340 lines
7.7 KiB
Plaintext
340 lines
7.7 KiB
Plaintext
[[observability]]
|
|
== Observability
|
|
|
|
The client does not provide a default logger, but instead it offers an event
|
|
emitter interfaces to hook into internal events, such as `request` and
|
|
`response`.
|
|
|
|
Correlating those events can be quite hard, especially if your applications have
|
|
a large codebase with many events happening at the same time.
|
|
|
|
To help you with this, the client offers you a correlation id system and other
|
|
features. Let's see them in action.
|
|
|
|
=== Events
|
|
|
|
The client is an event emitter, this means that you can listen for its event and
|
|
add additional logic to your code, without need to change the client internals
|
|
or your normal usage. You can find the events names by access the `events` key
|
|
of the client.
|
|
|
|
[source,js]
|
|
----
|
|
const { events } = require('@elastic/elasticsearch')
|
|
console.log(events)
|
|
----
|
|
|
|
|
|
The event emitter functionality can be useful if you want to log every request,
|
|
response and error that is happening during the use of the client.
|
|
|
|
[source,js]
|
|
----
|
|
const logger = require('my-logger')()
|
|
const { Client } = require('@elastic/elasticsearch')
|
|
const client = new Client({ node: 'http://localhost:9200' })
|
|
|
|
client.on('response', (err, result) => {
|
|
if (err) {
|
|
logger.error(err)
|
|
} else {
|
|
logger.info(result)
|
|
}
|
|
})
|
|
----
|
|
|
|
|
|
The client emits the following events:
|
|
[cols=2*]
|
|
|===
|
|
|`request`
|
|
a|Emitted before sending the actual request to {es} _(emitted multiple times in case of retries)_.
|
|
[source,js]
|
|
----
|
|
client.on('request', (err, result) => {
|
|
console.log(err, result)
|
|
})
|
|
----
|
|
|
|
|`response`
|
|
a|Emitted once {es} response has been received and parsed.
|
|
[source,js]
|
|
----
|
|
client.on('response', (err, result) => {
|
|
console.log(err, result)
|
|
})
|
|
----
|
|
|
|
|`sniff`
|
|
a|Emitted when the client ends a sniffing request.
|
|
[source,js]
|
|
----
|
|
client.on('sniff', (err, result) => {
|
|
console.log(err, result)
|
|
})
|
|
----
|
|
|
|
|`resurrect`
|
|
a|Emitted if the client is able to resurrect a dead node.
|
|
[source,js]
|
|
----
|
|
client.on('resurrect', (err, result) => {
|
|
console.log(err, result)
|
|
})
|
|
----
|
|
|
|
|===
|
|
|
|
The values of `result` in `request`, `response` and `sniff` will be:
|
|
|
|
[source,ts]
|
|
----
|
|
body: any;
|
|
statusCode: number | null;
|
|
headers: anyObject | null;
|
|
warnings: string[] | null;
|
|
meta: {
|
|
context: any;
|
|
name: string;
|
|
request: {
|
|
params: TransportRequestParams;
|
|
options: TransportRequestOptions;
|
|
id: any;
|
|
};
|
|
connection: Connection;
|
|
attempts: number;
|
|
aborted: boolean;
|
|
sniff?: {
|
|
hosts: any[];
|
|
reason: string;
|
|
};
|
|
};
|
|
----
|
|
|
|
|
|
While the `result` value in `resurrect` will be:
|
|
|
|
[source,ts]
|
|
----
|
|
strategy: string;
|
|
isAlive: boolean;
|
|
connection: Connection;
|
|
name: string;
|
|
request: {
|
|
id: any;
|
|
};
|
|
----
|
|
|
|
|
|
=== Correlation id
|
|
|
|
Correlating events can be quite hard, especially if there are many events at the
|
|
same time. The client offers you an automatic (and configurable) system to help
|
|
you handle this problem.
|
|
|
|
[source,js]
|
|
----
|
|
const { Client } = require('@elastic/elasticsearch')
|
|
const client = new Client({ node: 'http://localhost:9200' })
|
|
|
|
client.on('request', (err, result) => {
|
|
const { id } = result.meta.request
|
|
if (err) {
|
|
console.log({ error: err, reqId: id })
|
|
}
|
|
})
|
|
|
|
client.on('response', (err, result) => {
|
|
const { id } = result.meta.request
|
|
if (err) {
|
|
console.log({ error: err, reqId: id })
|
|
}
|
|
})
|
|
|
|
client.search({
|
|
index: 'my-index',
|
|
body: { foo: 'bar' }
|
|
}, (err, result) => {
|
|
if (err) console.log(err)
|
|
})
|
|
----
|
|
|
|
|
|
By default the id is an incremental integer, but you can easily configure that
|
|
with the `generateRequestId` option:
|
|
|
|
[source,js]
|
|
----
|
|
const { Client } = require('@elastic/elasticsearch')
|
|
const client = new Client({
|
|
node: 'http://localhost:9200',
|
|
// it takes two parameters, the request parameters and options
|
|
generateRequestId: function (params, options) {
|
|
// your id generation logic
|
|
// must be syncronous
|
|
return 'id'
|
|
}
|
|
})
|
|
----
|
|
|
|
|
|
You can also specify a custom id per request:
|
|
|
|
[source,js]
|
|
----
|
|
client.search({
|
|
index: 'my-index',
|
|
body: { foo: 'bar' }
|
|
}, {
|
|
id: 'custom-id'
|
|
}, (err, result) => {
|
|
if (err) console.log(err)
|
|
})
|
|
----
|
|
|
|
|
|
=== Context object
|
|
|
|
Sometimes, you might need to make some custom data available in your events, you
|
|
can do that via the `context` option of a request:
|
|
|
|
[source,js]
|
|
----
|
|
const { Client } = require('@elastic/elasticsearch')
|
|
const client = new Client({ node: 'http://localhost:9200' })
|
|
|
|
client.on('request', (err, result) => {
|
|
const { id } = result.meta.request
|
|
const { context } = result.meta
|
|
if (err) {
|
|
console.log({ error: err, reqId: id, context })
|
|
}
|
|
})
|
|
|
|
client.on('response', (err, result) => {
|
|
const { id } = result.meta.request
|
|
const { winter } = result.meta.context
|
|
if (err) {
|
|
console.log({ error: err, reqId: id, winter })
|
|
}
|
|
})
|
|
|
|
client.search({
|
|
index: 'my-index',
|
|
body: { foo: 'bar' }
|
|
}, {
|
|
context: { winter: 'is coming' }
|
|
}, (err, result) => {
|
|
if (err) console.log(err)
|
|
})
|
|
----
|
|
|
|
|
|
=== Client name
|
|
|
|
If you are using multiple instances of the client or if you are using multiple
|
|
child clients _(which is the recommended way to have multiple instances of the
|
|
client)_, you might need to recognize which client you are using. The `name`
|
|
options will help you in this regard.
|
|
|
|
[source,js]
|
|
----
|
|
const { Client } = require('@elastic/elasticsearch')
|
|
const client = new Client({
|
|
node: 'http://localhost:9200',
|
|
name: 'parent-client' // default to 'elasticsearch-js'
|
|
})
|
|
|
|
const child = client.child({
|
|
name: 'child-client'
|
|
})
|
|
|
|
console.log(client.name, child.name)
|
|
|
|
client.on('request', (err, result) => {
|
|
const { id } = result.meta.request
|
|
const { name } = result.meta
|
|
if (err) {
|
|
console.log({ error: err, reqId: id, name })
|
|
}
|
|
})
|
|
|
|
client.on('response', (err, result) => {
|
|
const { id } = result.meta.request
|
|
const { name } = result.meta
|
|
if (err) {
|
|
console.log({ error: err, reqId: id, name })
|
|
}
|
|
})
|
|
|
|
client.search({
|
|
index: 'my-index',
|
|
body: { foo: 'bar' }
|
|
}, (err, result) => {
|
|
if (err) console.log(err)
|
|
})
|
|
|
|
child.search({
|
|
index: 'my-index',
|
|
body: { foo: 'bar' }
|
|
}, (err, result) => {
|
|
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)
|
|
})
|
|
----
|
|
|