-
Notifications
You must be signed in to change notification settings - Fork 8.5k
[core.logging] Add response logs to the KP logging system. #87939
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
5d7d1ee
POC for KP response logging.
lukeelmers 73c7a3b
Add unit tests.
lukeelmers 452d580
Add integration tests.
lukeelmers e3828f1
Update payload size logic.
lukeelmers a036a53
Add config deprecations for logging.events.response.
lukeelmers 638d524
Update docs.
lukeelmers 1a29686
Disable legacy response logs when logging.verbose=true
lukeelmers c95fca8
Fix legacy response logs payload size.
lukeelmers 3c578c8
Move ECS typings to logging service.
lukeelmers 8da8fae
Rename logger context to http.server.response
lukeelmers 6fd3deb
Address get_response_log feedback.
lukeelmers 5239bba
Log errors when calculating payload bytes.
lukeelmers 64d3393
Refactor logic for calculating response payload.
lukeelmers f3067a6
Update docs.
lukeelmers 2283752
Address feedback.
lukeelmers 5d87516
Address remaining feedback.
lukeelmers a41dbd5
Merge branch 'master' into feat/logging-requests
kibanamachine 871da2d
Merge branch 'master' into feat/logging-requests
kibanamachine 0811e30
Update license headers.
lukeelmers File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
101 changes: 101 additions & 0 deletions
101
packages/kbn-legacy-logging/src/utils/get_payload_size.test.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| /* | ||
| * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
| * or more contributor license agreements. Licensed under the Elastic License | ||
| * 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
| * in compliance with, at your election, the Elastic License 2.0 or the Server | ||
| * Side Public License, v 1. | ||
| */ | ||
|
|
||
| import mockFs from 'mock-fs'; | ||
| import { createReadStream } from 'fs'; | ||
|
|
||
| import { getResponsePayloadBytes } from './get_payload_size'; | ||
|
|
||
| describe('getPayloadSize', () => { | ||
| describe('handles Buffers', () => { | ||
| test('with ascii characters', () => { | ||
| const payload = 'heya'; | ||
| const result = getResponsePayloadBytes(Buffer.from(payload)); | ||
| expect(result).toBe(4); | ||
| }); | ||
|
|
||
| test('with special characters', () => { | ||
| const payload = '¡hola!'; | ||
| const result = getResponsePayloadBytes(Buffer.from(payload)); | ||
| expect(result).toBe(7); | ||
| }); | ||
| }); | ||
|
|
||
| describe('handles fs streams', () => { | ||
| afterEach(() => mockFs.restore()); | ||
|
|
||
| test('with ascii characters', async () => { | ||
| mockFs({ 'test.txt': 'heya' }); | ||
| const readStream = createReadStream('test.txt'); | ||
|
|
||
| let data = ''; | ||
| for await (const chunk of readStream) { | ||
| data += chunk; | ||
| } | ||
|
|
||
| const result = getResponsePayloadBytes(readStream); | ||
| expect(result).toBe(Buffer.byteLength(data)); | ||
| }); | ||
|
|
||
| test('with special characters', async () => { | ||
| mockFs({ 'test.txt': '¡hola!' }); | ||
| const readStream = createReadStream('test.txt'); | ||
|
|
||
| let data = ''; | ||
| for await (const chunk of readStream) { | ||
| data += chunk; | ||
| } | ||
|
|
||
| const result = getResponsePayloadBytes(readStream); | ||
| expect(result).toBe(Buffer.byteLength(data)); | ||
| }); | ||
| }); | ||
|
|
||
| describe('handles plain responses', () => { | ||
| test('when source is text', () => { | ||
| const result = getResponsePayloadBytes('heya'); | ||
| expect(result).toBe(4); | ||
| }); | ||
|
|
||
| test('when source contains special characters', () => { | ||
| const result = getResponsePayloadBytes('¡hola!'); | ||
| expect(result).toBe(7); | ||
| }); | ||
|
|
||
| test('when source is object', () => { | ||
| const payload = { message: 'heya' }; | ||
| const result = getResponsePayloadBytes(payload); | ||
| expect(result).toBe(JSON.stringify(payload).length); | ||
| }); | ||
| }); | ||
|
|
||
| describe('handles content-length header', () => { | ||
| test('always provides content-length header if available', () => { | ||
| const headers = { 'content-length': '123' }; | ||
| const result = getResponsePayloadBytes('heya', headers); | ||
| expect(result).toBe(123); | ||
| }); | ||
|
|
||
| test('uses first value when hapi header is an array', () => { | ||
| const headers = { 'content-length': ['123', '456'] }; | ||
| const result = getResponsePayloadBytes(null, headers); | ||
| expect(result).toBe(123); | ||
| }); | ||
|
|
||
| test('returns undefined if length is NaN', () => { | ||
| const headers = { 'content-length': 'oops' }; | ||
| const result = getResponsePayloadBytes(null, headers); | ||
| expect(result).toBeUndefined(); | ||
| }); | ||
| }); | ||
|
|
||
| test('defaults to undefined', () => { | ||
| const result = getResponsePayloadBytes(null); | ||
| expect(result).toBeUndefined(); | ||
| }); | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| /* | ||
| * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
| * or more contributor license agreements. Licensed under the Elastic License | ||
| * 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
| * in compliance with, at your election, the Elastic License 2.0 or the Server | ||
| * Side Public License, v 1. | ||
| */ | ||
|
|
||
| import type { ReadStream } from 'fs'; | ||
| import type { ResponseObject } from '@hapi/hapi'; | ||
|
|
||
| const isBuffer = (obj: unknown): obj is Buffer => Buffer.isBuffer(obj); | ||
| const isObject = (obj: unknown): obj is Record<string, unknown> => | ||
| typeof obj === 'object' && obj !== null; | ||
| const isFsReadStream = (obj: unknown): obj is ReadStream => | ||
| typeof obj === 'object' && obj !== null && 'bytesRead' in obj; | ||
| const isString = (obj: unknown): obj is string => typeof obj === 'string'; | ||
|
|
||
| /** | ||
| * Attempts to determine the size (in bytes) of a hapi/good | ||
| * responsePayload based on the payload type. Falls back to | ||
| * `undefined` if the size cannot be determined. | ||
| * | ||
| * This is similar to the implementation in `core/server/http/logging`, | ||
| * however it uses more duck typing as we do not have access to the | ||
| * entire hapi request object like we do in the HttpServer. | ||
lukeelmers marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| * | ||
| * @param headers responseHeaders from hapi/good event | ||
| * @param payload responsePayload from hapi/good event | ||
| * | ||
| * @internal | ||
| */ | ||
| export function getResponsePayloadBytes( | ||
| payload: ResponseObject['source'], | ||
| headers: Record<string, any> = {} | ||
| ): number | undefined { | ||
| const contentLength = headers['content-length']; | ||
| if (contentLength) { | ||
| const val = parseInt( | ||
| // hapi response headers can be `string | string[]`, so we need to handle both cases | ||
| Array.isArray(contentLength) ? String(contentLength) : contentLength, | ||
| 10 | ||
| ); | ||
| return !isNaN(val) ? val : undefined; | ||
| } | ||
|
|
||
| if (isBuffer(payload)) { | ||
| return payload.byteLength; | ||
| } | ||
|
|
||
| if (isFsReadStream(payload)) { | ||
| return payload.bytesRead; | ||
| } | ||
|
|
||
| if (isString(payload)) { | ||
| return Buffer.byteLength(payload); | ||
| } | ||
|
|
||
| if (isObject(payload)) { | ||
| return Buffer.byteLength(JSON.stringify(payload)); | ||
| } | ||
|
|
||
| return undefined; | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.