Skip to content

Commit 8b437a7

Browse files
delvedorgithub-actions[bot]
authored andcommitted
Added x-elastic-client-meta header (#1373)
1 parent 48762f1 commit 8b437a7

File tree

8 files changed

+115
-8
lines changed

8 files changed

+115
-8
lines changed

docs/configuration.asciidoc

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,10 +218,15 @@ _Default:_ `null`
218218
_Default:_ `{}`
219219

220220
|`context`
221-
|`object` - A custom object that you can use for observability in yoru events.
221+
|`object` - A custom object that you can use for observability in your events.
222222
It will be merged with the API level context option. +
223223
_Default:_ `null`
224224

225+
|`enableMetaHeader`
226+
|`boolean` - If true, adds an header named `'x-elastic-client-meta'`, containing some minimal telemetry data,
227+
such as the client and platform version. +
228+
_Default:_ `true`
229+
225230
|`cloud`
226231
a|`object` - Custom configuration for connecting to
227232
https://cloud.elastic.co[Elastic Cloud]. See https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/auth-reference.html[Authentication]

index.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ interface ClientOptions {
108108
auth?: BasicAuth | ApiKeyAuth;
109109
context?: Context;
110110
proxy?: string | URL;
111+
enableMetaHeader?: boolean;
111112
cloud?: {
112113
id: string;
113114
// TODO: remove username and password here in 8

index.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ const Serializer = require('./lib/Serializer')
3333
const errors = require('./lib/errors')
3434
const { ConfigurationError } = errors
3535
const { prepareHeaders } = Connection.internals
36+
const clientVersion = require('./package.json').version
37+
const nodeVersion = process.versions.node
3638

3739
const kInitialOptions = Symbol('elasticsearchjs-initial-options')
3840
const kChild = Symbol('elasticsearchjs-child')
@@ -125,13 +127,18 @@ class Client extends ESAPI {
125127
auth: null,
126128
opaqueIdPrefix: null,
127129
context: null,
128-
proxy: null
130+
proxy: null,
131+
enableMetaHeader: true
129132
}, opts)
130133

131134
this[kInitialOptions] = options
132135
this[kExtensions] = []
133136
this.name = options.name
134137

138+
if (options.enableMetaHeader) {
139+
options.headers['x-elastic-client-meta'] = `es=${clientVersion},js=${nodeVersion},t=${clientVersion},hc=${nodeVersion}`
140+
}
141+
135142
if (opts[kChild] !== undefined) {
136143
this.serializer = options[kChild].serializer
137144
this.connectionPool = options[kChild].connectionPool
@@ -179,7 +186,13 @@ class Client extends ESAPI {
179186

180187
/* istanbul ignore else */
181188
if (Helpers !== null) {
182-
this.helpers = new Helpers({ client: this, maxRetries: options.maxRetries })
189+
this.helpers = new Helpers({
190+
client: this,
191+
maxRetries: options.maxRetries,
192+
metaHeader: options.enableMetaHeader
193+
? `es=${clientVersion},js=${nodeVersion},t=${clientVersion},hc=${nodeVersion}`
194+
: null
195+
})
183196
}
184197
}
185198

lib/Helpers.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,14 @@ const { ResponseError, ConfigurationError } = require('./errors')
2828
const pImmediate = promisify(setImmediate)
2929
const sleep = promisify(setTimeout)
3030
const kClient = Symbol('elasticsearch-client')
31+
const kMetaHeader = Symbol('meta header')
3132
/* istanbul ignore next */
3233
const noop = () => {}
3334

3435
class Helpers {
3536
constructor (opts) {
3637
this[kClient] = opts.client
38+
this[kMetaHeader] = opts.metaHeader
3739
this.maxRetries = opts.maxRetries
3840
}
3941

@@ -71,6 +73,10 @@ class Helpers {
7173
* @return {iterator} the async iterator
7274
*/
7375
async * scrollSearch (params, options = {}) {
76+
if (this[kMetaHeader] !== null) {
77+
options.headers = options.headers || {}
78+
options.headers['x-elastic-client-meta'] = this[kMetaHeader] + ',h=s'
79+
}
7480
// TODO: study scroll search slices
7581
const wait = options.wait || 5000
7682
const maxRetries = options.maxRetries || this.maxRetries
@@ -99,7 +105,7 @@ class Helpers {
99105
stop = true
100106
await this[kClient].clearScroll(
101107
{ body: { scroll_id } },
102-
{ ignore: [400] }
108+
{ ignore: [400], ...options }
103109
)
104110
}
105111

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

677684
function tryBulk (bulkBody, callback) {
678685
if (shouldAbort === true) return callback(null, [])
679-
client.bulk(Object.assign({}, bulkOptions, { body: bulkBody }), (err, { body }) => {
686+
client.bulk(Object.assign({}, bulkOptions, { body: bulkBody }), reqOptions, (err, { body }) => {
680687
if (err) return callback(err, null)
681688
if (body.errors === false) {
682689
stats.successful += body.items.length

lib/Transport.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class Transport {
4444
if (typeof opts.compression === 'string' && opts.compression !== 'gzip') {
4545
throw new ConfigurationError(`Invalid compression: '${opts.compression}'`)
4646
}
47+
4748
this.emit = opts.emit
4849
this.connectionPool = opts.connectionPool
4950
this.serializer = opts.serializer

test/unit/client.test.js

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ const intoStream = require('into-stream')
2626
const { Client, ConnectionPool, Transport, Connection, errors } = require('../../index')
2727
const { CloudConnectionPool } = require('../../lib/pool')
2828
const { buildServer } = require('../utils')
29+
const clientVersion = require('../../package.json').version
30+
const nodeVersion = process.versions.node
2931

3032
test('Configure host', t => {
3133
t.test('Single string', t => {
@@ -1300,3 +1302,62 @@ test('Content length too big (string)', t => {
13001302
t.strictEqual(result.meta.attempts, 0)
13011303
})
13021304
})
1305+
1306+
test('Meta header enabled', t => {
1307+
t.plan(2)
1308+
1309+
class MockConnection extends Connection {
1310+
request (params, callback) {
1311+
t.match(params.headers, { 'x-elastic-client-meta': `es=${clientVersion},js=${nodeVersion},t=${clientVersion},hc=${nodeVersion}` })
1312+
const stream = intoStream(JSON.stringify({ hello: 'world' }))
1313+
stream.statusCode = 200
1314+
stream.headers = {
1315+
'content-type': 'application/json;utf=8',
1316+
'content-length': '17',
1317+
connection: 'keep-alive',
1318+
date: new Date().toISOString()
1319+
}
1320+
process.nextTick(callback, null, stream)
1321+
return { abort () {} }
1322+
}
1323+
}
1324+
1325+
const client = new Client({
1326+
node: 'http://localhost:9200',
1327+
Connection: MockConnection
1328+
})
1329+
1330+
client.info((err, result) => {
1331+
t.error(err)
1332+
})
1333+
})
1334+
1335+
test('Meta header disabled', t => {
1336+
t.plan(2)
1337+
1338+
class MockConnection extends Connection {
1339+
request (params, callback) {
1340+
t.notMatch(params.headers, { 'x-elastic-client-meta': `es=${clientVersion},js=${nodeVersion},t=${clientVersion},hc=${nodeVersion}` })
1341+
const stream = intoStream(JSON.stringify({ hello: 'world' }))
1342+
stream.statusCode = 200
1343+
stream.headers = {
1344+
'content-type': 'application/json;utf=8',
1345+
'content-length': '17',
1346+
connection: 'keep-alive',
1347+
date: new Date().toISOString()
1348+
}
1349+
process.nextTick(callback, null, stream)
1350+
return { abort () {} }
1351+
}
1352+
}
1353+
1354+
const client = new Client({
1355+
node: 'http://localhost:9200',
1356+
Connection: MockConnection,
1357+
enableMetaHeader: false
1358+
})
1359+
1360+
client.info((err, result) => {
1361+
t.error(err)
1362+
})
1363+
})

test/unit/helpers/bulk.test.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ const semver = require('semver')
2727
const { test } = require('tap')
2828
const { Client, errors } = require('../../../')
2929
const { buildServer, connection } = require('../../utils')
30+
const clientVersion = require('../../../package.json').version
31+
const nodeVersion = process.versions.node
3032

3133
const dataset = [
3234
{ user: 'jon', age: 23 },
@@ -41,7 +43,10 @@ test('bulk index', t => {
4143
const MockConnection = connection.buildMockConnection({
4244
onRequest (params) {
4345
t.strictEqual(params.path, '/_bulk')
44-
t.match(params.headers, { 'content-type': 'application/x-ndjson' })
46+
t.match(params.headers, {
47+
'content-type': 'application/x-ndjson',
48+
'x-elastic-client-meta': `es=${clientVersion},js=${nodeVersion},t=${clientVersion},hc=${nodeVersion},h=bp`
49+
})
4550
const [action, payload] = params.body.split('\n')
4651
t.deepEqual(JSON.parse(action), { index: { _index: 'test' } })
4752
t.deepEqual(JSON.parse(payload), dataset[count++])
@@ -84,6 +89,9 @@ test('bulk index', t => {
8489
onRequest (params) {
8590
t.strictEqual(params.path, '/_bulk')
8691
t.match(params.headers, { 'content-type': 'application/x-ndjson' })
92+
t.notMatch(params.headers, {
93+
'x-elastic-client-meta': `es=${clientVersion},js=${nodeVersion},t=${clientVersion},hc=${nodeVersion},h=bp`
94+
})
8795
const [action, payload] = params.body.split('\n')
8896
t.deepEqual(JSON.parse(action), { index: { _index: 'test' } })
8997
t.deepEqual(JSON.parse(payload), dataset[count++])
@@ -93,7 +101,8 @@ test('bulk index', t => {
93101

94102
const client = new Client({
95103
node: 'http://localhost:9200',
96-
Connection: MockConnection
104+
Connection: MockConnection,
105+
enableMetaHeader: false
97106
})
98107
const result = await client.helpers.bulk({
99108
datasource: dataset.slice(),

test/unit/helpers/scroll.test.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,17 @@
2222
const { test } = require('tap')
2323
const { Client, errors } = require('../../../')
2424
const { connection } = require('../../utils')
25+
const clientVersion = require('../../../package.json').version
26+
const nodeVersion = process.versions.node
2527

2628
test('Scroll search', async t => {
2729
var count = 0
2830
const MockConnection = connection.buildMockConnection({
2931
onRequest (params) {
32+
t.match(params.headers, {
33+
'x-elastic-client-meta': `es=${clientVersion},js=${nodeVersion},t=${clientVersion},hc=${nodeVersion},h=s`
34+
})
35+
3036
count += 1
3137
if (params.method === 'POST') {
3238
t.strictEqual(params.querystring, 'scroll=1m')
@@ -73,6 +79,9 @@ test('Clear a scroll search', async t => {
7379
var count = 0
7480
const MockConnection = connection.buildMockConnection({
7581
onRequest (params) {
82+
t.notMatch(params.headers, {
83+
'x-elastic-client-meta': `es=${clientVersion},js=${nodeVersion},t=${clientVersion},hc=${nodeVersion},h=s`
84+
})
7685
if (params.method === 'DELETE') {
7786
const body = JSON.parse(params.body)
7887
t.strictEqual(body.scroll_id, 'id')
@@ -95,7 +104,8 @@ test('Clear a scroll search', async t => {
95104

96105
const client = new Client({
97106
node: 'http://localhost:9200',
98-
Connection: MockConnection
107+
Connection: MockConnection,
108+
enableMetaHeader: false
99109
})
100110

101111
const scrollSearch = client.helpers.scrollSearch({

0 commit comments

Comments
 (0)