X-Opaque-Id support (#997)
* Added X-Opaque-Id support * Updated type definitions * Updated test * Updated docs
This commit is contained in:
committed by
delvedor
parent
3e2a823a72
commit
df76154388
@ -173,6 +173,11 @@ function generateRequestId (params, options) {
|
|||||||
|`string` - The name to identify the client instance in the events. +
|
|`string` - The name to identify the client instance in the events. +
|
||||||
_Default:_ `elasticsearch-js`
|
_Default:_ `elasticsearch-js`
|
||||||
|
|
||||||
|
|`opaqueIdPrefix`
|
||||||
|
|`string` - A string that will be use to prefix any `X-Opaque-Id` header. +
|
||||||
|
See https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/observability.html#_x-opaque-id_support[`X-Opaque-Id` support] for more details. +
|
||||||
|
_Default:_ `null`
|
||||||
|
|
||||||
|`headers`
|
|`headers`
|
||||||
|`object` - A set of custom headers to send in every request. +
|
|`object` - A set of custom headers to send in every request. +
|
||||||
_Default:_ `{}`
|
_Default:_ `{}`
|
||||||
|
|||||||
@ -248,3 +248,46 @@ child.search({
|
|||||||
if (err) console.log(err)
|
if (err) console.log(err)
|
||||||
})
|
})
|
||||||
----
|
----
|
||||||
|
|
||||||
|
=== X-Opaque-Id support
|
||||||
|
To improve the overall observability, the client offers an easy way to configure the `X-Opaque-Id` header. If you set the `X-Opaque-Id` in a specific request, this will allow you to discover this identifier in the https://www.elastic.co/guide/en/elasticsearch/reference/master/logging.html#deprecation-logging[deprecation logs], help you with https://www.elastic.co/guide/en/elasticsearch/reference/master/index-modules-slowlog.html#_identifying_search_slow_log_origin[identifying search slow log origin] as well as https://www.elastic.co/guide/en/elasticsearch/reference/master/tasks.html#_identifying_running_tasks[identifying running tasks].
|
||||||
|
|
||||||
|
The `X-Opaque-Id` should be configured in each request, for doing that you can use the `opaqueId` option, as you can see in the following example. +
|
||||||
|
The resulting header will be `{ 'X-Opaque-Id': 'my-search' }`.
|
||||||
|
|
||||||
|
[source,js]
|
||||||
|
----
|
||||||
|
const { Client } = require('@elastic/elasticsearch')
|
||||||
|
const client = new Client({
|
||||||
|
node: 'http://localhost:9200'
|
||||||
|
})
|
||||||
|
|
||||||
|
client.search({
|
||||||
|
index: 'my-index',
|
||||||
|
body: { foo: 'bar' }
|
||||||
|
}, {
|
||||||
|
opaqueId: 'my-search'
|
||||||
|
}, (err, result) => {
|
||||||
|
if (err) console.log(err)
|
||||||
|
})
|
||||||
|
----
|
||||||
|
|
||||||
|
Sometimes it may be useful to prefix all the `X-Opaque-Id` headers with a specific string, in case you need to identify a specific client or server. For doing this, the client offers a top-level configuration option: `opaqueIdPrefix`. +
|
||||||
|
In the following example, the resulting header will be `{ 'X-Opaque-Id': 'proxy-client::my-search' }`.
|
||||||
|
[source,js]
|
||||||
|
----
|
||||||
|
const { Client } = require('@elastic/elasticsearch')
|
||||||
|
const client = new Client({
|
||||||
|
node: 'http://localhost:9200',
|
||||||
|
opaqueIdPrefix: 'proxy-client::'
|
||||||
|
})
|
||||||
|
|
||||||
|
client.search({
|
||||||
|
index: 'my-index',
|
||||||
|
body: { foo: 'bar' }
|
||||||
|
}, {
|
||||||
|
opaqueId: 'my-search'
|
||||||
|
}, (err, result) => {
|
||||||
|
if (err) console.log(err)
|
||||||
|
})
|
||||||
|
----
|
||||||
|
|||||||
1
index.d.ts
vendored
1
index.d.ts
vendored
@ -94,6 +94,7 @@ interface ClientOptions {
|
|||||||
nodeFilter?: nodeFilterFn;
|
nodeFilter?: nodeFilterFn;
|
||||||
nodeSelector?: nodeSelectorFn | string;
|
nodeSelector?: nodeSelectorFn | string;
|
||||||
headers?: anyObject;
|
headers?: anyObject;
|
||||||
|
opaqueIdPrefix?: string;
|
||||||
generateRequestId?: generateRequestIdFn;
|
generateRequestId?: generateRequestIdFn;
|
||||||
name?: string;
|
name?: string;
|
||||||
auth?: BasicAuth | ApiKeyAuth;
|
auth?: BasicAuth | ApiKeyAuth;
|
||||||
|
|||||||
6
index.js
6
index.js
@ -79,7 +79,8 @@ class Client extends EventEmitter {
|
|||||||
nodeSelector: 'round-robin',
|
nodeSelector: 'round-robin',
|
||||||
generateRequestId: null,
|
generateRequestId: null,
|
||||||
name: 'elasticsearch-js',
|
name: 'elasticsearch-js',
|
||||||
auth: null
|
auth: null,
|
||||||
|
opaqueIdPrefix: null
|
||||||
}, opts)
|
}, opts)
|
||||||
|
|
||||||
this[kInitialOptions] = options
|
this[kInitialOptions] = options
|
||||||
@ -121,7 +122,8 @@ class Client extends EventEmitter {
|
|||||||
nodeFilter: options.nodeFilter,
|
nodeFilter: options.nodeFilter,
|
||||||
nodeSelector: options.nodeSelector,
|
nodeSelector: options.nodeSelector,
|
||||||
generateRequestId: options.generateRequestId,
|
generateRequestId: options.generateRequestId,
|
||||||
name: options.name
|
name: options.name,
|
||||||
|
opaqueIdPrefix: options.opaqueIdPrefix
|
||||||
})
|
})
|
||||||
|
|
||||||
const apis = buildApi({
|
const apis = buildApi({
|
||||||
|
|||||||
3
lib/Transport.d.ts
vendored
3
lib/Transport.d.ts
vendored
@ -38,6 +38,7 @@ interface TransportOptions {
|
|||||||
headers?: anyObject;
|
headers?: anyObject;
|
||||||
generateRequestId?: generateRequestIdFn;
|
generateRequestId?: generateRequestIdFn;
|
||||||
name: string;
|
name: string;
|
||||||
|
opaqueIdPrefix?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RequestEvent<T = any, C = any> {
|
export interface RequestEvent<T = any, C = any> {
|
||||||
@ -90,6 +91,7 @@ export interface TransportRequestOptions {
|
|||||||
id?: any;
|
id?: any;
|
||||||
context?: any;
|
context?: any;
|
||||||
warnings?: [string];
|
warnings?: [string];
|
||||||
|
opaqueId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TransportRequestCallback {
|
export interface TransportRequestCallback {
|
||||||
@ -121,6 +123,7 @@ export default class Transport {
|
|||||||
compression: 'gzip' | false;
|
compression: 'gzip' | false;
|
||||||
sniffInterval: number;
|
sniffInterval: number;
|
||||||
sniffOnConnectionFault: boolean;
|
sniffOnConnectionFault: boolean;
|
||||||
|
opaqueIdPrefix: string | null;
|
||||||
sniffEndpoint: string;
|
sniffEndpoint: string;
|
||||||
_sniffEnabled: boolean;
|
_sniffEnabled: boolean;
|
||||||
_nextSniff: number;
|
_nextSniff: number;
|
||||||
|
|||||||
@ -41,6 +41,7 @@ class Transport {
|
|||||||
this.sniffEndpoint = opts.sniffEndpoint
|
this.sniffEndpoint = opts.sniffEndpoint
|
||||||
this.generateRequestId = opts.generateRequestId || generateRequestId()
|
this.generateRequestId = opts.generateRequestId || generateRequestId()
|
||||||
this.name = opts.name
|
this.name = opts.name
|
||||||
|
this.opaqueIdPrefix = opts.opaqueIdPrefix
|
||||||
|
|
||||||
this.nodeFilter = opts.nodeFilter || defaultNodeFilter
|
this.nodeFilter = opts.nodeFilter || defaultNodeFilter
|
||||||
if (typeof opts.nodeSelector === 'function') {
|
if (typeof opts.nodeSelector === 'function') {
|
||||||
@ -114,6 +115,12 @@ class Transport {
|
|||||||
// TODO: make this assignment FAST
|
// TODO: make this assignment FAST
|
||||||
const headers = Object.assign({}, this.headers, options.headers)
|
const headers = Object.assign({}, this.headers, options.headers)
|
||||||
|
|
||||||
|
if (options.opaqueId !== undefined) {
|
||||||
|
headers['X-Opaque-Id'] = this.opaqueIdPrefix !== null
|
||||||
|
? this.opaqueIdPrefix + options.opaqueId
|
||||||
|
: options.opaqueId
|
||||||
|
}
|
||||||
|
|
||||||
// handle json body
|
// handle json body
|
||||||
if (params.body != null) {
|
if (params.body != null) {
|
||||||
if (shouldSerialize(params.body) === true) {
|
if (shouldSerialize(params.body) === true) {
|
||||||
|
|||||||
@ -851,3 +851,87 @@ test('Elastic cloud config', t => {
|
|||||||
|
|
||||||
t.end()
|
t.end()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('Opaque Id support', t => {
|
||||||
|
t.test('No opaqueId', t => {
|
||||||
|
t.plan(3)
|
||||||
|
|
||||||
|
function handler (req, res) {
|
||||||
|
t.strictEqual(req.headers['x-opaque-id'], undefined)
|
||||||
|
res.setHeader('Content-Type', 'application/json;utf=8')
|
||||||
|
res.end(JSON.stringify({ hello: 'world' }))
|
||||||
|
}
|
||||||
|
|
||||||
|
buildServer(handler, ({ port }, server) => {
|
||||||
|
const client = new Client({
|
||||||
|
node: `http://localhost:${port}`
|
||||||
|
})
|
||||||
|
|
||||||
|
client.search({
|
||||||
|
index: 'test',
|
||||||
|
q: 'foo:bar'
|
||||||
|
}, (err, { body }) => {
|
||||||
|
t.error(err)
|
||||||
|
t.deepEqual(body, { hello: 'world' })
|
||||||
|
server.stop()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('No prefix', t => {
|
||||||
|
t.plan(3)
|
||||||
|
|
||||||
|
function handler (req, res) {
|
||||||
|
t.strictEqual(req.headers['x-opaque-id'], 'bar')
|
||||||
|
res.setHeader('Content-Type', 'application/json;utf=8')
|
||||||
|
res.end(JSON.stringify({ hello: 'world' }))
|
||||||
|
}
|
||||||
|
|
||||||
|
buildServer(handler, ({ port }, server) => {
|
||||||
|
const client = new Client({
|
||||||
|
node: `http://localhost:${port}`
|
||||||
|
})
|
||||||
|
|
||||||
|
client.search({
|
||||||
|
index: 'test',
|
||||||
|
q: 'foo:bar'
|
||||||
|
}, {
|
||||||
|
opaqueId: 'bar'
|
||||||
|
}, (err, { body }) => {
|
||||||
|
t.error(err)
|
||||||
|
t.deepEqual(body, { hello: 'world' })
|
||||||
|
server.stop()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('With prefix', t => {
|
||||||
|
t.plan(3)
|
||||||
|
|
||||||
|
function handler (req, res) {
|
||||||
|
t.strictEqual(req.headers['x-opaque-id'], 'foo-bar')
|
||||||
|
res.setHeader('Content-Type', 'application/json;utf=8')
|
||||||
|
res.end(JSON.stringify({ hello: 'world' }))
|
||||||
|
}
|
||||||
|
|
||||||
|
buildServer(handler, ({ port }, server) => {
|
||||||
|
const client = new Client({
|
||||||
|
node: `http://localhost:${port}`,
|
||||||
|
opaqueIdPrefix: 'foo-'
|
||||||
|
})
|
||||||
|
|
||||||
|
client.search({
|
||||||
|
index: 'test',
|
||||||
|
q: 'foo:bar'
|
||||||
|
}, {
|
||||||
|
opaqueId: 'bar'
|
||||||
|
}, (err, { body }) => {
|
||||||
|
t.error(err)
|
||||||
|
t.deepEqual(body, { hello: 'world' })
|
||||||
|
server.stop()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user