Skip to content

Commit

Permalink
feat: add support for loading a tracing baggage dump in wc3 baggage f…
Browse files Browse the repository at this point in the history
…ormat
  • Loading branch information
Daniel Climent committed Oct 20, 2023
1 parent 72e33da commit 79b6fcb
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 1 deletion.
23 changes: 23 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/build/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
"@netlify/run-utils": "^5.1.1",
"@netlify/zip-it-and-ship-it": "9.25.3",
"@opentelemetry/api": "^1.4.1",
"@opentelemetry/core": "^1.17.1",
"@sindresorhus/slugify": "^2.0.0",
"ansi-escapes": "^6.0.0",
"chalk": "^5.0.0",
Expand Down
17 changes: 17 additions & 0 deletions packages/build/src/tracing/main.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { readFile } from 'node:fs/promises'

import { HoneycombSDK } from '@honeycombio/opentelemetry-node'
import { context, trace, propagation, SpanStatusCode, diag, DiagLogLevel, DiagLogger } from '@opentelemetry/api'
import { parseKeyPairsIntoRecord } from '@opentelemetry/core/build/src/baggage/utils.js'
import { NodeSDK } from '@opentelemetry/sdk-node'

import type { TracingOptions } from '../core/types.js'
Expand Down Expand Up @@ -89,6 +92,20 @@ export const addErrorToActiveSpan = function (error: Error) {
})
}

//** Loads the baggage attributes from a baggabe file which follows W3C Baggage specification */
export const loadBaggageFromFile = async function (baggageFilePath: string) {
if (baggageFilePath === undefined || baggageFilePath.length == 0) return
let baggageString: string
try {
baggageString = await readFile(baggageFilePath, 'utf-8')
} catch (error) {
diag.error(error)
return
}
const parsedBaggage = parseKeyPairsIntoRecord(baggageString)
return setMultiSpanAttributes(parsedBaggage)
}

/** Attributes used for the root span of our execution */
export type RootExecutionAttributes = {
'build.id': string
Expand Down
67 changes: 66 additions & 1 deletion packages/build/tests/tracing/tests.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import { writeFile, rm } from 'fs/promises'

import { trace, TraceFlags } from '@opentelemetry/api'
import { getBaggage } from '@opentelemetry/api/build/src/baggage/context-helpers.js'
import test from 'ava'

import { setMultiSpanAttributes, startTracing, stopTracing } from '../../lib/tracing/main.js'
import { setMultiSpanAttributes, startTracing, stopTracing, loadBaggageFromFile } from '../../lib/tracing/main.js'

const BAGGAGE_PATH = './baggage.dump'

test('Tracing set multi span attributes', async (t) => {
const ctx = setMultiSpanAttributes({ some: 'test', foo: 'bar' })
Expand All @@ -11,6 +15,67 @@ test('Tracing set multi span attributes', async (t) => {
t.is(baggage.getEntry('foo').value, 'bar')
})

const testMatrixBaggageFile = [
{
description: 'when baggageFilePath is blank',
input: {
baggageFilePath: '',
baggageFileContent: null,
},
expects: {
somefield: undefined,
foo: undefined
}
},
{
description: 'when baggageFilePath is set but file is empty',
input: {
baggageFilePath: BAGGAGE_PATH,
baggageFileContent: '',
},
expects: {
somefield: undefined,
foo: undefined
}
},
{
description: 'when baggageFilePath is set and has content',
input: {
baggageFilePath: BAGGAGE_PATH,
baggageFileContent: 'somefield=value,foo=bar',
},
expects: {
somefield: { value: 'value' },
foo: { value: 'bar' },
}
}
]

testMatrixBaggageFile.forEach((testCase) => {
test.serial(`Tracing baggage loading - ${testCase.description}`, async (t) => {
const { input, expects } = testCase
var ctx
try {
if (input.baggageFilePath.length > 0) {
await writeFile(input.baggageFilePath, input.baggageFileContent)
}
ctx = await loadBaggageFromFile(input.baggageFilePath)
} finally {
if (input.baggageFilePath.length > 0) await rm(input.baggageFilePath, { force: true })
}

const baggage = getBaggage(ctx)

Object.entries(expects).forEach(([property, expected]) => {
if (expected == undefined) {
t.is(baggage.getEntry(property), expected)
} else {
t.is(baggage.getEntry(property).value, expected.value)
}
})
})
})

const spanId = '6e0c63257de34c92'
// The sampler is deterministic, meaning that for a given traceId it will always produce a `SAMPLED` or a `NONE`
// consistently. More info in - https://opentelemetry.io/docs/specs/otel/trace/tracestate-probability-sampling/#consistent-probability-sampling
Expand Down

0 comments on commit 79b6fcb

Please sign in to comment.