[7.x] Deprecate and remove usages of elasticsearch.logQueries (#89296) (#89879)

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Josh Dover 2021-02-01 19:22:25 +01:00 committed by GitHub
parent 420906569e
commit 2a5f6797ce
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 216 additions and 335 deletions

View file

@ -9,7 +9,7 @@ Configuration options to be used to create a [cluster client](./kibana-plugin-co
<b>Signature:</b> <b>Signature:</b>
```typescript ```typescript
export declare type ElasticsearchClientConfig = Pick<ElasticsearchConfig, 'customHeaders' | 'logQueries' | 'sniffOnStart' | 'sniffOnConnectionFault' | 'requestHeadersWhitelist' | 'sniffInterval' | 'hosts' | 'username' | 'password'> & { export declare type ElasticsearchClientConfig = Pick<ElasticsearchConfig, 'customHeaders' | 'sniffOnStart' | 'sniffOnConnectionFault' | 'requestHeadersWhitelist' | 'sniffInterval' | 'hosts' | 'username' | 'password'> & {
pingTimeout?: ElasticsearchConfig['pingTimeout'] | ClientOptions['pingTimeout']; pingTimeout?: ElasticsearchConfig['pingTimeout'] | ClientOptions['pingTimeout'];
requestTimeout?: ElasticsearchConfig['requestTimeout'] | ClientOptions['requestTimeout']; requestTimeout?: ElasticsearchConfig['requestTimeout'] | ClientOptions['requestTimeout'];
ssl?: Partial<ElasticsearchConfig['ssl']>; ssl?: Partial<ElasticsearchConfig['ssl']>;

View file

@ -1,13 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-core-server](./kibana-plugin-core-server.md) &gt; [ElasticsearchConfig](./kibana-plugin-core-server.elasticsearchconfig.md) &gt; [logQueries](./kibana-plugin-core-server.elasticsearchconfig.logqueries.md)
## ElasticsearchConfig.logQueries property
Specifies whether all queries to the client should be logged (status code, method, query etc.).
<b>Signature:</b>
```typescript
readonly logQueries: boolean;
```

View file

@ -27,7 +27,6 @@ export declare class ElasticsearchConfig
| [healthCheckDelay](./kibana-plugin-core-server.elasticsearchconfig.healthcheckdelay.md) | | <code>Duration</code> | The interval between health check requests Kibana sends to the Elasticsearch. | | [healthCheckDelay](./kibana-plugin-core-server.elasticsearchconfig.healthcheckdelay.md) | | <code>Duration</code> | The interval between health check requests Kibana sends to the Elasticsearch. |
| [hosts](./kibana-plugin-core-server.elasticsearchconfig.hosts.md) | | <code>string[]</code> | Hosts that the client will connect to. If sniffing is enabled, this list will be used as seeds to discover the rest of your cluster. | | [hosts](./kibana-plugin-core-server.elasticsearchconfig.hosts.md) | | <code>string[]</code> | Hosts that the client will connect to. If sniffing is enabled, this list will be used as seeds to discover the rest of your cluster. |
| [ignoreVersionMismatch](./kibana-plugin-core-server.elasticsearchconfig.ignoreversionmismatch.md) | | <code>boolean</code> | Whether to allow kibana to connect to a non-compatible elasticsearch node. | | [ignoreVersionMismatch](./kibana-plugin-core-server.elasticsearchconfig.ignoreversionmismatch.md) | | <code>boolean</code> | Whether to allow kibana to connect to a non-compatible elasticsearch node. |
| [logQueries](./kibana-plugin-core-server.elasticsearchconfig.logqueries.md) | | <code>boolean</code> | Specifies whether all queries to the client should be logged (status code, method, query etc.). |
| [password](./kibana-plugin-core-server.elasticsearchconfig.password.md) | | <code>string</code> | If Elasticsearch is protected with basic authentication, this setting provides the password that the Kibana server uses to perform its administrative functions. | | [password](./kibana-plugin-core-server.elasticsearchconfig.password.md) | | <code>string</code> | If Elasticsearch is protected with basic authentication, this setting provides the password that the Kibana server uses to perform its administrative functions. |
| [pingTimeout](./kibana-plugin-core-server.elasticsearchconfig.pingtimeout.md) | | <code>Duration</code> | Timeout after which PING HTTP request will be aborted and retried. | | [pingTimeout](./kibana-plugin-core-server.elasticsearchconfig.pingtimeout.md) | | <code>Duration</code> | Timeout after which PING HTTP request will be aborted and retried. |
| [requestHeadersWhitelist](./kibana-plugin-core-server.elasticsearchconfig.requestheaderswhitelist.md) | | <code>string[]</code> | List of Kibana client-side headers to send to Elasticsearch when request scoped cluster client is used. If this is an empty array then \*no\* client-side will be sent. | | [requestHeadersWhitelist](./kibana-plugin-core-server.elasticsearchconfig.requestheaderswhitelist.md) | | <code>string[]</code> | List of Kibana client-side headers to send to Elasticsearch when request scoped cluster client is used. If this is an empty array then \*no\* client-side will be sent. |

View file

@ -9,7 +9,7 @@ Constructs a new instance of the `LegacyClusterClient` class
<b>Signature:</b> <b>Signature:</b>
```typescript ```typescript
constructor(config: LegacyElasticsearchClientConfig, log: Logger, getAuthHeaders?: GetAuthHeaders); constructor(config: LegacyElasticsearchClientConfig, log: Logger, type: string, getAuthHeaders?: GetAuthHeaders);
``` ```
## Parameters ## Parameters
@ -18,5 +18,6 @@ constructor(config: LegacyElasticsearchClientConfig, log: Logger, getAuthHeaders
| --- | --- | --- | | --- | --- | --- |
| config | <code>LegacyElasticsearchClientConfig</code> | | | config | <code>LegacyElasticsearchClientConfig</code> | |
| log | <code>Logger</code> | | | log | <code>Logger</code> | |
| type | <code>string</code> | |
| getAuthHeaders | <code>GetAuthHeaders</code> | | | getAuthHeaders | <code>GetAuthHeaders</code> | |

View file

@ -21,7 +21,7 @@ export declare class LegacyClusterClient implements ILegacyClusterClient
| Constructor | Modifiers | Description | | Constructor | Modifiers | Description |
| --- | --- | --- | | --- | --- | --- |
| [(constructor)(config, log, getAuthHeaders)](./kibana-plugin-core-server.legacyclusterclient._constructor_.md) | | Constructs a new instance of the <code>LegacyClusterClient</code> class | | [(constructor)(config, log, type, getAuthHeaders)](./kibana-plugin-core-server.legacyclusterclient._constructor_.md) | | Constructs a new instance of the <code>LegacyClusterClient</code> class |
## Properties ## Properties

View file

@ -11,7 +11,7 @@
<b>Signature:</b> <b>Signature:</b>
```typescript ```typescript
export declare type LegacyElasticsearchClientConfig = Pick<ConfigOptions, 'keepAlive' | 'log' | 'plugins'> & Pick<ElasticsearchConfig, 'apiVersion' | 'customHeaders' | 'logQueries' | 'requestHeadersWhitelist' | 'sniffOnStart' | 'sniffOnConnectionFault' | 'hosts' | 'username' | 'password'> & { export declare type LegacyElasticsearchClientConfig = Pick<ConfigOptions, 'keepAlive' | 'log' | 'plugins'> & Pick<ElasticsearchConfig, 'apiVersion' | 'customHeaders' | 'requestHeadersWhitelist' | 'sniffOnStart' | 'sniffOnConnectionFault' | 'hosts' | 'username' | 'password'> & {
pingTimeout?: ElasticsearchConfig['pingTimeout'] | ConfigOptions['pingTimeout']; pingTimeout?: ElasticsearchConfig['pingTimeout'] | ConfigOptions['pingTimeout'];
requestTimeout?: ElasticsearchConfig['requestTimeout'] | ConfigOptions['requestTimeout']; requestTimeout?: ElasticsearchConfig['requestTimeout'] | ConfigOptions['requestTimeout'];
sniffInterval?: ElasticsearchConfig['sniffInterval'] | ConfigOptions['sniffInterval']; sniffInterval?: ElasticsearchConfig['sniffInterval'] | ConfigOptions['sniffInterval'];

View file

@ -59,7 +59,7 @@ To enable SSL/TLS for outbound connections to {es}, use the `https` protocol
in this setting. in this setting.
| `elasticsearch.logQueries:` | `elasticsearch.logQueries:`
| Log queries sent to {es}. Requires <<logging-verbose, `logging.verbose`>> set to `true`. | *deprecated* This setting is no longer used and will get removed in Kibana 8.0. Instead, set <<logging-verbose, `logging.verbose`>> to `true`
This is useful for seeing the query DSL generated by applications that This is useful for seeing the query DSL generated by applications that
currently do not have an inspector, for example Timelion and Monitoring. currently do not have an inspector, for example Timelion and Monitoring.
*Default: `false`* *Default: `false`*

View file

@ -15,7 +15,6 @@ const createConfig = (
): ElasticsearchClientConfig => { ): ElasticsearchClientConfig => {
return { return {
customHeaders: {}, customHeaders: {},
logQueries: false,
sniffOnStart: false, sniffOnStart: false,
sniffOnConnectionFault: false, sniffOnConnectionFault: false,
sniffInterval: false, sniffInterval: false,

View file

@ -22,7 +22,6 @@ import { DEFAULT_HEADERS } from '../default_headers';
export type ElasticsearchClientConfig = Pick< export type ElasticsearchClientConfig = Pick<
ElasticsearchConfig, ElasticsearchConfig,
| 'customHeaders' | 'customHeaders'
| 'logQueries'
| 'sniffOnStart' | 'sniffOnStart'
| 'sniffOnConnectionFault' | 'sniffOnConnectionFault'
| 'requestHeadersWhitelist' | 'requestHeadersWhitelist'

View file

@ -19,7 +19,6 @@ const createConfig = (
parts: Partial<ElasticsearchClientConfig> = {} parts: Partial<ElasticsearchClientConfig> = {}
): ElasticsearchClientConfig => { ): ElasticsearchClientConfig => {
return { return {
logQueries: false,
sniffOnStart: false, sniffOnStart: false,
sniffOnConnectionFault: false, sniffOnConnectionFault: false,
sniffInterval: false, sniffInterval: false,
@ -57,16 +56,25 @@ describe('ClusterClient', () => {
it('creates a single internal and scoped client during initialization', () => { it('creates a single internal and scoped client during initialization', () => {
const config = createConfig(); const config = createConfig();
new ClusterClient(config, logger, getAuthHeaders); new ClusterClient(config, logger, 'custom-type', getAuthHeaders);
expect(configureClientMock).toHaveBeenCalledTimes(2); expect(configureClientMock).toHaveBeenCalledTimes(2);
expect(configureClientMock).toHaveBeenCalledWith(config, { logger }); expect(configureClientMock).toHaveBeenCalledWith(config, { logger, type: 'custom-type' });
expect(configureClientMock).toHaveBeenCalledWith(config, { logger, scoped: true }); expect(configureClientMock).toHaveBeenCalledWith(config, {
logger,
type: 'custom-type',
scoped: true,
});
}); });
describe('#asInternalUser', () => { describe('#asInternalUser', () => {
it('returns the internal client', () => { it('returns the internal client', () => {
const clusterClient = new ClusterClient(createConfig(), logger, getAuthHeaders); const clusterClient = new ClusterClient(
createConfig(),
logger,
'custom-type',
getAuthHeaders
);
expect(clusterClient.asInternalUser).toBe(internalClient); expect(clusterClient.asInternalUser).toBe(internalClient);
}); });
@ -74,7 +82,12 @@ describe('ClusterClient', () => {
describe('#asScoped', () => { describe('#asScoped', () => {
it('returns a scoped cluster client bound to the request', () => { it('returns a scoped cluster client bound to the request', () => {
const clusterClient = new ClusterClient(createConfig(), logger, getAuthHeaders); const clusterClient = new ClusterClient(
createConfig(),
logger,
'custom-type',
getAuthHeaders
);
const request = httpServerMock.createKibanaRequest(); const request = httpServerMock.createKibanaRequest();
const scopedClusterClient = clusterClient.asScoped(request); const scopedClusterClient = clusterClient.asScoped(request);
@ -87,7 +100,12 @@ describe('ClusterClient', () => {
}); });
it('returns a distinct scoped cluster client on each call', () => { it('returns a distinct scoped cluster client on each call', () => {
const clusterClient = new ClusterClient(createConfig(), logger, getAuthHeaders); const clusterClient = new ClusterClient(
createConfig(),
logger,
'custom-type',
getAuthHeaders
);
const request = httpServerMock.createKibanaRequest(); const request = httpServerMock.createKibanaRequest();
const scopedClusterClient1 = clusterClient.asScoped(request); const scopedClusterClient1 = clusterClient.asScoped(request);
@ -105,7 +123,7 @@ describe('ClusterClient', () => {
}); });
getAuthHeaders.mockReturnValue({}); getAuthHeaders.mockReturnValue({});
const clusterClient = new ClusterClient(config, logger, getAuthHeaders); const clusterClient = new ClusterClient(config, logger, 'custom-type', getAuthHeaders);
const request = httpServerMock.createKibanaRequest({ const request = httpServerMock.createKibanaRequest({
headers: { headers: {
foo: 'bar', foo: 'bar',
@ -130,7 +148,7 @@ describe('ClusterClient', () => {
other: 'nope', other: 'nope',
}); });
const clusterClient = new ClusterClient(config, logger, getAuthHeaders); const clusterClient = new ClusterClient(config, logger, 'custom-type', getAuthHeaders);
const request = httpServerMock.createKibanaRequest({}); const request = httpServerMock.createKibanaRequest({});
clusterClient.asScoped(request); clusterClient.asScoped(request);
@ -150,7 +168,7 @@ describe('ClusterClient', () => {
other: 'nope', other: 'nope',
}); });
const clusterClient = new ClusterClient(config, logger, getAuthHeaders); const clusterClient = new ClusterClient(config, logger, 'custom-type', getAuthHeaders);
const request = httpServerMock.createKibanaRequest({ const request = httpServerMock.createKibanaRequest({
headers: { headers: {
authorization: 'override', authorization: 'override',
@ -175,7 +193,7 @@ describe('ClusterClient', () => {
}); });
getAuthHeaders.mockReturnValue({}); getAuthHeaders.mockReturnValue({});
const clusterClient = new ClusterClient(config, logger, getAuthHeaders); const clusterClient = new ClusterClient(config, logger, 'custom-type', getAuthHeaders);
const request = httpServerMock.createKibanaRequest({}); const request = httpServerMock.createKibanaRequest({});
clusterClient.asScoped(request); clusterClient.asScoped(request);
@ -195,7 +213,7 @@ describe('ClusterClient', () => {
const config = createConfig(); const config = createConfig();
getAuthHeaders.mockReturnValue({}); getAuthHeaders.mockReturnValue({});
const clusterClient = new ClusterClient(config, logger, getAuthHeaders); const clusterClient = new ClusterClient(config, logger, 'custom-type', getAuthHeaders);
const request = httpServerMock.createKibanaRequest({ const request = httpServerMock.createKibanaRequest({
kibanaRequestState: { requestId: 'my-fake-id', requestUuid: 'ignore-this-id' }, kibanaRequestState: { requestId: 'my-fake-id', requestUuid: 'ignore-this-id' },
}); });
@ -223,7 +241,7 @@ describe('ClusterClient', () => {
foo: 'auth', foo: 'auth',
}); });
const clusterClient = new ClusterClient(config, logger, getAuthHeaders); const clusterClient = new ClusterClient(config, logger, 'custom-type', getAuthHeaders);
const request = httpServerMock.createKibanaRequest({}); const request = httpServerMock.createKibanaRequest({});
clusterClient.asScoped(request); clusterClient.asScoped(request);
@ -249,7 +267,7 @@ describe('ClusterClient', () => {
}); });
getAuthHeaders.mockReturnValue({}); getAuthHeaders.mockReturnValue({});
const clusterClient = new ClusterClient(config, logger, getAuthHeaders); const clusterClient = new ClusterClient(config, logger, 'custom-type', getAuthHeaders);
const request = httpServerMock.createKibanaRequest({ const request = httpServerMock.createKibanaRequest({
headers: { foo: 'request' }, headers: { foo: 'request' },
}); });
@ -276,7 +294,7 @@ describe('ClusterClient', () => {
}); });
getAuthHeaders.mockReturnValue({}); getAuthHeaders.mockReturnValue({});
const clusterClient = new ClusterClient(config, logger, getAuthHeaders); const clusterClient = new ClusterClient(config, logger, 'custom-type', getAuthHeaders);
const request = httpServerMock.createKibanaRequest(); const request = httpServerMock.createKibanaRequest();
clusterClient.asScoped(request); clusterClient.asScoped(request);
@ -297,7 +315,7 @@ describe('ClusterClient', () => {
}); });
getAuthHeaders.mockReturnValue({}); getAuthHeaders.mockReturnValue({});
const clusterClient = new ClusterClient(config, logger, getAuthHeaders); const clusterClient = new ClusterClient(config, logger, 'custom-type', getAuthHeaders);
const request = httpServerMock.createKibanaRequest({ const request = httpServerMock.createKibanaRequest({
headers: { [headerKey]: 'foo' }, headers: { [headerKey]: 'foo' },
}); });
@ -321,7 +339,7 @@ describe('ClusterClient', () => {
}); });
getAuthHeaders.mockReturnValue({}); getAuthHeaders.mockReturnValue({});
const clusterClient = new ClusterClient(config, logger, getAuthHeaders); const clusterClient = new ClusterClient(config, logger, 'custom-type', getAuthHeaders);
const request = httpServerMock.createKibanaRequest({ const request = httpServerMock.createKibanaRequest({
headers: { foo: 'request' }, headers: { foo: 'request' },
kibanaRequestState: { requestId: 'from request', requestUuid: 'ignore-this-id' }, kibanaRequestState: { requestId: 'from request', requestUuid: 'ignore-this-id' },
@ -344,7 +362,7 @@ describe('ClusterClient', () => {
}); });
getAuthHeaders.mockReturnValue({}); getAuthHeaders.mockReturnValue({});
const clusterClient = new ClusterClient(config, logger, getAuthHeaders); const clusterClient = new ClusterClient(config, logger, 'custom-type', getAuthHeaders);
const request = { const request = {
headers: { headers: {
authorization: 'auth', authorization: 'auth',
@ -368,7 +386,7 @@ describe('ClusterClient', () => {
authorization: 'auth', authorization: 'auth',
}); });
const clusterClient = new ClusterClient(config, logger, getAuthHeaders); const clusterClient = new ClusterClient(config, logger, 'custom-type', getAuthHeaders);
const request = { const request = {
headers: { headers: {
foo: 'bar', foo: 'bar',
@ -387,7 +405,12 @@ describe('ClusterClient', () => {
describe('#close', () => { describe('#close', () => {
it('closes both underlying clients', async () => { it('closes both underlying clients', async () => {
const clusterClient = new ClusterClient(createConfig(), logger, getAuthHeaders); const clusterClient = new ClusterClient(
createConfig(),
logger,
'custom-type',
getAuthHeaders
);
await clusterClient.close(); await clusterClient.close();
@ -398,7 +421,12 @@ describe('ClusterClient', () => {
it('waits for both clients to close', async (done) => { it('waits for both clients to close', async (done) => {
expect.assertions(4); expect.assertions(4);
const clusterClient = new ClusterClient(createConfig(), logger, getAuthHeaders); const clusterClient = new ClusterClient(
createConfig(),
logger,
'custom-type',
getAuthHeaders
);
let internalClientClosed = false; let internalClientClosed = false;
let scopedClientClosed = false; let scopedClientClosed = false;
@ -436,7 +464,12 @@ describe('ClusterClient', () => {
}); });
it('return a rejected promise is any client rejects', async () => { it('return a rejected promise is any client rejects', async () => {
const clusterClient = new ClusterClient(createConfig(), logger, getAuthHeaders); const clusterClient = new ClusterClient(
createConfig(),
logger,
'custom-type',
getAuthHeaders
);
internalClient.close.mockRejectedValue(new Error('error closing client')); internalClient.close.mockRejectedValue(new Error('error closing client'));
@ -446,7 +479,12 @@ describe('ClusterClient', () => {
}); });
it('does nothing after the first call', async () => { it('does nothing after the first call', async () => {
const clusterClient = new ClusterClient(createConfig(), logger, getAuthHeaders); const clusterClient = new ClusterClient(
createConfig(),
logger,
'custom-type',
getAuthHeaders
);
await clusterClient.close(); await clusterClient.close();

View file

@ -60,10 +60,11 @@ export class ClusterClient implements ICustomClusterClient {
constructor( constructor(
private readonly config: ElasticsearchClientConfig, private readonly config: ElasticsearchClientConfig,
logger: Logger, logger: Logger,
type: string,
private readonly getAuthHeaders: GetAuthHeaders = noop private readonly getAuthHeaders: GetAuthHeaders = noop
) { ) {
this.asInternalUser = configureClient(config, { logger }); this.asInternalUser = configureClient(config, { logger, type });
this.rootScopedClient = configureClient(config, { logger, scoped: true }); this.rootScopedClient = configureClient(config, { logger, type, scoped: true });
} }
asScoped(request: ScopeableRequest) { asScoped(request: ScopeableRequest) {

View file

@ -76,14 +76,14 @@ describe('configureClient', () => {
}); });
it('calls `parseClientOptions` with the correct parameters', () => { it('calls `parseClientOptions` with the correct parameters', () => {
configureClient(config, { logger, scoped: false }); configureClient(config, { logger, type: 'test', scoped: false });
expect(parseClientOptionsMock).toHaveBeenCalledTimes(1); expect(parseClientOptionsMock).toHaveBeenCalledTimes(1);
expect(parseClientOptionsMock).toHaveBeenCalledWith(config, false); expect(parseClientOptionsMock).toHaveBeenCalledWith(config, false);
parseClientOptionsMock.mockClear(); parseClientOptionsMock.mockClear();
configureClient(config, { logger, scoped: true }); configureClient(config, { logger, type: 'test', scoped: true });
expect(parseClientOptionsMock).toHaveBeenCalledTimes(1); expect(parseClientOptionsMock).toHaveBeenCalledTimes(1);
expect(parseClientOptionsMock).toHaveBeenCalledWith(config, true); expect(parseClientOptionsMock).toHaveBeenCalledWith(config, true);
@ -95,7 +95,7 @@ describe('configureClient', () => {
}; };
parseClientOptionsMock.mockReturnValue(parsedOptions); parseClientOptionsMock.mockReturnValue(parsedOptions);
const client = configureClient(config, { logger, scoped: false }); const client = configureClient(config, { logger, type: 'test', scoped: false });
expect(ClientMock).toHaveBeenCalledTimes(1); expect(ClientMock).toHaveBeenCalledTimes(1);
expect(ClientMock).toHaveBeenCalledWith(parsedOptions); expect(ClientMock).toHaveBeenCalledWith(parsedOptions);
@ -103,7 +103,7 @@ describe('configureClient', () => {
}); });
it('listens to client on `response` events', () => { it('listens to client on `response` events', () => {
const client = configureClient(config, { logger, scoped: false }); const client = configureClient(config, { logger, type: 'test', scoped: false });
expect(client.on).toHaveBeenCalledTimes(1); expect(client.on).toHaveBeenCalledTimes(1);
expect(client.on).toHaveBeenCalledWith('response', expect.any(Function)); expect(client.on).toHaveBeenCalledWith('response', expect.any(Function));
@ -122,38 +122,15 @@ describe('configureClient', () => {
}, },
}); });
} }
describe('does not log whrn "logQueries: false"', () => {
it('response', () => {
const client = configureClient(config, { logger, scoped: false });
const response = createResponseWithBody({
seq_no_primary_term: true,
query: {
term: { user: 'kimchy' },
},
});
client.emit('response', null, response); describe('logs each query', () => {
expect(loggingSystemMock.collect(logger).debug).toHaveLength(0); it('creates a query logger context based on the `type` parameter', () => {
configureClient(createFakeConfig(), { logger, type: 'test123' });
expect(logger.get).toHaveBeenCalledWith('query', 'test123');
}); });
it('error', () => {
const client = configureClient(config, { logger, scoped: false });
const response = createApiResponse({ body: {} });
client.emit('response', new errors.TimeoutError('message', response), response);
expect(loggingSystemMock.collect(logger).error).toHaveLength(0);
});
});
describe('logs each queries if `logQueries` is true', () => {
it('when request body is an object', () => { it('when request body is an object', () => {
const client = configureClient( const client = configureClient(createFakeConfig(), { logger, type: 'test', scoped: false });
createFakeConfig({
logQueries: true,
}),
{ logger, scoped: false }
);
const response = createResponseWithBody({ const response = createResponseWithBody({
seq_no_primary_term: true, seq_no_primary_term: true,
@ -169,23 +146,13 @@ describe('configureClient', () => {
"200 "200
GET /foo?hello=dolly GET /foo?hello=dolly
{\\"seq_no_primary_term\\":true,\\"query\\":{\\"term\\":{\\"user\\":\\"kimchy\\"}}}", {\\"seq_no_primary_term\\":true,\\"query\\":{\\"term\\":{\\"user\\":\\"kimchy\\"}}}",
Object {
"tags": Array [
"query",
],
},
], ],
] ]
`); `);
}); });
it('when request body is a string', () => { it('when request body is a string', () => {
const client = configureClient( const client = configureClient(createFakeConfig(), { logger, type: 'test', scoped: false });
createFakeConfig({
logQueries: true,
}),
{ logger, scoped: false }
);
const response = createResponseWithBody( const response = createResponseWithBody(
JSON.stringify({ JSON.stringify({
@ -203,23 +170,13 @@ describe('configureClient', () => {
"200 "200
GET /foo?hello=dolly GET /foo?hello=dolly
{\\"seq_no_primary_term\\":true,\\"query\\":{\\"term\\":{\\"user\\":\\"kimchy\\"}}}", {\\"seq_no_primary_term\\":true,\\"query\\":{\\"term\\":{\\"user\\":\\"kimchy\\"}}}",
Object {
"tags": Array [
"query",
],
},
], ],
] ]
`); `);
}); });
it('when request body is a buffer', () => { it('when request body is a buffer', () => {
const client = configureClient( const client = configureClient(createFakeConfig(), { logger, type: 'test', scoped: false });
createFakeConfig({
logQueries: true,
}),
{ logger, scoped: false }
);
const response = createResponseWithBody( const response = createResponseWithBody(
Buffer.from( Buffer.from(
@ -239,23 +196,13 @@ describe('configureClient', () => {
"200 "200
GET /foo?hello=dolly GET /foo?hello=dolly
[buffer]", [buffer]",
Object {
"tags": Array [
"query",
],
},
], ],
] ]
`); `);
}); });
it('when request body is a readable stream', () => { it('when request body is a readable stream', () => {
const client = configureClient( const client = configureClient(createFakeConfig(), { logger, type: 'test', scoped: false });
createFakeConfig({
logQueries: true,
}),
{ logger, scoped: false }
);
const response = createResponseWithBody( const response = createResponseWithBody(
Readable.from( Readable.from(
@ -275,23 +222,13 @@ describe('configureClient', () => {
"200 "200
GET /foo?hello=dolly GET /foo?hello=dolly
[stream]", [stream]",
Object {
"tags": Array [
"query",
],
},
], ],
] ]
`); `);
}); });
it('when request body is not defined', () => { it('when request body is not defined', () => {
const client = configureClient( const client = configureClient(createFakeConfig(), { logger, type: 'test', scoped: false });
createFakeConfig({
logQueries: true,
}),
{ logger, scoped: false }
);
const response = createResponseWithBody(); const response = createResponseWithBody();
@ -301,23 +238,13 @@ describe('configureClient', () => {
Array [ Array [
"200 "200
GET /foo?hello=dolly", GET /foo?hello=dolly",
Object {
"tags": Array [
"query",
],
},
], ],
] ]
`); `);
}); });
it('properly encode queries', () => { it('properly encode queries', () => {
const client = configureClient( const client = configureClient(createFakeConfig(), { logger, type: 'test', scoped: false });
createFakeConfig({
logQueries: true,
}),
{ logger, scoped: false }
);
const response = createApiResponse({ const response = createApiResponse({
body: {}, body: {},
@ -336,23 +263,13 @@ describe('configureClient', () => {
Array [ Array [
"200 "200
GET /foo?city=M%C3%BCnich", GET /foo?city=M%C3%BCnich",
Object {
"tags": Array [
"query",
],
},
], ],
] ]
`); `);
}); });
it('logs queries even in case of errors if `logQueries` is true', () => { it('logs queries even in case of errors', () => {
const client = configureClient( const client = configureClient(createFakeConfig(), { logger, type: 'test', scoped: false });
createFakeConfig({
logQueries: true,
}),
{ logger, scoped: false }
);
const response = createApiResponse({ const response = createApiResponse({
statusCode: 500, statusCode: 500,
@ -375,7 +292,7 @@ describe('configureClient', () => {
}); });
client.emit('response', new errors.ResponseError(response), response); client.emit('response', new errors.ResponseError(response), response);
expect(loggingSystemMock.collect(logger).error).toMatchInlineSnapshot(` expect(loggingSystemMock.collect(logger).debug).toMatchInlineSnapshot(`
Array [ Array [
Array [ Array [
"500 "500
@ -386,40 +303,13 @@ describe('configureClient', () => {
`); `);
}); });
it('does not log queries if `logQueries` is false', () => { it('logs debug when the client emits an @elastic/elasticsearch error', () => {
const client = configureClient( const client = configureClient(createFakeConfig(), { logger, type: 'test', scoped: false });
createFakeConfig({
logQueries: false,
}),
{ logger, scoped: false }
);
const response = createApiResponse({
body: {},
statusCode: 200,
params: {
method: 'GET',
path: '/foo',
},
});
client.emit('response', null, response);
expect(logger.debug).not.toHaveBeenCalled();
});
it('logs error when the client emits an @elastic/elasticsearch error', () => {
const client = configureClient(
createFakeConfig({
logQueries: true,
}),
{ logger, scoped: false }
);
const response = createApiResponse({ body: {} }); const response = createApiResponse({ body: {} });
client.emit('response', new errors.TimeoutError('message', response), response); client.emit('response', new errors.TimeoutError('message', response), response);
expect(loggingSystemMock.collect(logger).error).toMatchInlineSnapshot(` expect(loggingSystemMock.collect(logger).debug).toMatchInlineSnapshot(`
Array [ Array [
Array [ Array [
"[TimeoutError]: message", "[TimeoutError]: message",
@ -428,13 +318,8 @@ describe('configureClient', () => {
`); `);
}); });
it('logs error when the client emits an ResponseError returned by elasticsearch', () => { it('logs debug when the client emits an ResponseError returned by elasticsearch', () => {
const client = configureClient( const client = configureClient(createFakeConfig(), { logger, type: 'test', scoped: false });
createFakeConfig({
logQueries: true,
}),
{ logger, scoped: false }
);
const response = createApiResponse({ const response = createApiResponse({
statusCode: 400, statusCode: 400,
@ -453,7 +338,7 @@ describe('configureClient', () => {
}); });
client.emit('response', new errors.ResponseError(response), response); client.emit('response', new errors.ResponseError(response), response);
expect(loggingSystemMock.collect(logger).error).toMatchInlineSnapshot(` expect(loggingSystemMock.collect(logger).debug).toMatchInlineSnapshot(`
Array [ Array [
Array [ Array [
"400 "400
@ -464,12 +349,7 @@ describe('configureClient', () => {
}); });
it('logs default error info when the error response body is empty', () => { it('logs default error info when the error response body is empty', () => {
const client = configureClient( const client = configureClient(createFakeConfig(), { logger, type: 'test', scoped: false });
createFakeConfig({
logQueries: true,
}),
{ logger, scoped: false }
);
let response = createApiResponse({ let response = createApiResponse({
statusCode: 400, statusCode: 400,
@ -484,7 +364,7 @@ describe('configureClient', () => {
}); });
client.emit('response', new errors.ResponseError(response), response); client.emit('response', new errors.ResponseError(response), response);
expect(loggingSystemMock.collect(logger).error).toMatchInlineSnapshot(` expect(loggingSystemMock.collect(logger).debug).toMatchInlineSnapshot(`
Array [ Array [
Array [ Array [
"400 "400
@ -493,7 +373,7 @@ describe('configureClient', () => {
] ]
`); `);
logger.error.mockClear(); logger.debug.mockClear();
response = createApiResponse({ response = createApiResponse({
statusCode: 400, statusCode: 400,
@ -506,7 +386,7 @@ describe('configureClient', () => {
}); });
client.emit('response', new errors.ResponseError(response), response); client.emit('response', new errors.ResponseError(response), response);
expect(loggingSystemMock.collect(logger).error).toMatchInlineSnapshot(` expect(loggingSystemMock.collect(logger).debug).toMatchInlineSnapshot(`
Array [ Array [
Array [ Array [
"400 "400

View file

@ -15,12 +15,12 @@ import { parseClientOptions, ElasticsearchClientConfig } from './client_config';
export const configureClient = ( export const configureClient = (
config: ElasticsearchClientConfig, config: ElasticsearchClientConfig,
{ logger, scoped = false }: { logger: Logger; scoped?: boolean } { logger, type, scoped = false }: { logger: Logger; type: string; scoped?: boolean }
): Client => { ): Client => {
const clientOptions = parseClientOptions(config, scoped); const clientOptions = parseClientOptions(config, scoped);
const client = new Client(clientOptions); const client = new Client(clientOptions);
addLogging(client, logger, config.logQueries); addLogging(client, logger.get('query', type));
return client; return client;
}; };
@ -67,15 +67,13 @@ function getResponseMessage(event: RequestEvent): string {
return `${event.statusCode}\n${params.method} ${url}${body}`; return `${event.statusCode}\n${params.method} ${url}${body}`;
} }
const addLogging = (client: Client, logger: Logger, logQueries: boolean) => { const addLogging = (client: Client, logger: Logger) => {
client.on('response', (error, event) => { client.on('response', (error, event) => {
if (event && logQueries) { if (event) {
if (error) { if (error) {
logger.error(getErrorMessage(error, event)); logger.debug(getErrorMessage(error, event));
} else { } else {
logger.debug(getResponseMessage(event), { logger.debug(getResponseMessage(event));
tags: ['query'],
});
} }
} }
}); });

View file

@ -47,7 +47,6 @@ test('set correct defaults', () => {
"http://localhost:9200", "http://localhost:9200",
], ],
"ignoreVersionMismatch": false, "ignoreVersionMismatch": false,
"logQueries": false,
"password": undefined, "password": undefined,
"pingTimeout": "PT30S", "pingTimeout": "PT30S",
"requestHeadersWhitelist": Array [ "requestHeadersWhitelist": Array [

View file

@ -133,6 +133,10 @@ const deprecations: ConfigDeprecationProvider = () => [
log( log(
`Setting [${fromPath}.ssl.certificate] without [${fromPath}.ssl.key] is deprecated. This has no effect, you should use both settings to enable TLS client authentication to Elasticsearch.` `Setting [${fromPath}.ssl.certificate] without [${fromPath}.ssl.key] is deprecated. This has no effect, you should use both settings to enable TLS client authentication to Elasticsearch.`
); );
} else if (es.logQueries === true) {
log(
`Setting [${fromPath}.logQueries] is deprecated and no longer used. You should set the log level to "debug" for the "elasticsearch.queries" context in "logging.loggers" or use "logging.verbose: true".`
);
} }
return settings; return settings;
}, },
@ -164,12 +168,6 @@ export class ElasticsearchConfig {
*/ */
public readonly apiVersion: string; public readonly apiVersion: string;
/**
* Specifies whether all queries to the client should be logged (status code,
* method, query etc.).
*/
public readonly logQueries: boolean;
/** /**
* Hosts that the client will connect to. If sniffing is enabled, this list will * Hosts that the client will connect to. If sniffing is enabled, this list will
* be used as seeds to discover the rest of your cluster. * be used as seeds to discover the rest of your cluster.
@ -248,7 +246,6 @@ export class ElasticsearchConfig {
constructor(rawConfig: ElasticsearchConfigType) { constructor(rawConfig: ElasticsearchConfigType) {
this.ignoreVersionMismatch = rawConfig.ignoreVersionMismatch; this.ignoreVersionMismatch = rawConfig.ignoreVersionMismatch;
this.apiVersion = rawConfig.apiVersion; this.apiVersion = rawConfig.apiVersion;
this.logQueries = rawConfig.logQueries;
this.hosts = Array.isArray(rawConfig.hosts) ? rawConfig.hosts : [rawConfig.hosts]; this.hosts = Array.isArray(rawConfig.hosts) ? rawConfig.hosts : [rawConfig.hosts];
this.requestHeadersWhitelist = Array.isArray(rawConfig.requestHeadersWhitelist) this.requestHeadersWhitelist = Array.isArray(rawConfig.requestHeadersWhitelist)
? rawConfig.requestHeadersWhitelist ? rawConfig.requestHeadersWhitelist

View file

@ -92,14 +92,15 @@ describe('#setup', () => {
// reset all mocks called during setup phase // reset all mocks called during setup phase
MockLegacyClusterClient.mockClear(); MockLegacyClusterClient.mockClear();
const customConfig = { logQueries: true }; const customConfig = { keepAlive: true };
const clusterClient = setupContract.legacy.createClient('some-custom-type', customConfig); const clusterClient = setupContract.legacy.createClient('some-custom-type', customConfig);
expect(clusterClient).toBe(mockLegacyClusterClientInstance); expect(clusterClient).toBe(mockLegacyClusterClientInstance);
expect(MockLegacyClusterClient).toHaveBeenCalledWith( expect(MockLegacyClusterClient).toHaveBeenCalledWith(
expect.objectContaining(customConfig), expect.objectContaining(customConfig),
expect.objectContaining({ context: ['elasticsearch', 'some-custom-type'] }), expect.objectContaining({ context: ['elasticsearch'] }),
'some-custom-type',
expect.any(Function) expect.any(Function)
); );
}); });
@ -267,7 +268,7 @@ describe('#start', () => {
// reset all mocks called during setup phase // reset all mocks called during setup phase
MockClusterClient.mockClear(); MockClusterClient.mockClear();
const customConfig = { logQueries: true }; const customConfig = { keepAlive: true };
const clusterClient = startContract.createClient('custom-type', customConfig); const clusterClient = startContract.createClient('custom-type', customConfig);
expect(clusterClient).toBe(mockClusterClientInstance); expect(clusterClient).toBe(mockClusterClientInstance);
@ -275,7 +276,8 @@ describe('#start', () => {
expect(MockClusterClient).toHaveBeenCalledTimes(1); expect(MockClusterClient).toHaveBeenCalledTimes(1);
expect(MockClusterClient).toHaveBeenCalledWith( expect(MockClusterClient).toHaveBeenCalledWith(
expect.objectContaining(customConfig), expect.objectContaining(customConfig),
expect.objectContaining({ context: ['elasticsearch', 'custom-type'] }), expect.objectContaining({ context: ['elasticsearch'] }),
'custom-type',
expect.any(Function) expect.any(Function)
); );
}); });
@ -286,7 +288,7 @@ describe('#start', () => {
// reset all mocks called during setup phase // reset all mocks called during setup phase
MockClusterClient.mockClear(); MockClusterClient.mockClear();
const customConfig = { logQueries: true }; const customConfig = { keepAlive: true };
startContract.createClient('custom-type', customConfig); startContract.createClient('custom-type', customConfig);
startContract.createClient('another-type', customConfig); startContract.createClient('another-type', customConfig);

View file

@ -126,7 +126,8 @@ export class ElasticsearchService
private createClusterClient(type: string, config: ElasticsearchClientConfig) { private createClusterClient(type: string, config: ElasticsearchClientConfig) {
return new ClusterClient( return new ClusterClient(
config, config,
this.coreContext.logger.get('elasticsearch', type), this.coreContext.logger.get('elasticsearch'),
type,
this.getAuthHeaders this.getAuthHeaders
); );
} }
@ -134,7 +135,8 @@ export class ElasticsearchService
private createLegacyClusterClient(type: string, config: LegacyElasticsearchClientConfig) { private createLegacyClusterClient(type: string, config: LegacyElasticsearchClientConfig) {
return new LegacyClusterClient( return new LegacyClusterClient(
config, config,
this.coreContext.logger.get('elasticsearch', type), this.coreContext.logger.get('elasticsearch'),
type,
this.getAuthHeaders this.getAuthHeaders
); );
} }

View file

@ -31,11 +31,15 @@ test('#constructor creates client with parsed config', () => {
const mockEsConfig = { apiVersion: 'es-version' } as any; const mockEsConfig = { apiVersion: 'es-version' } as any;
const mockLogger = logger.get(); const mockLogger = logger.get();
const clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger); const clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger, 'custom-type');
expect(clusterClient).toBeDefined(); expect(clusterClient).toBeDefined();
expect(mockParseElasticsearchClientConfig).toHaveBeenCalledTimes(1); expect(mockParseElasticsearchClientConfig).toHaveBeenCalledTimes(1);
expect(mockParseElasticsearchClientConfig).toHaveBeenLastCalledWith(mockEsConfig, mockLogger); expect(mockParseElasticsearchClientConfig).toHaveBeenLastCalledWith(
mockEsConfig,
mockLogger,
'custom-type'
);
expect(MockClient).toHaveBeenCalledTimes(1); expect(MockClient).toHaveBeenCalledTimes(1);
expect(MockClient).toHaveBeenCalledWith(mockEsClientConfig); expect(MockClient).toHaveBeenCalledWith(mockEsClientConfig);
@ -57,7 +61,11 @@ describe('#callAsInternalUser', () => {
}; };
MockClient.mockImplementation(() => mockEsClientInstance); MockClient.mockImplementation(() => mockEsClientInstance);
clusterClient = new LegacyClusterClient({ apiVersion: 'es-version' } as any, logger.get()); clusterClient = new LegacyClusterClient(
{ apiVersion: 'es-version' } as any,
logger.get(),
'custom-type'
);
}); });
test('fails if cluster client is closed', async () => { test('fails if cluster client is closed', async () => {
@ -226,7 +234,7 @@ describe('#asScoped', () => {
requestHeadersWhitelist: ['one', 'two'], requestHeadersWhitelist: ['one', 'two'],
} as any; } as any;
clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger); clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger, 'custom-type');
jest.clearAllMocks(); jest.clearAllMocks();
}); });
@ -237,10 +245,15 @@ describe('#asScoped', () => {
expect(firstScopedClusterClient).toBeDefined(); expect(firstScopedClusterClient).toBeDefined();
expect(mockParseElasticsearchClientConfig).toHaveBeenCalledTimes(1); expect(mockParseElasticsearchClientConfig).toHaveBeenCalledTimes(1);
expect(mockParseElasticsearchClientConfig).toHaveBeenLastCalledWith(mockEsConfig, mockLogger, { expect(mockParseElasticsearchClientConfig).toHaveBeenLastCalledWith(
auth: false, mockEsConfig,
ignoreCertAndKey: true, mockLogger,
}); 'custom-type',
{
auth: false,
ignoreCertAndKey: true,
}
);
expect(MockClient).toHaveBeenCalledTimes(1); expect(MockClient).toHaveBeenCalledTimes(1);
expect(MockClient).toHaveBeenCalledWith( expect(MockClient).toHaveBeenCalledWith(
@ -261,42 +274,57 @@ describe('#asScoped', () => {
test('properly configures `ignoreCertAndKey` for various configurations', () => { test('properly configures `ignoreCertAndKey` for various configurations', () => {
// Config without SSL. // Config without SSL.
clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger); clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger, 'custom-type');
mockParseElasticsearchClientConfig.mockClear(); mockParseElasticsearchClientConfig.mockClear();
clusterClient.asScoped(httpServerMock.createRawRequest({ headers: { one: '1' } })); clusterClient.asScoped(httpServerMock.createRawRequest({ headers: { one: '1' } }));
expect(mockParseElasticsearchClientConfig).toHaveBeenCalledTimes(1); expect(mockParseElasticsearchClientConfig).toHaveBeenCalledTimes(1);
expect(mockParseElasticsearchClientConfig).toHaveBeenLastCalledWith(mockEsConfig, mockLogger, { expect(mockParseElasticsearchClientConfig).toHaveBeenLastCalledWith(
auth: false, mockEsConfig,
ignoreCertAndKey: true, mockLogger,
}); 'custom-type',
{
auth: false,
ignoreCertAndKey: true,
}
);
// Config ssl.alwaysPresentCertificate === false // Config ssl.alwaysPresentCertificate === false
mockEsConfig = { ...mockEsConfig, ssl: { alwaysPresentCertificate: false } } as any; mockEsConfig = { ...mockEsConfig, ssl: { alwaysPresentCertificate: false } } as any;
clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger); clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger, 'custom-type');
mockParseElasticsearchClientConfig.mockClear(); mockParseElasticsearchClientConfig.mockClear();
clusterClient.asScoped(httpServerMock.createRawRequest({ headers: { one: '1' } })); clusterClient.asScoped(httpServerMock.createRawRequest({ headers: { one: '1' } }));
expect(mockParseElasticsearchClientConfig).toHaveBeenCalledTimes(1); expect(mockParseElasticsearchClientConfig).toHaveBeenCalledTimes(1);
expect(mockParseElasticsearchClientConfig).toHaveBeenLastCalledWith(mockEsConfig, mockLogger, { expect(mockParseElasticsearchClientConfig).toHaveBeenLastCalledWith(
auth: false, mockEsConfig,
ignoreCertAndKey: true, mockLogger,
}); 'custom-type',
{
auth: false,
ignoreCertAndKey: true,
}
);
// Config ssl.alwaysPresentCertificate === true // Config ssl.alwaysPresentCertificate === true
mockEsConfig = { ...mockEsConfig, ssl: { alwaysPresentCertificate: true } } as any; mockEsConfig = { ...mockEsConfig, ssl: { alwaysPresentCertificate: true } } as any;
clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger); clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger, 'custom-type');
mockParseElasticsearchClientConfig.mockClear(); mockParseElasticsearchClientConfig.mockClear();
clusterClient.asScoped(httpServerMock.createRawRequest({ headers: { one: '1' } })); clusterClient.asScoped(httpServerMock.createRawRequest({ headers: { one: '1' } }));
expect(mockParseElasticsearchClientConfig).toHaveBeenCalledTimes(1); expect(mockParseElasticsearchClientConfig).toHaveBeenCalledTimes(1);
expect(mockParseElasticsearchClientConfig).toHaveBeenLastCalledWith(mockEsConfig, mockLogger, { expect(mockParseElasticsearchClientConfig).toHaveBeenLastCalledWith(
auth: false, mockEsConfig,
ignoreCertAndKey: false, mockLogger,
}); 'custom-type',
{
auth: false,
ignoreCertAndKey: false,
}
);
}); });
test('passes only filtered headers to the scoped cluster client', () => { test('passes only filtered headers to the scoped cluster client', () => {
@ -345,7 +373,7 @@ describe('#asScoped', () => {
}); });
test('does not fail when scope to not defined request', async () => { test('does not fail when scope to not defined request', async () => {
clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger); clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger, 'custom-type');
clusterClient.asScoped(); clusterClient.asScoped();
expect(MockScopedClusterClient).toHaveBeenCalledTimes(1); expect(MockScopedClusterClient).toHaveBeenCalledTimes(1);
expect(MockScopedClusterClient).toHaveBeenCalledWith( expect(MockScopedClusterClient).toHaveBeenCalledWith(
@ -356,7 +384,7 @@ describe('#asScoped', () => {
}); });
test('does not fail when scope to a request without headers', async () => { test('does not fail when scope to a request without headers', async () => {
clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger); clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger, 'custom-type');
clusterClient.asScoped({} as any); clusterClient.asScoped({} as any);
expect(MockScopedClusterClient).toHaveBeenCalledTimes(1); expect(MockScopedClusterClient).toHaveBeenCalledTimes(1);
expect(MockScopedClusterClient).toHaveBeenCalledWith( expect(MockScopedClusterClient).toHaveBeenCalledWith(
@ -367,7 +395,7 @@ describe('#asScoped', () => {
}); });
test('calls getAuthHeaders and filters results for a real request', async () => { test('calls getAuthHeaders and filters results for a real request', async () => {
clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger, () => ({ clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger, 'custom-type', () => ({
one: '1', one: '1',
three: '3', three: '3',
})); }));
@ -381,7 +409,9 @@ describe('#asScoped', () => {
}); });
test('getAuthHeaders results rewrite extends a request headers', async () => { test('getAuthHeaders results rewrite extends a request headers', async () => {
clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger, () => ({ one: 'foo' })); clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger, 'custom-type', () => ({
one: 'foo',
}));
clusterClient.asScoped(httpServerMock.createRawRequest({ headers: { one: '1', two: '2' } })); clusterClient.asScoped(httpServerMock.createRawRequest({ headers: { one: '1', two: '2' } }));
expect(MockScopedClusterClient).toHaveBeenCalledTimes(1); expect(MockScopedClusterClient).toHaveBeenCalledTimes(1);
expect(MockScopedClusterClient).toHaveBeenCalledWith( expect(MockScopedClusterClient).toHaveBeenCalledWith(
@ -392,7 +422,7 @@ describe('#asScoped', () => {
}); });
test("doesn't call getAuthHeaders for a fake request", async () => { test("doesn't call getAuthHeaders for a fake request", async () => {
clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger, () => ({})); clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger, 'custom-type', () => ({}));
clusterClient.asScoped({ headers: { one: 'foo' } }); clusterClient.asScoped({ headers: { one: 'foo' } });
expect(MockScopedClusterClient).toHaveBeenCalledTimes(1); expect(MockScopedClusterClient).toHaveBeenCalledTimes(1);
@ -404,7 +434,7 @@ describe('#asScoped', () => {
}); });
test('filters a fake request headers', async () => { test('filters a fake request headers', async () => {
clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger); clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger, 'custom-type');
clusterClient.asScoped({ headers: { one: '1', two: '2', three: '3' } }); clusterClient.asScoped({ headers: { one: '1', two: '2', three: '3' } });
expect(MockScopedClusterClient).toHaveBeenCalledTimes(1); expect(MockScopedClusterClient).toHaveBeenCalledTimes(1);
@ -431,7 +461,8 @@ describe('#close', () => {
clusterClient = new LegacyClusterClient( clusterClient = new LegacyClusterClient(
{ apiVersion: 'es-version', requestHeadersWhitelist: [] } as any, { apiVersion: 'es-version', requestHeadersWhitelist: [] } as any,
logger.get() logger.get(),
'custom-type'
); );
}); });

View file

@ -121,9 +121,10 @@ export class LegacyClusterClient implements ILegacyClusterClient {
constructor( constructor(
private readonly config: LegacyElasticsearchClientConfig, private readonly config: LegacyElasticsearchClientConfig,
private readonly log: Logger, private readonly log: Logger,
private readonly type: string,
private readonly getAuthHeaders: GetAuthHeaders = noop private readonly getAuthHeaders: GetAuthHeaders = noop
) { ) {
this.client = new Client(parseElasticsearchClientConfig(config, log)); this.client = new Client(parseElasticsearchClientConfig(config, log, type));
} }
/** /**
@ -186,7 +187,7 @@ export class LegacyClusterClient implements ILegacyClusterClient {
// between all scoped client instances. // between all scoped client instances.
if (this.scopedClient === undefined) { if (this.scopedClient === undefined) {
this.scopedClient = new Client( this.scopedClient = new Client(
parseElasticsearchClientConfig(this.config, this.log, { parseElasticsearchClientConfig(this.config, this.log, this.type, {
auth: false, auth: false,
ignoreCertAndKey: !this.config.ssl || !this.config.ssl.alwaysPresentCertificate, ignoreCertAndKey: !this.config.ssl || !this.config.ssl.alwaysPresentCertificate,
}) })

View file

@ -22,13 +22,13 @@ test('parses minimally specified config', () => {
{ {
apiVersion: 'master', apiVersion: 'master',
customHeaders: { xsrf: 'something' }, customHeaders: { xsrf: 'something' },
logQueries: false,
sniffOnStart: false, sniffOnStart: false,
sniffOnConnectionFault: false, sniffOnConnectionFault: false,
hosts: ['http://localhost/elasticsearch'], hosts: ['http://localhost/elasticsearch'],
requestHeadersWhitelist: [], requestHeadersWhitelist: [],
}, },
logger.get() logger.get(),
'custom-type'
) )
).toMatchInlineSnapshot(` ).toMatchInlineSnapshot(`
Object { Object {
@ -58,7 +58,6 @@ test('parses fully specified config', () => {
const elasticsearchConfig: LegacyElasticsearchClientConfig = { const elasticsearchConfig: LegacyElasticsearchClientConfig = {
apiVersion: 'v7.0.0', apiVersion: 'v7.0.0',
customHeaders: { xsrf: 'something' }, customHeaders: { xsrf: 'something' },
logQueries: true,
sniffOnStart: true, sniffOnStart: true,
sniffOnConnectionFault: true, sniffOnConnectionFault: true,
hosts: [ hosts: [
@ -84,7 +83,8 @@ test('parses fully specified config', () => {
const elasticsearchClientConfig = parseElasticsearchClientConfig( const elasticsearchClientConfig = parseElasticsearchClientConfig(
elasticsearchConfig, elasticsearchConfig,
logger.get() logger.get(),
'custom-type'
); );
// Check that original references aren't used. // Check that original references aren't used.
@ -163,7 +163,6 @@ test('parses config timeouts of moment.Duration type', () => {
{ {
apiVersion: 'master', apiVersion: 'master',
customHeaders: { xsrf: 'something' }, customHeaders: { xsrf: 'something' },
logQueries: false,
sniffOnStart: false, sniffOnStart: false,
sniffOnConnectionFault: false, sniffOnConnectionFault: false,
pingTimeout: duration(100, 'ms'), pingTimeout: duration(100, 'ms'),
@ -172,7 +171,8 @@ test('parses config timeouts of moment.Duration type', () => {
hosts: ['http://localhost:9200/elasticsearch'], hosts: ['http://localhost:9200/elasticsearch'],
requestHeadersWhitelist: [], requestHeadersWhitelist: [],
}, },
logger.get() logger.get(),
'custom-type'
) )
).toMatchInlineSnapshot(` ).toMatchInlineSnapshot(`
Object { Object {
@ -208,7 +208,6 @@ describe('#auth', () => {
{ {
apiVersion: 'v7.0.0', apiVersion: 'v7.0.0',
customHeaders: { xsrf: 'something' }, customHeaders: { xsrf: 'something' },
logQueries: true,
sniffOnStart: true, sniffOnStart: true,
sniffOnConnectionFault: true, sniffOnConnectionFault: true,
hosts: ['http://user:password@localhost/elasticsearch', 'https://es.local'], hosts: ['http://user:password@localhost/elasticsearch', 'https://es.local'],
@ -217,6 +216,7 @@ describe('#auth', () => {
requestHeadersWhitelist: [], requestHeadersWhitelist: [],
}, },
logger.get(), logger.get(),
'custom-type',
{ auth: false } { auth: false }
) )
).toMatchInlineSnapshot(` ).toMatchInlineSnapshot(`
@ -260,7 +260,6 @@ describe('#auth', () => {
{ {
apiVersion: 'v7.0.0', apiVersion: 'v7.0.0',
customHeaders: { xsrf: 'something' }, customHeaders: { xsrf: 'something' },
logQueries: true,
sniffOnStart: true, sniffOnStart: true,
sniffOnConnectionFault: true, sniffOnConnectionFault: true,
hosts: ['https://es.local'], hosts: ['https://es.local'],
@ -268,6 +267,7 @@ describe('#auth', () => {
password: 'changeme', password: 'changeme',
}, },
logger.get(), logger.get(),
'custom-type',
{ auth: true } { auth: true }
) )
).toMatchInlineSnapshot(` ).toMatchInlineSnapshot(`
@ -300,7 +300,6 @@ describe('#auth', () => {
{ {
apiVersion: 'v7.0.0', apiVersion: 'v7.0.0',
customHeaders: { xsrf: 'something' }, customHeaders: { xsrf: 'something' },
logQueries: true,
sniffOnStart: true, sniffOnStart: true,
sniffOnConnectionFault: true, sniffOnConnectionFault: true,
hosts: ['https://es.local'], hosts: ['https://es.local'],
@ -308,6 +307,7 @@ describe('#auth', () => {
username: 'elastic', username: 'elastic',
}, },
logger.get(), logger.get(),
'custom-type',
{ auth: true } { auth: true }
) )
).toMatchInlineSnapshot(` ).toMatchInlineSnapshot(`
@ -342,13 +342,13 @@ describe('#customHeaders', () => {
{ {
apiVersion: 'master', apiVersion: 'master',
customHeaders: { [headerKey]: 'foo' }, customHeaders: { [headerKey]: 'foo' },
logQueries: false,
sniffOnStart: false, sniffOnStart: false,
sniffOnConnectionFault: false, sniffOnConnectionFault: false,
hosts: ['http://localhost/elasticsearch'], hosts: ['http://localhost/elasticsearch'],
requestHeadersWhitelist: [], requestHeadersWhitelist: [],
}, },
logger.get() logger.get(),
'custom-type'
); );
expect(parsedConfig.hosts[0].headers).toEqual({ expect(parsedConfig.hosts[0].headers).toEqual({
[headerKey]: 'foo', [headerKey]: 'foo',
@ -357,62 +357,18 @@ describe('#customHeaders', () => {
}); });
describe('#log', () => { describe('#log', () => {
test('default logger with #logQueries = false', () => { test('default logger', () => {
const parsedConfig = parseElasticsearchClientConfig( const parsedConfig = parseElasticsearchClientConfig(
{ {
apiVersion: 'master', apiVersion: 'master',
customHeaders: { xsrf: 'something' }, customHeaders: { xsrf: 'something' },
logQueries: false,
sniffOnStart: false, sniffOnStart: false,
sniffOnConnectionFault: false, sniffOnConnectionFault: false,
hosts: ['http://localhost/elasticsearch'], hosts: ['http://localhost/elasticsearch'],
requestHeadersWhitelist: [], requestHeadersWhitelist: [],
}, },
logger.get() logger.get(),
); 'custom-type'
const esLogger = new parsedConfig.log();
esLogger.error('some-error');
esLogger.warning('some-warning');
esLogger.trace('some-trace');
esLogger.info('some-info');
esLogger.debug('some-debug');
expect(typeof esLogger.close).toBe('function');
expect(loggingSystemMock.collect(logger)).toMatchInlineSnapshot(`
Object {
"debug": Array [],
"error": Array [
Array [
"some-error",
],
],
"fatal": Array [],
"info": Array [],
"log": Array [],
"trace": Array [],
"warn": Array [
Array [
"some-warning",
],
],
}
`);
});
test('default logger with #logQueries = true', () => {
const parsedConfig = parseElasticsearchClientConfig(
{
apiVersion: 'master',
customHeaders: { xsrf: 'something' },
logQueries: true,
sniffOnStart: false,
sniffOnConnectionFault: false,
hosts: ['http://localhost/elasticsearch'],
requestHeadersWhitelist: [],
},
logger.get()
); );
const esLogger = new parsedConfig.log(); const esLogger = new parsedConfig.log();
@ -433,11 +389,6 @@ describe('#log', () => {
"304 "304
METHOD /some-path METHOD /some-path
?query=2", ?query=2",
Object {
"tags": Array [
"query",
],
},
], ],
], ],
"error": Array [ "error": Array [
@ -465,14 +416,14 @@ describe('#log', () => {
{ {
apiVersion: 'master', apiVersion: 'master',
customHeaders: { xsrf: 'something' }, customHeaders: { xsrf: 'something' },
logQueries: true,
sniffOnStart: false, sniffOnStart: false,
sniffOnConnectionFault: false, sniffOnConnectionFault: false,
hosts: ['http://localhost/elasticsearch'], hosts: ['http://localhost/elasticsearch'],
requestHeadersWhitelist: [], requestHeadersWhitelist: [],
log: customLogger, log: customLogger,
}, },
logger.get() logger.get(),
'custom-type'
); );
expect(parsedConfig.log).toBe(customLogger); expect(parsedConfig.log).toBe(customLogger);
@ -486,14 +437,14 @@ describe('#ssl', () => {
{ {
apiVersion: 'v7.0.0', apiVersion: 'v7.0.0',
customHeaders: {}, customHeaders: {},
logQueries: true,
sniffOnStart: true, sniffOnStart: true,
sniffOnConnectionFault: true, sniffOnConnectionFault: true,
hosts: ['https://es.local'], hosts: ['https://es.local'],
requestHeadersWhitelist: [], requestHeadersWhitelist: [],
ssl: { verificationMode: 'none' }, ssl: { verificationMode: 'none' },
}, },
logger.get() logger.get(),
'custom-type'
) )
).toMatchInlineSnapshot(` ).toMatchInlineSnapshot(`
Object { Object {
@ -527,14 +478,14 @@ describe('#ssl', () => {
{ {
apiVersion: 'v7.0.0', apiVersion: 'v7.0.0',
customHeaders: {}, customHeaders: {},
logQueries: true,
sniffOnStart: true, sniffOnStart: true,
sniffOnConnectionFault: true, sniffOnConnectionFault: true,
hosts: ['https://es.local'], hosts: ['https://es.local'],
requestHeadersWhitelist: [], requestHeadersWhitelist: [],
ssl: { verificationMode: 'certificate' }, ssl: { verificationMode: 'certificate' },
}, },
logger.get() logger.get(),
'custom-type'
); );
// `checkServerIdentity` shouldn't check hostname when verificationMode is certificate. // `checkServerIdentity` shouldn't check hostname when verificationMode is certificate.
@ -576,14 +527,14 @@ describe('#ssl', () => {
{ {
apiVersion: 'v7.0.0', apiVersion: 'v7.0.0',
customHeaders: {}, customHeaders: {},
logQueries: true,
sniffOnStart: true, sniffOnStart: true,
sniffOnConnectionFault: true, sniffOnConnectionFault: true,
hosts: ['https://es.local'], hosts: ['https://es.local'],
requestHeadersWhitelist: [], requestHeadersWhitelist: [],
ssl: { verificationMode: 'full' }, ssl: { verificationMode: 'full' },
}, },
logger.get() logger.get(),
'custom-type'
) )
).toMatchInlineSnapshot(` ).toMatchInlineSnapshot(`
Object { Object {
@ -618,14 +569,14 @@ describe('#ssl', () => {
{ {
apiVersion: 'v7.0.0', apiVersion: 'v7.0.0',
customHeaders: {}, customHeaders: {},
logQueries: true,
sniffOnStart: true, sniffOnStart: true,
sniffOnConnectionFault: true, sniffOnConnectionFault: true,
hosts: ['https://es.local'], hosts: ['https://es.local'],
requestHeadersWhitelist: [], requestHeadersWhitelist: [],
ssl: { verificationMode: 'misspelled' as any }, ssl: { verificationMode: 'misspelled' as any },
}, },
logger.get() logger.get(),
'custom-type'
) )
).toThrowErrorMatchingInlineSnapshot(`"Unknown ssl verificationMode: misspelled"`); ).toThrowErrorMatchingInlineSnapshot(`"Unknown ssl verificationMode: misspelled"`);
}); });
@ -636,7 +587,6 @@ describe('#ssl', () => {
{ {
apiVersion: 'v7.0.0', apiVersion: 'v7.0.0',
customHeaders: {}, customHeaders: {},
logQueries: true,
sniffOnStart: true, sniffOnStart: true,
sniffOnConnectionFault: true, sniffOnConnectionFault: true,
hosts: ['https://es.local'], hosts: ['https://es.local'],
@ -651,6 +601,7 @@ describe('#ssl', () => {
}, },
}, },
logger.get(), logger.get(),
'custom-type',
{ ignoreCertAndKey: true } { ignoreCertAndKey: true }
) )
).toMatchInlineSnapshot(` ).toMatchInlineSnapshot(`

View file

@ -29,7 +29,6 @@ export type LegacyElasticsearchClientConfig = Pick<ConfigOptions, 'keepAlive' |
ElasticsearchConfig, ElasticsearchConfig,
| 'apiVersion' | 'apiVersion'
| 'customHeaders' | 'customHeaders'
| 'logQueries'
| 'requestHeadersWhitelist' | 'requestHeadersWhitelist'
| 'sniffOnStart' | 'sniffOnStart'
| 'sniffOnConnectionFault' | 'sniffOnConnectionFault'
@ -76,6 +75,7 @@ type ExtendedConfigOptions = ConfigOptions &
export function parseElasticsearchClientConfig( export function parseElasticsearchClientConfig(
config: LegacyElasticsearchClientConfig, config: LegacyElasticsearchClientConfig,
log: Logger, log: Logger,
type: string,
{ ignoreCertAndKey = false, auth = true }: LegacyElasticsearchClientConfigOverrides = {} { ignoreCertAndKey = false, auth = true }: LegacyElasticsearchClientConfigOverrides = {}
) { ) {
const esClientConfig: ExtendedConfigOptions = { const esClientConfig: ExtendedConfigOptions = {
@ -91,7 +91,7 @@ export function parseElasticsearchClientConfig(
}; };
if (esClientConfig.log == null) { if (esClientConfig.log == null) {
esClientConfig.log = getLoggerClass(log, config.logQueries); esClientConfig.log = getLoggerClass(log, type);
} }
if (config.pingTimeout != null) { if (config.pingTimeout != null) {
@ -180,7 +180,9 @@ function getDurationAsMs(duration: number | Duration) {
return duration.asMilliseconds(); return duration.asMilliseconds();
} }
function getLoggerClass(log: Logger, logQueries = false) { function getLoggerClass(log: Logger, type: string) {
const queryLogger = log.get('query', type);
return class ElasticsearchClientLogging { return class ElasticsearchClientLogging {
public error(err: string | Error) { public error(err: string | Error) {
log.error(err); log.error(err);
@ -197,11 +199,7 @@ function getLoggerClass(log: Logger, logQueries = false) {
_: unknown, _: unknown,
statusCode: string statusCode: string
) { ) {
if (logQueries) { queryLogger.debug(`${statusCode}\n${method} ${options.path}\n${query ? query.trim() : ''}`);
log.debug(`${statusCode}\n${method} ${options.path}\n${query ? query.trim() : ''}`, {
tags: ['query'],
});
}
} }
// elasticsearch-js expects the following functions to exist // elasticsearch-js expects the following functions to exist

View file

@ -843,7 +843,7 @@ export type ElasticsearchClient = Omit<KibanaClient, 'connectionPool' | 'transpo
}; };
// @public // @public
export type ElasticsearchClientConfig = Pick<ElasticsearchConfig, 'customHeaders' | 'logQueries' | 'sniffOnStart' | 'sniffOnConnectionFault' | 'requestHeadersWhitelist' | 'sniffInterval' | 'hosts' | 'username' | 'password'> & { export type ElasticsearchClientConfig = Pick<ElasticsearchConfig, 'customHeaders' | 'sniffOnStart' | 'sniffOnConnectionFault' | 'requestHeadersWhitelist' | 'sniffInterval' | 'hosts' | 'username' | 'password'> & {
pingTimeout?: ElasticsearchConfig['pingTimeout'] | ClientOptions['pingTimeout']; pingTimeout?: ElasticsearchConfig['pingTimeout'] | ClientOptions['pingTimeout'];
requestTimeout?: ElasticsearchConfig['requestTimeout'] | ClientOptions['requestTimeout']; requestTimeout?: ElasticsearchConfig['requestTimeout'] | ClientOptions['requestTimeout'];
ssl?: Partial<ElasticsearchConfig['ssl']>; ssl?: Partial<ElasticsearchConfig['ssl']>;
@ -859,7 +859,6 @@ export class ElasticsearchConfig {
readonly healthCheckDelay: Duration; readonly healthCheckDelay: Duration;
readonly hosts: string[]; readonly hosts: string[];
readonly ignoreVersionMismatch: boolean; readonly ignoreVersionMismatch: boolean;
readonly logQueries: boolean;
readonly password?: string; readonly password?: string;
readonly pingTimeout: Duration; readonly pingTimeout: Duration;
readonly requestHeadersWhitelist: string[]; readonly requestHeadersWhitelist: string[];
@ -1531,7 +1530,7 @@ export interface LegacyCallAPIOptions {
// @public @deprecated // @public @deprecated
export class LegacyClusterClient implements ILegacyClusterClient { export class LegacyClusterClient implements ILegacyClusterClient {
constructor(config: LegacyElasticsearchClientConfig, log: Logger, getAuthHeaders?: GetAuthHeaders); constructor(config: LegacyElasticsearchClientConfig, log: Logger, type: string, getAuthHeaders?: GetAuthHeaders);
asScoped(request?: ScopeableRequest): ILegacyScopedClusterClient; asScoped(request?: ScopeableRequest): ILegacyScopedClusterClient;
// @deprecated // @deprecated
callAsInternalUser: LegacyAPICaller; callAsInternalUser: LegacyAPICaller;
@ -1553,7 +1552,7 @@ export interface LegacyConfig {
} }
// @public @deprecated (undocumented) // @public @deprecated (undocumented)
export type LegacyElasticsearchClientConfig = Pick<ConfigOptions, 'keepAlive' | 'log' | 'plugins'> & Pick<ElasticsearchConfig, 'apiVersion' | 'customHeaders' | 'logQueries' | 'requestHeadersWhitelist' | 'sniffOnStart' | 'sniffOnConnectionFault' | 'hosts' | 'username' | 'password'> & { export type LegacyElasticsearchClientConfig = Pick<ConfigOptions, 'keepAlive' | 'log' | 'plugins'> & Pick<ElasticsearchConfig, 'apiVersion' | 'customHeaders' | 'requestHeadersWhitelist' | 'sniffOnStart' | 'sniffOnConnectionFault' | 'hosts' | 'username' | 'password'> & {
pingTimeout?: ElasticsearchConfig['pingTimeout'] | ConfigOptions['pingTimeout']; pingTimeout?: ElasticsearchConfig['pingTimeout'] | ConfigOptions['pingTimeout'];
requestTimeout?: ElasticsearchConfig['requestTimeout'] | ConfigOptions['requestTimeout']; requestTimeout?: ElasticsearchConfig['requestTimeout'] | ConfigOptions['requestTimeout'];
sniffInterval?: ElasticsearchConfig['sniffInterval'] | ConfigOptions['sniffInterval']; sniffInterval?: ElasticsearchConfig['sniffInterval'] | ConfigOptions['sniffInterval'];

View file

@ -30,7 +30,6 @@ export function instantiateClient(
const cluster = createClient('monitoring', { const cluster = createClient('monitoring', {
...(isMonitoringCluster ? elasticsearchConfig : {}), ...(isMonitoringCluster ? elasticsearchConfig : {}),
plugins: [monitoringBulk, monitoringEndpointDisableWatches], plugins: [monitoringBulk, monitoringEndpointDisableWatches],
logQueries: Boolean(elasticsearchConfig.logQueries),
} as ESClusterConfig); } as ESClusterConfig);
const configSource = isMonitoringCluster ? 'monitoring' : 'production'; const configSource = isMonitoringCluster ? 'monitoring' : 'production';