可观测性
编辑可观测性编辑
客户端不提供默认日志记录器,而是提供一个事件发射器接口来挂钩内部事件,例如 request
和 response
。
关联这些事件可能很困难,特别是如果您的应用程序具有庞大的代码库,并且同时发生许多事件。
为了帮助您解决这个问题,客户端为您提供了一个关联 ID 系统和其他功能。让我们看看它们的作用。
事件编辑
客户端是一个事件发射器,这意味着您可以监听其事件并向代码添加额外的逻辑,而无需更改客户端内部结构或正常使用方式。您可以通过访问客户端的 events
键来查找事件名称。
const { events } = require('@elastic/elasticsearch') console.log(events)
如果您想记录在使用客户端期间发生的每个请求、响应和错误,则事件发射器功能非常有用。
const logger = require('my-logger')() const { Client } = require('@elastic/elasticsearch') const client = new Client({ cloud: { id: '<cloud-id>' }, auth: { apiKey: 'base64EncodedKey' } }) client.diagnostic.on('response', (err, result) => { if (err) { logger.error(err) } else { logger.info(result) } })
客户端发出以下事件
|
在开始序列化和压缩之前发出。如果要测量此阶段的持续时间,则应测量此事件与 client.diagnostic.on('serialization', (err, result) => { console.log(err, result) }) |
|
在向 Elasticsearch 发送实际请求之前发出*(如果重试,则会多次发出)*。 client.diagnostic.on('request', (err, result) => { console.log(err, result) }) |
|
在开始反序列化和解压缩之前发出。如果要测量此阶段的持续时间,则应测量此事件与 client.diagnostic.on('deserialization', (err, result) => { console.log(err, result) }) |
|
在收到并解析 Elasticsearch 响应后发出。 client.diagnostic.on('response', (err, result) => { console.log(err, result) }) |
|
当客户端结束嗅探请求时发出。 client.diagnostic.on('sniff', (err, result) => { console.log(err, result) }) |
|
如果客户端能够复活死节点,则发出。 client.diagnostic.on('resurrect', (err, result) => { console.log(err, result) }) |
serialization
、request
、deserialization
、response
和 sniff
中的 result
的值是
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; }; };
而 resurrect
中的 result
值是
strategy: string; isAlive: boolean; connection: Connection; name: string; request: { id: any; };
事件顺序编辑
事件顺序在下图中描述,在某些情况下,顺序无法保证。您可以在 test/acceptance/events-order.test.js
中找到顺序如何根据情况而变化。
serialization │ │ (serialization and compression happens between those two events) │ └─▶ request │ │ (actual time spent over the wire) │ └─▶ deserialization │ │ (deserialization and decompression happens between those two events) │ └─▶ response
关联 ID编辑
关联事件可能很困难,尤其是在同时发生许多事件的情况下。客户端为您提供了一个自动(且可配置)的系统来帮助您解决此问题。
const { Client } = require('@elastic/elasticsearch') const client = new Client({ cloud: { id: '<cloud-id>' }, auth: { apiKey: 'base64EncodedKey' } }) client.diagnostic.on('request', (err, result) => { const { id } = result.meta.request if (err) { console.log({ error: err, reqId: id }) } }) client.diagnostic.on('response', (err, result) => { const { id } = result.meta.request if (err) { console.log({ error: err, reqId: id }) } }) client.search({ index: 'my-index', query: { match_all: {} } }).then(console.log, console.log)
默认情况下,ID 是一个递增的整数,但您可以使用 generateRequestId
选项对其进行配置
const { Client } = require('@elastic/elasticsearch') const client = new Client({ cloud: { id: '<cloud-id>' }, auth: { apiKey: 'base64EncodedKey' }, // it takes two parameters, the request parameters and options generateRequestId: function (params, options) { // your id generation logic // must be syncronous return 'id' } })
您还可以为每个请求指定自定义 ID
client.search({ index: 'my-index', query: { match_all: {} } }, { id: 'custom-id' }).then(console.log, console.log)
上下文对象编辑
有时,您可能需要在事件中提供一些自定义数据,您可以通过请求的 context
选项来实现
const { Client } = require('@elastic/elasticsearch') const client = new Client({ cloud: { id: '<cloud-id>' }, auth: { apiKey: 'base64EncodedKey' } }) client.diagnostic.on('request', (err, result) => { const { id } = result.meta.request const { context } = result.meta if (err) { console.log({ error: err, reqId: id, context }) } }) client.diagnostic.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', query: { match_all: {} } }, { context: { winter: 'is coming' } }).then(console.log, console.log)
上下文对象也可以在客户端配置中配置为全局选项。如果您同时提供两者,则两个上下文对象将进行浅层合并,并且 API 级别的对象将优先。
const { Client } = require('@elastic/elasticsearch') const client = new Client({ cloud: { id: '<cloud-id>' }, auth: { apiKey: 'base64EncodedKey' }, context: { winter: 'is coming' } }) client.diagnostic.on('request', (err, result) => { const { id } = result.meta.request const { context } = result.meta if (err) { console.log({ error: err, reqId: id, context }) } }) client.diagnostic.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', query: { match_all: {} } }, { context: { winter: 'has come' } }).then(console.log, console.log)
客户端名称编辑
如果您正在使用客户端的多个实例,或者您正在使用多个子客户端*(这是拥有客户端多个实例的推荐方法)*,则您可能需要识别您正在使用的客户端。name
选项在这方面可以帮助您。
const { Client } = require('@elastic/elasticsearch') const client = new Client({ cloud: { id: '<cloud-id>' }, auth: { apiKey: 'base64EncodedKey' }, name: 'parent-client' // default to 'elasticsearch-js' }) const child = client.child({ name: 'child-client' }) console.log(client.name, child.name) client.diagnostic.on('request', (err, result) => { const { id } = result.meta.request const { name } = result.meta if (err) { console.log({ error: err, reqId: id, name }) } }) client.diagnostic.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', query: { match_all: {} } }).then(console.log, console.log) child.search({ index: 'my-index', query: { match_all: {} } }).then(console.log, console.log)
X-Opaque-Id 支持编辑
为了提高可观测性,客户端提供了一种简单的方法来配置 X-Opaque-Id
标头。如果您在特定请求中设置了 X-Opaque-Id
,则可以在 弃用日志 中发现此标识符,帮助您 识别搜索慢日志来源 以及 识别正在运行的任务。
X-Opaque-Id
应在每个请求中配置,为此,您可以使用 opaqueId
选项,如下例所示。结果标头将是 { 'X-Opaque-Id': 'my-search' }
。
const { Client } = require('@elastic/elasticsearch') const client = new Client({ cloud: { id: '<cloud-id>' }, auth: { apiKey: 'base64EncodedKey' } }) client.search({ index: 'my-index', body: { foo: 'bar' } }, { opaqueId: 'my-search' }).then(console.log, console.log)
有时,使用特定字符串作为所有 X-Opaque-Id
标头的开头可能很有用,以防您需要识别特定的客户端或服务器。为此,客户端提供了一个顶级配置选项:opaqueIdPrefix
。在以下示例中,结果标头将是 { 'X-Opaque-Id': 'proxy-client::my-search' }
。
const { Client } = require('@elastic/elasticsearch') const client = new Client({ cloud: { id: '<cloud-id>' }, auth: { apiKey: 'base64EncodedKey' }, opaqueIdPrefix: 'proxy-client::' }) client.search({ index: 'my-index', body: { foo: 'bar' } }, { opaqueId: 'my-search' }).then(console.log, console.log)