Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 15 additions & 10 deletions packages/instrumentation-pino/src/instrumentation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,12 @@ export class PinoInstrumentation extends InstrumentationBase<PinoInstrumentation
level: number,
...rest: unknown[]
) => {
return Object.assign(
otelMixin(ctx, level),
origMixin(ctx, level, ...rest)
);
const otelMixinResult = otelMixin(ctx, level);
if (config.passLogCorrelationToMixin) {
return origMixin(otelMixinResult, level, ...rest);
} else {
return Object.assign(otelMixinResult, origMixin(ctx, level, ...rest));
}
};
}

Expand Down Expand Up @@ -184,14 +186,17 @@ export class PinoInstrumentation extends InstrumentationBase<PinoInstrumentation
return {};
}

const logKeys = instrumentation.getConfig().logKeys ?? DEFAULT_LOG_KEYS;

const record = {
[logKeys.traceId]: spanContext.traceId,
[logKeys.spanId]: spanContext.spanId,
[logKeys.traceFlags]: `0${spanContext.traceFlags.toString(16)}`,
const logKeys = {
...DEFAULT_LOG_KEYS,
...instrumentation.getConfig().logKeys,
};

const record: Record<string, string> = {};
if (logKeys.traceId) record[logKeys.traceId] = spanContext.traceId;
if (logKeys.spanId) record[logKeys.spanId] = spanContext.spanId;
if (logKeys.traceFlags)
record[logKeys.traceFlags] = `0${spanContext.traceFlags.toString(16)}`;

instrumentation._callHook(span, record, level);

return record;
Expand Down
13 changes: 10 additions & 3 deletions packages/instrumentation-pino/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ export interface PinoInstrumentationConfig extends InstrumentationConfig {
*/
disableLogCorrelation?: boolean;

/**
* Whether to pass the injected trace-context fields into the
* mixin function's context.
* @default false
*/
passLogCorrelationToMixin?: boolean;

/**
* A function that allows injecting additional fields in log records. It is
* called, as `logHook(span, record)`, for each log record emitted in a valid
Expand All @@ -50,8 +57,8 @@ export interface PinoInstrumentationConfig extends InstrumentationConfig {
* available.
*/
logKeys?: {
traceId: string;
spanId: string;
traceFlags: string;
traceId?: string;
spanId?: string;
traceFlags?: string;
};
}
87 changes: 87 additions & 0 deletions packages/instrumentation-pino/test/pino.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,47 @@ describe('PinoInstrumentation', () => {
});
});

it('injects span context to records with partial custom keys', () => {
const logKeys = {
traceId: 'traceId',
spanId: 'spanId',
};
instrumentation.setConfig({ logKeys });
tracer.startActiveSpan('abc', span => {
logger.info('a message');
span.end();

sinon.assert.calledOnce(writeSpy);
const record = JSON.parse(writeSpy.firstCall.args[0].toString());
const { traceId, spanId, traceFlags } = span.spanContext();
assert.strictEqual(record['traceId'], traceId);
assert.strictEqual(record['spanId'], spanId);
assert.strictEqual(record['trace_id'], undefined);
assert.strictEqual(record['span_id'], undefined);
assert.strictEqual(record['trace_flags'], traceFlags);
assert.strictEqual(record['msg'], 'a message');
});
});

it('injects span context to records with an explicitly undefined custom key', () => {
const logKeys = {
traceFlags: undefined,
};
instrumentation.setConfig({ logKeys });
tracer.startActiveSpan('abc', span => {
logger.info('a message');
span.end();

sinon.assert.calledOnce(writeSpy);
const record = JSON.parse(writeSpy.firstCall.args[0].toString());
const { traceId, spanId } = span.spanContext();
assert.strictEqual(record['trace_id'], traceId);
assert.strictEqual(record['span_id'], spanId);
assert.strictEqual(record['trace_flags'], undefined);
assert.strictEqual(record['msg'], 'a message');
});
});

it('injects span context to child logger records', () => {
const child = logger.child({ childField: 42 });
tracer.startActiveSpan('abc', span => {
Expand Down Expand Up @@ -440,6 +481,52 @@ describe('PinoInstrumentation', () => {
assert.strictEqual(record['span_id'], spanId);
});
});

it('ensures user mixin can override values', () => {
const logger = pino(
{
mixin(mergeObject: object) {
return { ...mergeObject, trace_id: '123' };
},
},
process.stdout
);
instrumentation.setConfig({
passLogCorrelationToMixin: true,
});
tracer.startActiveSpan('abc', span => {
logger.info('a message');
span.end();

const { spanId } = span.spanContext();
const record = JSON.parse(stdoutSpy.firstCall.args[0].toString());
assert.strictEqual(record['trace_id'], '123');
assert.strictEqual(record['span_id'], spanId);
});
});

it('ensures user mixin can eliminate values', () => {
const logger = pino(
{
mixin(mergeObject: object) {
return { ...mergeObject, trace_id: undefined };
},
},
process.stdout
);
instrumentation.setConfig({
passLogCorrelationToMixin: true,
});
tracer.startActiveSpan('abc', span => {
logger.info('a message');
span.end();

const { spanId } = span.spanContext();
const record = JSON.parse(stdoutSpy.firstCall.args[0].toString());
assert.strictEqual(record['trace_id'], undefined);
assert.strictEqual(record['span_id'], spanId);
});
});
});

describe('log sending', () => {
Expand Down