Skip to content

Instantly share code, notes, and snippets.

@gkampitakis
Created February 4, 2022 20:49
Show Gist options
  • Save gkampitakis/b36819f38f8886598c20ed1af7245e3a to your computer and use it in GitHub Desktop.
Save gkampitakis/b36819f38f8886598c20ed1af7245e3a to your computer and use it in GitHub Desktop.
pino-http ECS compliant
import { Options, pinoHttp } from 'pino-http';
import { formatError } from '@elastic/ecs-helpers';
// Taken as it is from @elastic/ecs-pino-format
function bindings(bindingsObject: Record<string, unknown>) {
const { pid, hostname, ...ecsBindings } = bindingsObject;
if (pid !== undefined) {
ecsBindings.process = { pid };
}
if (hostname !== undefined) {
ecsBindings.host = { hostname };
}
return ecsBindings;
}
export const options = (options?: Options): Options => ({
...options,
customAttributeKeys: {
req: 'http.request',
res: 'http.response',
responseTime: 'event.duration',
},
messageKey: 'message',
timestamp: () => `"@timestamp":"${new Date().toISOString()}"`,
serializers: {
'http.response': (object) => {
const { statusCode, ...response } = object;
return {
...response,
status_code: statusCode,
};
},
'http.request': () => {
// here you can perform headers transformation
}
},
formatters: {
bindings,
level: (label: string) => ({ 'log.level': label }),
log: (o: object) => {
const { error, ...ecsObject } = o;
ecsObject.ecs = { version: '1.6.0' };
formatError(ecsObject, error);
return ecsObject;
}
}
});
const { logger } = pinoHttp(options());
logger.info({
test: 'test'
}, 'msg');
@fourthdimension
Copy link

fourthdimension commented Mar 16, 2023

// When used with NestJS 9+, in app.module.ts

import { LoggerModule } from 'nestjs-pino';
//@ts-ignore
import { formatError } from '@elastic/ecs-helpers';

@Module({
    imports: [
        LoggerModule.forRoot({
            pinoHttp: [
                {
                    level: process.env.NODE_ENV !== 'production' ? 'debug' : 'info',
                    // install 'pino-pretty' package in order to use the following option
                    transport: process.env.NODE_ENV !== 'production' ? { target: 'pino-pretty' } : undefined,
                    customAttributeKeys: {
                        req: 'http.request',
                        res: 'http.response',
                        responseTime: 'event.duration',
                    },
                    messageKey: 'message',
                    timestamp: () => `,"@timestamp":"${new Date().toISOString()}"`,
                    serializers: {
                        'http.response': (object: any) => {
                            const { statusCode, ...response } = object;
                            return {
                                ...response,
                                status_code: statusCode,
                            };
                        },
                        'http.request': () => {
                            // here you can perform headers transformation
                        },
                    },
                    formatters: {
                        bindings(bindings: Record<string, unknown>) {
                            const {
                                // `pid` and `hostname` are default bindings, unless overriden by
                                // a `base: {...}` passed to logger creation.
                                pid,
                                hostname,
                                // name is defined if `log = pino({name: 'my name', ...})`
                                name,
                                // Warning: silently drop any "ecs" value from `base`. See
                                // "ecs.version" comment below.
                                ecs,
                                ...ecsBindings
                            } = bindings;
                            if (pid !== undefined) {
                                // https://www.elastic.co/guide/en/ecs/current/ecs-process.html#field-process-pid
                                ecsBindings.process = { pid: pid };
                            }
                            if (hostname !== undefined) {
                                // https://www.elastic.co/guide/en/ecs/current/ecs-host.html#field-host-hostname
                                ecsBindings.host = { hostname: hostname };
                            }
                            if (name !== undefined) {
                                // https://www.elastic.co/guide/en/ecs/current/ecs-log.html#field-log-logger
                                ecsBindings.log = { logger: name };
                            }
                            return ecsBindings;
                        },
                        level: (label: string) => ({ 'log.level': label }),
                        log: (o: object) => {
                            //@ts-ignore
                            const { error, ...ecsObject } = o;
                            //@ts-ignore
                            ecsObject.ecs = { version: '1.6.0' };
                            formatError(ecsObject, error);
                            return ecsObject;
                        },
                    },
                },
            ],
        })
     ]
})
export class AppModule {}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment