Skip to content

Commit 463efb9

Browse files
committed
log request body in new ES client
1 parent b913f21 commit 463efb9

File tree

2 files changed

+174
-44
lines changed

2 files changed

+174
-44
lines changed

src/core/server/elasticsearch/client/configure_client.test.ts

Lines changed: 159 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@
1616
* specific language governing permissions and limitations
1717
* under the License.
1818
*/
19+
import { Buffer } from 'buffer';
20+
import { Readable } from 'stream';
1921

2022
import { RequestEvent, errors } from '@elastic/elasticsearch';
21-
import { TransportRequestParams } from '@elastic/elasticsearch/lib/Transport';
23+
import { TransportRequestParams, RequestBody } from '@elastic/elasticsearch/lib/Transport';
2224

2325
import { parseClientOptionsMock, ClientMock } from './configure_client.test.mocks';
2426
import { loggingSystemMock } from '../../logging/logging_system.mock';
@@ -195,40 +197,158 @@ describe('configureClient', () => {
195197
`);
196198
});
197199

198-
it('logs each queries if `logQueries` is true', () => {
199-
const client = configureClient(
200-
createFakeConfig({
201-
logQueries: true,
202-
}),
203-
{ logger, scoped: false }
204-
);
200+
describe('logs each queries if `logQueries` is true', () => {
201+
function createResponseWithBody(body: RequestBody) {
202+
return createApiResponse({
203+
body: {},
204+
statusCode: 200,
205+
params: {
206+
method: 'GET',
207+
path: '/foo',
208+
querystring: { hello: 'dolly' },
209+
body,
210+
},
211+
});
212+
}
213+
214+
it('when request body is an object', () => {
215+
const client = configureClient(
216+
createFakeConfig({
217+
logQueries: true,
218+
}),
219+
{ logger, scoped: false }
220+
);
221+
222+
const response = createResponseWithBody({
223+
seq_no_primary_term: true,
224+
query: {
225+
term: { user: 'kimchy' },
226+
},
227+
});
228+
229+
client.emit('response', null, response);
230+
expect(loggingSystemMock.collect(logger).debug).toMatchInlineSnapshot(`
231+
Array [
232+
Array [
233+
"200
234+
GET /foo?hello=dolly
235+
{\\"seq_no_primary_term\\":true,\\"query\\":{\\"term\\":{\\"user\\":\\"kimchy\\"}}}",
236+
Object {
237+
"tags": Array [
238+
"query",
239+
],
240+
},
241+
],
242+
]
243+
`);
244+
});
205245

206-
const response = createApiResponse({
207-
body: {},
208-
statusCode: 200,
209-
params: {
210-
method: 'GET',
211-
path: '/foo',
212-
querystring: { hello: 'dolly' },
213-
},
246+
it('when request body is a string', () => {
247+
const client = configureClient(
248+
createFakeConfig({
249+
logQueries: true,
250+
}),
251+
{ logger, scoped: false }
252+
);
253+
254+
const response = createResponseWithBody(
255+
JSON.stringify({
256+
seq_no_primary_term: true,
257+
query: {
258+
term: { user: 'kimchy' },
259+
},
260+
})
261+
);
262+
263+
client.emit('response', null, response);
264+
expect(loggingSystemMock.collect(logger).debug).toMatchInlineSnapshot(`
265+
Array [
266+
Array [
267+
"200
268+
GET /foo?hello=dolly
269+
{\\"seq_no_primary_term\\":true,\\"query\\":{\\"term\\":{\\"user\\":\\"kimchy\\"}}}",
270+
Object {
271+
"tags": Array [
272+
"query",
273+
],
274+
},
275+
],
276+
]
277+
`);
214278
});
215279

216-
client.emit('response', null, response);
280+
it('when request body is a buffer', () => {
281+
const client = configureClient(
282+
createFakeConfig({
283+
logQueries: true,
284+
}),
285+
{ logger, scoped: false }
286+
);
287+
288+
const response = createResponseWithBody(
289+
Buffer.from(
290+
JSON.stringify({
291+
seq_no_primary_term: true,
292+
query: {
293+
term: { user: 'kimchy' },
294+
},
295+
})
296+
)
297+
);
298+
299+
client.emit('response', null, response);
300+
expect(loggingSystemMock.collect(logger).debug).toMatchInlineSnapshot(`
301+
Array [
302+
Array [
303+
"200
304+
GET /foo?hello=dolly
305+
[buffer]",
306+
Object {
307+
"tags": Array [
308+
"query",
309+
],
310+
},
311+
],
312+
]
313+
`);
314+
});
217315

218-
expect(loggingSystemMock.collect(logger).debug).toMatchInlineSnapshot(`
219-
Array [
316+
it('when request body is a readable stream', () => {
317+
const client = configureClient(
318+
createFakeConfig({
319+
logQueries: true,
320+
}),
321+
{ logger, scoped: false }
322+
);
323+
324+
const response = createResponseWithBody(
325+
// @ts-expect-error definition doesn't know about from
326+
Readable.from(
327+
JSON.stringify({
328+
seq_no_primary_term: true,
329+
query: {
330+
term: { user: 'kimchy' },
331+
},
332+
})
333+
)
334+
);
335+
336+
client.emit('response', null, response);
337+
expect(loggingSystemMock.collect(logger).debug).toMatchInlineSnapshot(`
220338
Array [
221-
"200
222-
GET /foo
223-
hello=dolly",
224-
Object {
225-
"tags": Array [
226-
"query",
227-
],
228-
},
229-
],
230-
]
231-
`);
339+
Array [
340+
"200
341+
GET /foo?hello=dolly
342+
[stream]",
343+
Object {
344+
"tags": Array [
345+
"query",
346+
],
347+
},
348+
],
349+
]
350+
`);
351+
});
232352
});
233353

234354
it('properly encode queries', () => {
@@ -255,8 +375,7 @@ describe('configureClient', () => {
255375
Array [
256376
Array [
257377
"200
258-
GET /foo
259-
city=M%C3%BCnich",
378+
GET /foo?city=M%C3%BCnich",
260379
Object {
261380
"tags": Array [
262381
"query",
@@ -286,6 +405,12 @@ describe('configureClient', () => {
286405
method: 'GET',
287406
path: '/foo',
288407
querystring: { hello: 'dolly' },
408+
body: {
409+
seq_no_primary_term: true,
410+
query: {
411+
term: { user: 'kimchy' },
412+
},
413+
},
289414
},
290415
});
291416
client.emit('response', new errors.ResponseError(response), response);
@@ -294,8 +419,8 @@ describe('configureClient', () => {
294419
Array [
295420
Array [
296421
"500
297-
GET /foo
298-
hello=dolly",
422+
GET /foo?hello=dolly
423+
{\\"seq_no_primary_term\\":true,\\"query\\":{\\"term\\":{\\"user\\":\\"kimchy\\"}}}",
299424
Object {
300425
"tags": Array [
301426
"query",

src/core/server/elasticsearch/client/configure_client.ts

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@
1616
* specific language governing permissions and limitations
1717
* under the License.
1818
*/
19-
19+
import { Buffer } from 'buffer';
2020
import { stringify } from 'querystring';
2121
import { Client } from '@elastic/elasticsearch';
22+
import { RequestBody } from '@elastic/elasticsearch/lib/Transport';
23+
2224
import { Logger } from '../../logging';
2325
import { parseClientOptions, ElasticsearchClientConfig } from './client_config';
2426

@@ -48,15 +50,11 @@ const addLogging = (client: Client, logger: Logger, logQueries: boolean) => {
4850

4951
// definition is wrong, `params.querystring` can be either a string or an object
5052
const querystring = convertQueryString(params.querystring);
51-
52-
logger.debug(
53-
`${event.statusCode}\n${params.method} ${params.path}${
54-
querystring ? `\n${querystring}` : ''
55-
}`,
56-
{
57-
tags: ['query'],
58-
}
59-
);
53+
const url = `${params.path}${querystring ? `?${querystring}` : ''}`;
54+
const body = params.body ? `\n${ensureString(params.body)}` : '';
55+
logger.debug(`${event.statusCode}\n${params.method} ${url}${body}`, {
56+
tags: ['query'],
57+
});
6058
}
6159
});
6260
};
@@ -67,3 +65,10 @@ const convertQueryString = (qs: string | Record<string, any> | undefined): strin
6765
}
6866
return stringify(qs);
6967
};
68+
69+
function ensureString(body: RequestBody): string {
70+
if (typeof body === 'string') return body;
71+
if (Buffer.isBuffer(body)) return '[buffer]';
72+
if ('readable' in body && body.readable && typeof body._read === 'function') return '[stream]';
73+
return JSON.stringify(body);
74+
}

0 commit comments

Comments
 (0)