import querystring from 'querystring' ; import { isBoom } from '@hapi/boom' ; import type { Request } from '@hapi/hapi' ; import numeral from '@elastic/numeral' ; import { LogMeta } from '@kbn/logging' ; import { Logger } from '../../logging' ; import { getResponsePayloadBytes } from './get_payload_size' ; import type { KibanaRequestState } from '../router' ; const FORBIDDEN_HEADERS = [ 'authorization' , 'cookie' , 'set-cookie' ] ; const REDACTED_HEADER_TEXT = '[REDACTED]' ; type HapiHeaders = Record < string , string | string [ ] > ; function redactSensitiveHeaders ( key , value ) { return FORBIDDEN_HEADERS . includes ( key ) ? REDACTED_HEADER_TEXT : value ; } function cloneAndFilterHeaders ( headers ? ) { const result = { } as HapiHeaders ; if ( headers ) { for ( const key of Object . keys ( headers ) ) { result [ key ] = redactSensitiveHeaders ( key , Array . isArray ( headers [ key ] ) ? [ ... headers [ key ] ] : headers [ key ] ) ; } } return result ; } internal export function getEcsResponseLog ( request , log ) { const { path , response } = request ; const method = request . method . toUpperCase ( ) ; const query = querystring . stringify ( request . query ) ; const pathWithQuery = query . length > 0 ? `${ path }?${ query }` : path ; const status_code = isBoom ( response ) ? response . output . statusCode : response . statusCode ; const requestHeaders = cloneAndFilterHeaders ( request . headers ) ; const responseHeaders = cloneAndFilterHeaders ( isBoom ( response ) ? ( response . output . headers as HapiHeaders ) : response . headers ) ; const responseTime = ( request . info . completed || request . info . responded ) - request . info . received ; const responseTimeMsg = ! isNaN ( responseTime ) ? ` ${ responseTime }ms` : '' ; const bytes = getResponsePayloadBytes ( response , log ) ; const bytesMsg = bytes ? ` - ${ numeral ( bytes ) . format ( '0.0b' ) }` : '' ; const traceId = ( request . app as KibanaRequestState ) . traceId ; const meta = { client : { ip : request . info . remoteAddress , } , http : { request : { method , mime_type : request . mime , referrer : request . info . referrer , headers : requestHeaders , } , response : { body : { bytes , } , status_code , headers : responseHeaders , responseTime : ! isNaN ( responseTime ) ? responseTime : undefined , } , } , url : { path , query , } , user_agent : { original : request . headers [ 'user-agent' ] , } , trace : traceId ? { id : traceId } : undefined , } ; return { message : `${ method } ${ pathWithQuery } ${ status_code }${ responseTimeMsg }${ bytesMsg }` , meta , } ; }