Added x-elastic-client-meta header (#1373)
This commit is contained in:
committed by
GitHub
parent
4cace4c234
commit
61eee69424
@ -218,10 +218,15 @@ _Default:_ `null`
|
|||||||
_Default:_ `{}`
|
_Default:_ `{}`
|
||||||
|
|
||||||
|`context`
|
|`context`
|
||||||
|`object` - A custom object that you can use for observability in yoru events.
|
|`object` - A custom object that you can use for observability in your events.
|
||||||
It will be merged with the API level context option. +
|
It will be merged with the API level context option. +
|
||||||
_Default:_ `null`
|
_Default:_ `null`
|
||||||
|
|
||||||
|
|`enableMetaHeader`
|
||||||
|
|`boolean` - If true, adds an header named `'x-elastic-client-meta'`, containing some minimal telemetry data,
|
||||||
|
such as the client and platform version. +
|
||||||
|
_Default:_ `true`
|
||||||
|
|
||||||
|`cloud`
|
|`cloud`
|
||||||
a|`object` - Custom configuration for connecting to
|
a|`object` - Custom configuration for connecting to
|
||||||
https://cloud.elastic.co[Elastic Cloud]. See https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/auth-reference.html[Authentication]
|
https://cloud.elastic.co[Elastic Cloud]. See https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/auth-reference.html[Authentication]
|
||||||
|
|||||||
1
index.d.ts
vendored
1
index.d.ts
vendored
@ -108,6 +108,7 @@ interface ClientOptions {
|
|||||||
auth?: BasicAuth | ApiKeyAuth;
|
auth?: BasicAuth | ApiKeyAuth;
|
||||||
context?: Context;
|
context?: Context;
|
||||||
proxy?: string | URL;
|
proxy?: string | URL;
|
||||||
|
enableMetaHeader?: boolean;
|
||||||
cloud?: {
|
cloud?: {
|
||||||
id: string;
|
id: string;
|
||||||
// TODO: remove username and password here in 8
|
// TODO: remove username and password here in 8
|
||||||
|
|||||||
17
index.js
17
index.js
@ -33,6 +33,8 @@ const Serializer = require('./lib/Serializer')
|
|||||||
const errors = require('./lib/errors')
|
const errors = require('./lib/errors')
|
||||||
const { ConfigurationError } = errors
|
const { ConfigurationError } = errors
|
||||||
const { prepareHeaders } = Connection.internals
|
const { prepareHeaders } = Connection.internals
|
||||||
|
const clientVersion = require('./package.json').version
|
||||||
|
const nodeVersion = process.versions.node
|
||||||
|
|
||||||
const kInitialOptions = Symbol('elasticsearchjs-initial-options')
|
const kInitialOptions = Symbol('elasticsearchjs-initial-options')
|
||||||
const kChild = Symbol('elasticsearchjs-child')
|
const kChild = Symbol('elasticsearchjs-child')
|
||||||
@ -125,13 +127,18 @@ class Client extends ESAPI {
|
|||||||
auth: null,
|
auth: null,
|
||||||
opaqueIdPrefix: null,
|
opaqueIdPrefix: null,
|
||||||
context: null,
|
context: null,
|
||||||
proxy: null
|
proxy: null,
|
||||||
|
enableMetaHeader: true
|
||||||
}, opts)
|
}, opts)
|
||||||
|
|
||||||
this[kInitialOptions] = options
|
this[kInitialOptions] = options
|
||||||
this[kExtensions] = []
|
this[kExtensions] = []
|
||||||
this.name = options.name
|
this.name = options.name
|
||||||
|
|
||||||
|
if (options.enableMetaHeader) {
|
||||||
|
options.headers['x-elastic-client-meta'] = `es=${clientVersion},js=${nodeVersion},t=${clientVersion},hc=${nodeVersion}`
|
||||||
|
}
|
||||||
|
|
||||||
if (opts[kChild] !== undefined) {
|
if (opts[kChild] !== undefined) {
|
||||||
this.serializer = options[kChild].serializer
|
this.serializer = options[kChild].serializer
|
||||||
this.connectionPool = options[kChild].connectionPool
|
this.connectionPool = options[kChild].connectionPool
|
||||||
@ -179,7 +186,13 @@ class Client extends ESAPI {
|
|||||||
|
|
||||||
/* istanbul ignore else */
|
/* istanbul ignore else */
|
||||||
if (Helpers !== null) {
|
if (Helpers !== null) {
|
||||||
this.helpers = new Helpers({ client: this, maxRetries: options.maxRetries })
|
this.helpers = new Helpers({
|
||||||
|
client: this,
|
||||||
|
maxRetries: options.maxRetries,
|
||||||
|
metaHeader: options.enableMetaHeader
|
||||||
|
? `es=${clientVersion},js=${nodeVersion},t=${clientVersion},hc=${nodeVersion}`
|
||||||
|
: null
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -28,12 +28,14 @@ const { ResponseError, ConfigurationError } = require('./errors')
|
|||||||
const pImmediate = promisify(setImmediate)
|
const pImmediate = promisify(setImmediate)
|
||||||
const sleep = promisify(setTimeout)
|
const sleep = promisify(setTimeout)
|
||||||
const kClient = Symbol('elasticsearch-client')
|
const kClient = Symbol('elasticsearch-client')
|
||||||
|
const kMetaHeader = Symbol('meta header')
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
const noop = () => {}
|
const noop = () => {}
|
||||||
|
|
||||||
class Helpers {
|
class Helpers {
|
||||||
constructor (opts) {
|
constructor (opts) {
|
||||||
this[kClient] = opts.client
|
this[kClient] = opts.client
|
||||||
|
this[kMetaHeader] = opts.metaHeader
|
||||||
this.maxRetries = opts.maxRetries
|
this.maxRetries = opts.maxRetries
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,6 +73,10 @@ class Helpers {
|
|||||||
* @return {iterator} the async iterator
|
* @return {iterator} the async iterator
|
||||||
*/
|
*/
|
||||||
async * scrollSearch (params, options = {}) {
|
async * scrollSearch (params, options = {}) {
|
||||||
|
if (this[kMetaHeader] !== null) {
|
||||||
|
options.headers = options.headers || {}
|
||||||
|
options.headers['x-elastic-client-meta'] = this[kMetaHeader] + ',h=s'
|
||||||
|
}
|
||||||
// TODO: study scroll search slices
|
// TODO: study scroll search slices
|
||||||
const wait = options.wait || 5000
|
const wait = options.wait || 5000
|
||||||
const maxRetries = options.maxRetries || this.maxRetries
|
const maxRetries = options.maxRetries || this.maxRetries
|
||||||
@ -99,7 +105,7 @@ class Helpers {
|
|||||||
stop = true
|
stop = true
|
||||||
await this[kClient].clearScroll(
|
await this[kClient].clearScroll(
|
||||||
{ body: { scroll_id } },
|
{ body: { scroll_id } },
|
||||||
{ ignore: [400] }
|
{ ignore: [400], ...options }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -414,6 +420,7 @@ class Helpers {
|
|||||||
bulk (options) {
|
bulk (options) {
|
||||||
const client = this[kClient]
|
const client = this[kClient]
|
||||||
const { serialize, deserialize } = client.serializer
|
const { serialize, deserialize } = client.serializer
|
||||||
|
const reqOptions = this[kMetaHeader] !== null ? { headers: { 'x-elastic-client-meta': this[kMetaHeader] + ',h=bp' } } : {}
|
||||||
const {
|
const {
|
||||||
datasource,
|
datasource,
|
||||||
onDocument,
|
onDocument,
|
||||||
@ -676,7 +683,7 @@ class Helpers {
|
|||||||
|
|
||||||
function tryBulk (bulkBody, callback) {
|
function tryBulk (bulkBody, callback) {
|
||||||
if (shouldAbort === true) return callback(null, [])
|
if (shouldAbort === true) return callback(null, [])
|
||||||
client.bulk(Object.assign({}, bulkOptions, { body: bulkBody }), (err, { body }) => {
|
client.bulk(Object.assign({}, bulkOptions, { body: bulkBody }), reqOptions, (err, { body }) => {
|
||||||
if (err) return callback(err, null)
|
if (err) return callback(err, null)
|
||||||
if (body.errors === false) {
|
if (body.errors === false) {
|
||||||
stats.successful += body.items.length
|
stats.successful += body.items.length
|
||||||
|
|||||||
@ -44,6 +44,7 @@ class Transport {
|
|||||||
if (typeof opts.compression === 'string' && opts.compression !== 'gzip') {
|
if (typeof opts.compression === 'string' && opts.compression !== 'gzip') {
|
||||||
throw new ConfigurationError(`Invalid compression: '${opts.compression}'`)
|
throw new ConfigurationError(`Invalid compression: '${opts.compression}'`)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.emit = opts.emit
|
this.emit = opts.emit
|
||||||
this.connectionPool = opts.connectionPool
|
this.connectionPool = opts.connectionPool
|
||||||
this.serializer = opts.serializer
|
this.serializer = opts.serializer
|
||||||
|
|||||||
@ -26,6 +26,8 @@ const intoStream = require('into-stream')
|
|||||||
const { Client, ConnectionPool, Transport, Connection, errors } = require('../../index')
|
const { Client, ConnectionPool, Transport, Connection, errors } = require('../../index')
|
||||||
const { CloudConnectionPool } = require('../../lib/pool')
|
const { CloudConnectionPool } = require('../../lib/pool')
|
||||||
const { buildServer } = require('../utils')
|
const { buildServer } = require('../utils')
|
||||||
|
const clientVersion = require('../../package.json').version
|
||||||
|
const nodeVersion = process.versions.node
|
||||||
|
|
||||||
test('Configure host', t => {
|
test('Configure host', t => {
|
||||||
t.test('Single string', t => {
|
t.test('Single string', t => {
|
||||||
@ -1300,3 +1302,62 @@ test('Content length too big (string)', t => {
|
|||||||
t.strictEqual(result.meta.attempts, 0)
|
t.strictEqual(result.meta.attempts, 0)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('Meta header enabled', t => {
|
||||||
|
t.plan(2)
|
||||||
|
|
||||||
|
class MockConnection extends Connection {
|
||||||
|
request (params, callback) {
|
||||||
|
t.match(params.headers, { 'x-elastic-client-meta': `es=${clientVersion},js=${nodeVersion},t=${clientVersion},hc=${nodeVersion}` })
|
||||||
|
const stream = intoStream(JSON.stringify({ hello: 'world' }))
|
||||||
|
stream.statusCode = 200
|
||||||
|
stream.headers = {
|
||||||
|
'content-type': 'application/json;utf=8',
|
||||||
|
'content-length': '17',
|
||||||
|
connection: 'keep-alive',
|
||||||
|
date: new Date().toISOString()
|
||||||
|
}
|
||||||
|
process.nextTick(callback, null, stream)
|
||||||
|
return { abort () {} }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const client = new Client({
|
||||||
|
node: 'http://localhost:9200',
|
||||||
|
Connection: MockConnection
|
||||||
|
})
|
||||||
|
|
||||||
|
client.info((err, result) => {
|
||||||
|
t.error(err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('Meta header disabled', t => {
|
||||||
|
t.plan(2)
|
||||||
|
|
||||||
|
class MockConnection extends Connection {
|
||||||
|
request (params, callback) {
|
||||||
|
t.notMatch(params.headers, { 'x-elastic-client-meta': `es=${clientVersion},js=${nodeVersion},t=${clientVersion},hc=${nodeVersion}` })
|
||||||
|
const stream = intoStream(JSON.stringify({ hello: 'world' }))
|
||||||
|
stream.statusCode = 200
|
||||||
|
stream.headers = {
|
||||||
|
'content-type': 'application/json;utf=8',
|
||||||
|
'content-length': '17',
|
||||||
|
connection: 'keep-alive',
|
||||||
|
date: new Date().toISOString()
|
||||||
|
}
|
||||||
|
process.nextTick(callback, null, stream)
|
||||||
|
return { abort () {} }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const client = new Client({
|
||||||
|
node: 'http://localhost:9200',
|
||||||
|
Connection: MockConnection,
|
||||||
|
enableMetaHeader: false
|
||||||
|
})
|
||||||
|
|
||||||
|
client.info((err, result) => {
|
||||||
|
t.error(err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|||||||
@ -27,6 +27,8 @@ const semver = require('semver')
|
|||||||
const { test } = require('tap')
|
const { test } = require('tap')
|
||||||
const { Client, errors } = require('../../../')
|
const { Client, errors } = require('../../../')
|
||||||
const { buildServer, connection } = require('../../utils')
|
const { buildServer, connection } = require('../../utils')
|
||||||
|
const clientVersion = require('../../../package.json').version
|
||||||
|
const nodeVersion = process.versions.node
|
||||||
|
|
||||||
const dataset = [
|
const dataset = [
|
||||||
{ user: 'jon', age: 23 },
|
{ user: 'jon', age: 23 },
|
||||||
@ -41,7 +43,10 @@ test('bulk index', t => {
|
|||||||
const MockConnection = connection.buildMockConnection({
|
const MockConnection = connection.buildMockConnection({
|
||||||
onRequest (params) {
|
onRequest (params) {
|
||||||
t.strictEqual(params.path, '/_bulk')
|
t.strictEqual(params.path, '/_bulk')
|
||||||
t.match(params.headers, { 'content-type': 'application/x-ndjson' })
|
t.match(params.headers, {
|
||||||
|
'content-type': 'application/x-ndjson',
|
||||||
|
'x-elastic-client-meta': `es=${clientVersion},js=${nodeVersion},t=${clientVersion},hc=${nodeVersion},h=bp`
|
||||||
|
})
|
||||||
const [action, payload] = params.body.split('\n')
|
const [action, payload] = params.body.split('\n')
|
||||||
t.deepEqual(JSON.parse(action), { index: { _index: 'test' } })
|
t.deepEqual(JSON.parse(action), { index: { _index: 'test' } })
|
||||||
t.deepEqual(JSON.parse(payload), dataset[count++])
|
t.deepEqual(JSON.parse(payload), dataset[count++])
|
||||||
@ -84,6 +89,9 @@ test('bulk index', t => {
|
|||||||
onRequest (params) {
|
onRequest (params) {
|
||||||
t.strictEqual(params.path, '/_bulk')
|
t.strictEqual(params.path, '/_bulk')
|
||||||
t.match(params.headers, { 'content-type': 'application/x-ndjson' })
|
t.match(params.headers, { 'content-type': 'application/x-ndjson' })
|
||||||
|
t.notMatch(params.headers, {
|
||||||
|
'x-elastic-client-meta': `es=${clientVersion},js=${nodeVersion},t=${clientVersion},hc=${nodeVersion},h=bp`
|
||||||
|
})
|
||||||
const [action, payload] = params.body.split('\n')
|
const [action, payload] = params.body.split('\n')
|
||||||
t.deepEqual(JSON.parse(action), { index: { _index: 'test' } })
|
t.deepEqual(JSON.parse(action), { index: { _index: 'test' } })
|
||||||
t.deepEqual(JSON.parse(payload), dataset[count++])
|
t.deepEqual(JSON.parse(payload), dataset[count++])
|
||||||
@ -93,7 +101,8 @@ test('bulk index', t => {
|
|||||||
|
|
||||||
const client = new Client({
|
const client = new Client({
|
||||||
node: 'http://localhost:9200',
|
node: 'http://localhost:9200',
|
||||||
Connection: MockConnection
|
Connection: MockConnection,
|
||||||
|
enableMetaHeader: false
|
||||||
})
|
})
|
||||||
const result = await client.helpers.bulk({
|
const result = await client.helpers.bulk({
|
||||||
datasource: dataset.slice(),
|
datasource: dataset.slice(),
|
||||||
|
|||||||
@ -22,11 +22,17 @@
|
|||||||
const { test } = require('tap')
|
const { test } = require('tap')
|
||||||
const { Client, errors } = require('../../../')
|
const { Client, errors } = require('../../../')
|
||||||
const { connection } = require('../../utils')
|
const { connection } = require('../../utils')
|
||||||
|
const clientVersion = require('../../../package.json').version
|
||||||
|
const nodeVersion = process.versions.node
|
||||||
|
|
||||||
test('Scroll search', async t => {
|
test('Scroll search', async t => {
|
||||||
var count = 0
|
var count = 0
|
||||||
const MockConnection = connection.buildMockConnection({
|
const MockConnection = connection.buildMockConnection({
|
||||||
onRequest (params) {
|
onRequest (params) {
|
||||||
|
t.match(params.headers, {
|
||||||
|
'x-elastic-client-meta': `es=${clientVersion},js=${nodeVersion},t=${clientVersion},hc=${nodeVersion},h=s`
|
||||||
|
})
|
||||||
|
|
||||||
count += 1
|
count += 1
|
||||||
if (params.method === 'POST') {
|
if (params.method === 'POST') {
|
||||||
t.strictEqual(params.querystring, 'scroll=1m')
|
t.strictEqual(params.querystring, 'scroll=1m')
|
||||||
@ -73,6 +79,9 @@ test('Clear a scroll search', async t => {
|
|||||||
var count = 0
|
var count = 0
|
||||||
const MockConnection = connection.buildMockConnection({
|
const MockConnection = connection.buildMockConnection({
|
||||||
onRequest (params) {
|
onRequest (params) {
|
||||||
|
t.notMatch(params.headers, {
|
||||||
|
'x-elastic-client-meta': `es=${clientVersion},js=${nodeVersion},t=${clientVersion},hc=${nodeVersion},h=s`
|
||||||
|
})
|
||||||
if (params.method === 'DELETE') {
|
if (params.method === 'DELETE') {
|
||||||
const body = JSON.parse(params.body)
|
const body = JSON.parse(params.body)
|
||||||
t.strictEqual(body.scroll_id, 'id')
|
t.strictEqual(body.scroll_id, 'id')
|
||||||
@ -95,7 +104,8 @@ test('Clear a scroll search', async t => {
|
|||||||
|
|
||||||
const client = new Client({
|
const client = new Client({
|
||||||
node: 'http://localhost:9200',
|
node: 'http://localhost:9200',
|
||||||
Connection: MockConnection
|
Connection: MockConnection,
|
||||||
|
enableMetaHeader: false
|
||||||
})
|
})
|
||||||
|
|
||||||
const scrollSearch = client.helpers.scrollSearch({
|
const scrollSearch = client.helpers.scrollSearch({
|
||||||
|
|||||||
Reference in New Issue
Block a user