Skip to content

[Backport 7.x] Added x-elastic-client-meta header #1377

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion docs/configuration.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -218,10 +218,15 @@ _Default:_ `null`
_Default:_ `{}`

|`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. +
_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`
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]
Expand Down
1 change: 1 addition & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ interface ClientOptions {
auth?: BasicAuth | ApiKeyAuth;
context?: Context;
proxy?: string | URL;
enableMetaHeader?: boolean;
cloud?: {
id: string;
// TODO: remove username and password here in 8
Expand Down
17 changes: 15 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ const Serializer = require('./lib/Serializer')
const errors = require('./lib/errors')
const { ConfigurationError } = errors
const { prepareHeaders } = Connection.internals
const clientVersion = require('./package.json').version
const nodeVersion = process.versions.node

const kInitialOptions = Symbol('elasticsearchjs-initial-options')
const kChild = Symbol('elasticsearchjs-child')
Expand Down Expand Up @@ -125,13 +127,18 @@ class Client extends ESAPI {
auth: null,
opaqueIdPrefix: null,
context: null,
proxy: null
proxy: null,
enableMetaHeader: true
}, opts)

this[kInitialOptions] = options
this[kExtensions] = []
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) {
this.serializer = options[kChild].serializer
this.connectionPool = options[kChild].connectionPool
Expand Down Expand Up @@ -179,7 +186,13 @@ class Client extends ESAPI {

/* istanbul ignore else */
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
})
}
}

Expand Down
11 changes: 9 additions & 2 deletions lib/Helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,14 @@ const { ResponseError, ConfigurationError } = require('./errors')
const pImmediate = promisify(setImmediate)
const sleep = promisify(setTimeout)
const kClient = Symbol('elasticsearch-client')
const kMetaHeader = Symbol('meta header')
/* istanbul ignore next */
const noop = () => {}

class Helpers {
constructor (opts) {
this[kClient] = opts.client
this[kMetaHeader] = opts.metaHeader
this.maxRetries = opts.maxRetries
}

Expand Down Expand Up @@ -71,6 +73,10 @@ class Helpers {
* @return {iterator} the async iterator
*/
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
const wait = options.wait || 5000
const maxRetries = options.maxRetries || this.maxRetries
Expand Down Expand Up @@ -99,7 +105,7 @@ class Helpers {
stop = true
await this[kClient].clearScroll(
{ body: { scroll_id } },
{ ignore: [400] }
{ ignore: [400], ...options }
)
}

Expand Down Expand Up @@ -414,6 +420,7 @@ class Helpers {
bulk (options) {
const client = this[kClient]
const { serialize, deserialize } = client.serializer
const reqOptions = this[kMetaHeader] !== null ? { headers: { 'x-elastic-client-meta': this[kMetaHeader] + ',h=bp' } } : {}
const {
datasource,
onDocument,
Expand Down Expand Up @@ -676,7 +683,7 @@ class Helpers {

function tryBulk (bulkBody, callback) {
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 (body.errors === false) {
stats.successful += body.items.length
Expand Down
1 change: 1 addition & 0 deletions lib/Transport.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class Transport {
if (typeof opts.compression === 'string' && opts.compression !== 'gzip') {
throw new ConfigurationError(`Invalid compression: '${opts.compression}'`)
}

this.emit = opts.emit
this.connectionPool = opts.connectionPool
this.serializer = opts.serializer
Expand Down
61 changes: 61 additions & 0 deletions test/unit/client.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ const intoStream = require('into-stream')
const { Client, ConnectionPool, Transport, Connection, errors } = require('../../index')
const { CloudConnectionPool } = require('../../lib/pool')
const { buildServer } = require('../utils')
const clientVersion = require('../../package.json').version
const nodeVersion = process.versions.node

test('Configure host', t => {
t.test('Single string', t => {
Expand Down Expand Up @@ -1300,3 +1302,62 @@ test('Content length too big (string)', t => {
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)
})
})
13 changes: 11 additions & 2 deletions test/unit/helpers/bulk.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ const semver = require('semver')
const { test } = require('tap')
const { Client, errors } = require('../../../')
const { buildServer, connection } = require('../../utils')
const clientVersion = require('../../../package.json').version
const nodeVersion = process.versions.node

const dataset = [
{ user: 'jon', age: 23 },
Expand All @@ -41,7 +43,10 @@ test('bulk index', t => {
const MockConnection = connection.buildMockConnection({
onRequest (params) {
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')
t.deepEqual(JSON.parse(action), { index: { _index: 'test' } })
t.deepEqual(JSON.parse(payload), dataset[count++])
Expand Down Expand Up @@ -84,6 +89,9 @@ test('bulk index', t => {
onRequest (params) {
t.strictEqual(params.path, '/_bulk')
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')
t.deepEqual(JSON.parse(action), { index: { _index: 'test' } })
t.deepEqual(JSON.parse(payload), dataset[count++])
Expand All @@ -93,7 +101,8 @@ test('bulk index', t => {

const client = new Client({
node: 'http://localhost:9200',
Connection: MockConnection
Connection: MockConnection,
enableMetaHeader: false
})
const result = await client.helpers.bulk({
datasource: dataset.slice(),
Expand Down
12 changes: 11 additions & 1 deletion test/unit/helpers/scroll.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,17 @@
const { test } = require('tap')
const { Client, errors } = require('../../../')
const { connection } = require('../../utils')
const clientVersion = require('../../../package.json').version
const nodeVersion = process.versions.node

test('Scroll search', async t => {
var count = 0
const MockConnection = connection.buildMockConnection({
onRequest (params) {
t.match(params.headers, {
'x-elastic-client-meta': `es=${clientVersion},js=${nodeVersion},t=${clientVersion},hc=${nodeVersion},h=s`
})

count += 1
if (params.method === 'POST') {
t.strictEqual(params.querystring, 'scroll=1m')
Expand Down Expand Up @@ -73,6 +79,9 @@ test('Clear a scroll search', async t => {
var count = 0
const MockConnection = connection.buildMockConnection({
onRequest (params) {
t.notMatch(params.headers, {
'x-elastic-client-meta': `es=${clientVersion},js=${nodeVersion},t=${clientVersion},hc=${nodeVersion},h=s`
})
if (params.method === 'DELETE') {
const body = JSON.parse(params.body)
t.strictEqual(body.scroll_id, 'id')
Expand All @@ -95,7 +104,8 @@ test('Clear a scroll search', async t => {

const client = new Client({
node: 'http://localhost:9200',
Connection: MockConnection
Connection: MockConnection,
enableMetaHeader: false
})

const scrollSearch = client.helpers.scrollSearch({
Expand Down