opentelemetry-js-contrib
opentelemetry-js-contrib copied to clipboard
Cucumber instrumentation not creating spans
- [x] This only affects the JavaScript OpenTelemetry library
- [ ] This may affect other libraries, but I would like to get opinions here first
I am trying to instrument my cucumber tests in NodeJS but I can't make it trace anything at all.
I tried using both
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node'
and
import { CucumberInstrumentation } from '@opentelemetry/instrumentation-cucumber'
but had no luck with either.
This is the file I have that sets up the telemetry:
/* eslint-disable @typescript-eslint/no-unused-vars */
import { After, Before, BeforeStep, AfterStep, Status, BeforeAll } from '@cucumber/cucumber'
import { NodeSDK } from '@opentelemetry/sdk-node'
import { CucumberInstrumentation } from '@opentelemetry/instrumentation-cucumber'
import { Resource } from '@opentelemetry/resources'
import { ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions'
import * as api from '@opentelemetry/api'
import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks'
import * as grpc from '@grpc/grpc-js'
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc'
const collectorOptions = {
url: 'localhost:4317',
credentials: grpc.credentials.createInsecure(),
}
const sdk = new NodeSDK({
resource: new Resource({
[ATTR_SERVICE_NAME]: 'E2E System Tests'
}),
traceExporter: new OTLPTraceExporter(collectorOptions),
instrumentations: [new CucumberInstrumentation()],
})
const contextManager = new AsyncHooksContextManager().enable()
api.context.setGlobalContextManager(contextManager)
try {
sdk.start()
console.log('Tracing initialized')
} catch (error) {
console.log('Error initializing tracing', error)
}
// Executed after all scenarios
AfterAll(function () {
sdk.shutdown()
.then(() => console.log('Tracing terminated'))
.catch((error) => console.log('Error terminating tracing', error))
})
It gets called and if I create spans manually they show up in the OTELCollector, so telemetry seems to be properly set up.
Does anyone have a real example of to set it up for a real cucumber project?
do you compile your code to ESM or commonjs? :thinking:
There's an extra step for ESM users that needs to be followed, because we only hook require calls by default but they don't exist in ESM, so we need a loader hook - details here https://github.com/open-telemetry/opentelemetry-js/blob/main/doc/esm-support.md
do you compile your code to ESM or commonjs? 🤔 There's an extra step for ESM users that needs to be followed, because we only hook
requirecalls by default but they don't exist in ESM, so we need a loader hook - details here https://github.com/open-telemetry/opentelemetry-js/blob/main/doc/esm-support.md
Yes, it turns out that was the problem. I followed your suggestion and after quite some trial and error I made it work.
If this is useful for anyone, this is what my execution command looks like to run cucumber-js tests:
npm run build && node --experimental-loader=@opentelemetry/instrumentation/hook.mjs --import ./build/tracing.js ./node_modules/@cucumber/cucumber/bin/cucumber-js --tags "not @ignore"
And this is my tracing.ts file:
import { NodeSDK } from '@opentelemetry/sdk-node'
import { Resource } from '@opentelemetry/resources'
import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from '@opentelemetry/semantic-conventions'
import * as api from '@opentelemetry/api'
import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks'
import * as grpc from '@grpc/grpc-js'
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc'
import { ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base'
import TracingConstants from './src/tracing/constants'
import { Constants } from './src/shared/constants'
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node'
const collectorOptions = {
url: TracingConstants.OTEL_EXPORTER_OTLP_ENDPOINT,
credentials: grpc.credentials.createInsecure(),
}
const spanProcessors = [new SimpleSpanProcessor(new OTLPTraceExporter(collectorOptions))]
if (Constants.ERROR_LEVEL === 'DEBUG') {
spanProcessors.push(new SimpleSpanProcessor(new ConsoleSpanExporter()))
}
export const sdk = new NodeSDK({
resource: new Resource({
[ATTR_SERVICE_NAME]: TracingConstants.SERVICE_NAME,
[ATTR_SERVICE_VERSION]: TracingConstants.SERVICE_VERSION,
}),
spanProcessors: spanProcessors,
instrumentations: [getNodeAutoInstrumentations()],
})
const contextManager = new AsyncHooksContextManager().enable()
api.context.setGlobalContextManager(contextManager)
try {
sdk.start()
console.log('Tracing initialized')
} catch (error) {
console.log('Error initializing tracing', error)
}
Edit:
I used SimpleSpanProcessor also with the OTLPTraceExporter because otherwise the traces were not being pushed to the OTEL Collector before the process exited.
@sergimola, you can await sdk.shutdown() to flush all traces before the process exits.