Skip to content

Instantly share code, notes, and snippets.

@tmokmss

tmokmss/app.ts Secret

Last active April 23, 2024 10:48
Show Gist options
  • Save tmokmss/b6b0d639658161cd28519a65992866f9 to your computer and use it in GitHub Desktop.
Save tmokmss/b6b0d639658161cd28519a65992866f9 to your computer and use it in GitHub Desktop.
import './lib/otel';
import express, { NextFunction, Request, Response } from 'express';
const app = express();
/* redacted */
app.listen(3000, () => {
console.log('Server started on port 3000');
});
import { Attributes, diag, DiagConsoleLogger, DiagLogLevel, SpanKind } from '@opentelemetry/api';
import { AlwaysOnSampler, BatchSpanProcessor, Sampler, SamplingDecision } from '@opentelemetry/sdk-trace-node';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto';
import { SEMATTRS_HTTP_ROUTE, SEMRESATTRS_SERVICE_NAME } from '@opentelemetry/semantic-conventions';
import { ExpressInstrumentation } from '@opentelemetry/instrumentation-express';
import { AWSXRayIdGenerator } from '@opentelemetry/id-generator-aws-xray';
import { HttpInstrumentation } from '@opentelemetry/instrumentation-http';
import { Resource } from '@opentelemetry/resources';
import { AwsInstrumentation } from '@opentelemetry/instrumentation-aws-sdk';
import { AWSXRayPropagator } from '@opentelemetry/propagator-aws-xray';
import { NodeSDK } from '@opentelemetry/sdk-node';
diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.INFO);
// https://aws-otel.github.io/docs/getting-started/js-sdk/trace-manual-instr
const resource = Resource.default().merge(
new Resource({
[SEMRESATTRS_SERVICE_NAME]: process.env.SERVICE_NAME ?? 'service',
}),
);
const traceExporter = new OTLPTraceExporter();
const spanProcessor = new BatchSpanProcessor(traceExporter);
const sdk = new NodeSDK({
textMapPropagator: new AWSXRayPropagator(),
instrumentations: [
new HttpInstrumentation(),
new AwsInstrumentation({
suppressInternalInstrumentation: true,
}),
new ExpressInstrumentation(),
],
resource,
spanProcessors: [spanProcessor],
traceExporter,
idGenerator: new AWSXRayIdGenerator(),
sampler: filterSampler(ignoreHealthCheck, new AlwaysOnSampler()),
});
type FilterFunction = (spanName: string, spanKind: SpanKind, attributes: Attributes) => boolean;
function filterSampler(filterFn: FilterFunction, parent: Sampler): Sampler {
return {
shouldSample(ctx, tid, spanName, spanKind, attr, links) {
if (!filterFn(spanName, spanKind, attr)) {
return { decision: SamplingDecision.NOT_RECORD };
}
return parent.shouldSample(ctx, tid, spanName, spanKind, attr, links);
},
toString() {
return `FilterSampler(${parent.toString()})`;
},
};
}
function ignoreHealthCheck(spanName: string, spanKind: SpanKind, attributes: Attributes) {
return spanKind !== SpanKind.SERVER || attributes[SEMATTRS_HTTP_ROUTE] !== '/health';
}
// this enables the API to record telemetry
sdk.start();
// gracefully shut down the SDK on process exit
process.on('SIGTERM', () => {
sdk
.shutdown()
.then(() => console.log('Tracing and Metrics terminated'))
.catch((error) => console.log('Error terminating tracing and metrics', error))
.finally(() => process.exit(0));
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment