Skip to content
Merged
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
19 changes: 18 additions & 1 deletion src/hooks/telemetryPrerun.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,26 @@ declare const global: TelemetryGlobal;
type CommonData = {
nodeVersion: string;
plugin?: string;

plugin_version?: string;
command?: string;
traceId?: string;
parentSpanId?: string;
traceFlags?: string;
};

const TRACEPARENT_RE = /^([0-9a-f]{2})-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})$/i;

export function parseTraceParent(raw: string | undefined): Pick<CommonData, 'traceId' | 'parentSpanId' | 'traceFlags'> {
if (!raw) return {};
const match = TRACEPARENT_RE.exec(raw.trim());
if (!match || match[1].toLowerCase() === 'ff') return {};
const traceId = match[2].toLowerCase();
const parentSpanId = match[3].toLowerCase();
if (/^0+$/.test(traceId) || /^0+$/.test(parentSpanId)) return {};
return { traceId, parentSpanId, traceFlags: match[4].toLowerCase() };
}

/**
* A hook that runs before every command that:
* 1. Warns the user about command usage data collection the CLI does unless they have already acknowledged the warning.
Expand Down Expand Up @@ -178,6 +194,7 @@ const hook: Hook.Prerun = async function (options): Promise<void> {
// eslint-disable-next-line camelcase
plugin_version: pluginInfo.version,
command: commandExecution.getCommandName(),
...parseTraceParent(process.env.TRACEPARENT),
};
}
return commonData;
Expand Down
59 changes: 58 additions & 1 deletion test/hooks/telemetryPrerun.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { expect } from 'chai';
import sinon from 'sinon';
import Telemetry from '../../src/telemetry.js';
import { CommandExecution } from '../../src/commandExecution.js';
import hook from '../../src/hooks/telemetryPrerun.js';
import hook, { parseTraceParent } from '../../src/hooks/telemetryPrerun.js';
import { MyCommand } from '../helpers/myCommand.js';

const args = { argv: [], Command: MyCommand, config: {} as Config, context: {} as Hook.Context };
Expand Down Expand Up @@ -137,3 +137,60 @@ describe('telemetry prerun hook', () => {
});
});
});

describe('parseTraceParent', () => {
it('returns trace fields for a valid traceparent', () => {
const result = parseTraceParent('00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01');
expect(result).to.deep.equal({
traceId: '0af7651916cd43dd8448eb211c80319c',
parentSpanId: 'b7ad6b7169203331',
traceFlags: '01',
});
});

it('returns empty object for undefined', () => {
expect(parseTraceParent(undefined)).to.deep.equal({});
});

it('returns empty object for empty string', () => {
expect(parseTraceParent('')).to.deep.equal({});
});

it('returns empty object for invalid format', () => {
expect(parseTraceParent('not-valid')).to.deep.equal({});
});

it('rejects version ff', () => {
expect(parseTraceParent('ff-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01')).to.deep.equal({});
});

it('rejects uppercase version FF', () => {
expect(parseTraceParent('FF-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01')).to.deep.equal({});
});

it('rejects all-zero trace-id', () => {
expect(parseTraceParent('00-00000000000000000000000000000000-b7ad6b7169203331-01')).to.deep.equal({});
});

it('rejects all-zero parent-id', () => {
expect(parseTraceParent('00-0af7651916cd43dd8448eb211c80319c-0000000000000000-01')).to.deep.equal({});
});

it('handles uppercase hex by normalizing to lowercase', () => {
const result = parseTraceParent('00-0AF7651916CD43DD8448EB211C80319C-B7AD6B7169203331-01');
expect(result).to.deep.equal({
traceId: '0af7651916cd43dd8448eb211c80319c',
parentSpanId: 'b7ad6b7169203331',
traceFlags: '01',
});
});

it('trims whitespace', () => {
const result = parseTraceParent(' 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01 ');
expect(result).to.deep.equal({
traceId: '0af7651916cd43dd8448eb211c80319c',
parentSpanId: 'b7ad6b7169203331',
traceFlags: '01',
});
});
});
Loading