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
2 changes: 2 additions & 0 deletions .agents/skills/vendor-otel/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ description: Vendor an OpenTelemetry instrumentation package into the Sentry Jav

Copy upstream OTel instrumentation TypeScript source into a `vendored/` directory, remove the npm dependency, and ensure builds and tests pass. No logic changes — the vendored code must behave identically to the original.

**Scope of this rule:** "No logic changes" applies **only to the initial vendoring PR**. After a package has been vendored, the `vendored/` directory is Sentry-owned source and follow-up PRs may refactor, simplify, replace upstream utilities with Sentry equivalents (e.g. `@opentelemetry/core``@sentry/core`), or otherwise diverge from upstream. Such cleanup is desired, not discouraged.

## 1. Research

Find upstream source files:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
/* eslint-disable */

import { Span, SpanKind, context, trace, diag, SpanStatusCode } from '@opentelemetry/api';
import { hrTime, suppressTracing } from '@opentelemetry/core';
import { suppressTracing } from '@opentelemetry/core';
import { AttributeNames } from './enums';
import { ServicesExtensions } from './services';
import {
Expand Down Expand Up @@ -57,7 +57,7 @@ import { propwrap } from './propwrap';
import { RequestMetadata } from './services/ServiceExtension';
import { ATTR_HTTP_STATUS_CODE } from './semconv';
import { ATTR_HTTP_RESPONSE_STATUS_CODE } from '@opentelemetry/semantic-conventions';
import { SDK_VERSION } from '@sentry/core';
import { SDK_VERSION, timestampInSeconds } from '@sentry/core';

const PACKAGE_NAME = '@sentry/instrumentation-aws-sdk';

Expand Down Expand Up @@ -298,7 +298,7 @@ export class AwsInstrumentation extends InstrumentationBase<AwsSdkInstrumentatio
self._diag,
self._dbSemconvStability,
);
const startTime = hrTime();
const startTime = timestampInSeconds();
const span = self._startAwsV3Span(normalizedRequest, requestMetadata);
const activeContextWithSpan = trace.setSpan(context.active(), span);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
*/
/* eslint-disable */

import { DiagLogger, HrTime, Meter, Span, SpanAttributes, SpanKind, Tracer } from '@opentelemetry/api';
import { DiagLogger, Meter, Span, SpanAttributes, SpanKind, Tracer } from '@opentelemetry/api';
import { SemconvStability } from '@opentelemetry/instrumentation';
import { AwsSdkInstrumentationConfig, NormalizedRequest, NormalizedResponse } from '../types';

Expand Down Expand Up @@ -53,7 +53,7 @@ export interface ServiceExtension {
span: Span,
tracer: Tracer,
config: AwsSdkInstrumentationConfig,
startTime: HrTime,
startTime: number,
) => any | undefined;

updateMetricInstruments?: (meter: Meter) => void;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
*/
/* eslint-disable */

import { Tracer, Span, DiagLogger, Meter, HrTime } from '@opentelemetry/api';
import { Tracer, Span, DiagLogger, Meter } from '@opentelemetry/api';
import { SemconvStability } from '@opentelemetry/instrumentation';
import { ServiceExtension, RequestMetadata } from './ServiceExtension';
import { SqsServiceExtension } from './sqs';
Expand Down Expand Up @@ -77,7 +77,7 @@ export class ServicesExtensions implements ServiceExtension {
span: Span,
tracer: Tracer,
config: AwsSdkInstrumentationConfig,
startTime: HrTime,
startTime: number,
) {
const serviceExtension = this.services.get(response.request.serviceName);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
*/
/* eslint-disable */

import { Attributes, DiagLogger, diag, Histogram, HrTime, Meter, Span, Tracer, ValueType } from '@opentelemetry/api';
import { Attributes, DiagLogger, diag, Histogram, Meter, Span, Tracer, ValueType } from '@opentelemetry/api';
import { RequestMetadata, ServiceExtension } from './ServiceExtension';
import {
ATTR_GEN_AI_SYSTEM,
Expand All @@ -41,7 +41,7 @@ import {
METRIC_GEN_AI_CLIENT_TOKEN_USAGE,
} from '../semconv';
import { AwsSdkInstrumentationConfig, NormalizedRequest, NormalizedResponse } from '../types';
import { hrTime, hrTimeDuration, hrTimeToMilliseconds } from '@opentelemetry/core';
import { timestampInSeconds } from '@sentry/core';

// Simplified types inlined from @aws-sdk/client-bedrock-runtime
// Only the fields accessed by this instrumentation are included
Expand Down Expand Up @@ -295,7 +295,7 @@ export class BedrockRuntimeServiceExtension implements ServiceExtension {
span: Span,
tracer: Tracer,
config: AwsSdkInstrumentationConfig,
startTime: HrTime,
startTime: number,
) {
if (!span.isRecording()) {
return;
Expand All @@ -318,7 +318,7 @@ export class BedrockRuntimeServiceExtension implements ServiceExtension {
span: Span,
tracer: Tracer,
config: AwsSdkInstrumentationConfig,
startTime: HrTime,
startTime: number,
) {
const { stopReason, usage } = response.data;

Expand All @@ -331,7 +331,7 @@ export class BedrockRuntimeServiceExtension implements ServiceExtension {
span: Span,
tracer: Tracer,
config: AwsSdkInstrumentationConfig,
startTime: HrTime,
startTime: number,
) {
return {
...response.data,
Expand All @@ -345,7 +345,7 @@ export class BedrockRuntimeServiceExtension implements ServiceExtension {
response: NormalizedResponse,
stream: AsyncIterable<ConverseStreamOutput>,
span: Span,
startTime: HrTime,
startTime: number,
) {
try {
let usage: TokenUsage | undefined;
Expand All @@ -366,14 +366,14 @@ export class BedrockRuntimeServiceExtension implements ServiceExtension {
}
}

private setUsage(response: NormalizedResponse, span: Span, usage: TokenUsage | undefined, startTime: HrTime) {
private setUsage(response: NormalizedResponse, span: Span, usage: TokenUsage | undefined, startTime: number) {
const sharedMetricAttrs: Attributes = {
[ATTR_GEN_AI_SYSTEM]: GEN_AI_SYSTEM_VALUE_AWS_BEDROCK,
[ATTR_GEN_AI_OPERATION_NAME]: GEN_AI_OPERATION_NAME_VALUE_CHAT,
[ATTR_GEN_AI_REQUEST_MODEL]: response.request.commandInput.modelId,
};

const durationSecs = hrTimeToMilliseconds(hrTimeDuration(startTime, hrTime())) / 1000;
const durationSecs = timestampInSeconds() - startTime;
this.operationDuration.record(durationSecs, sharedMetricAttrs);

if (usage) {
Expand Down
1 change: 0 additions & 1 deletion packages/nestjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@
},
"dependencies": {
"@opentelemetry/api": "^1.9.1",
"@opentelemetry/core": "^2.6.1",
"@opentelemetry/instrumentation": "^0.214.0",
"@opentelemetry/semantic-conventions": "^1.40.0",
"@sentry/core": "10.54.0",
Expand Down
13 changes: 6 additions & 7 deletions packages/node/src/integrations/node-fetch/vendored/undici.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import * as diagch from 'diagnostics_channel';
import { URL } from 'url';

import { InstrumentationBase, safeExecuteInTheMiddle } from '@opentelemetry/instrumentation';
import type { Attributes, Histogram, HrTime, Span } from '@opentelemetry/api';
import type { Attributes, Histogram, Span } from '@opentelemetry/api';
import {
context,
INVALID_SPAN_CONTEXT,
Expand All @@ -35,7 +35,6 @@ import {
trace,
ValueType,
} from '@opentelemetry/api';
import { hrTime, hrTimeDuration, hrTimeToMilliseconds } from '@opentelemetry/core';
import {
ATTR_ERROR_TYPE,
ATTR_HTTP_REQUEST_METHOD,
Expand All @@ -62,12 +61,12 @@ import type {
} from './internal-types';
import type { UndiciInstrumentationConfig, UndiciRequest } from './types';

import { SDK_VERSION } from '@sentry/core';
import { SDK_VERSION, timestampInSeconds } from '@sentry/core';

interface InstrumentationRecord {
span: Span;
attributes: Attributes;
startTime: HrTime;
startTime: number;
}

const PACKAGE_NAME = '@sentry/instrumentation-undici';
Expand Down Expand Up @@ -225,7 +224,7 @@ export class UndiciInstrumentation extends InstrumentationBase<UndiciInstrumenta
return;
}

const startTime = hrTime();
const startTime = timestampInSeconds();
let requestUrl;
try {
requestUrl = new URL(request.path, request.origin);
Expand Down Expand Up @@ -475,7 +474,7 @@ export class UndiciInstrumentation extends InstrumentationBase<UndiciInstrumenta
this.recordRequestDuration(attributes, startTime);
}

private recordRequestDuration(attributes: Attributes, startTime: HrTime) {
private recordRequestDuration(attributes: Attributes, startTime: number) {
// Time to record metrics
const metricsAttributes: Attributes = {};
// Get the attribs already in span attributes
Expand All @@ -494,7 +493,7 @@ export class UndiciInstrumentation extends InstrumentationBase<UndiciInstrumenta
});

// Take the duration and record it
const durationSeconds = hrTimeToMilliseconds(hrTimeDuration(startTime, hrTime())) / 1000;
const durationSeconds = timestampInSeconds() - startTime;
this._httpClientDurationHistogram.record(durationSeconds, metricsAttributes);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import {
Link,
Context,
} from '@opentelemetry/api';
import { hrTime, hrTimeDuration, hrTimeToMilliseconds } from '@opentelemetry/core';
import { timestampInSeconds } from '@sentry/core';
import {
InstrumentationBase,
InstrumentationNodeModuleDefinition,
Expand Down Expand Up @@ -376,7 +376,7 @@ export class AmqplibInstrumentation extends InstrumentationBase<AmqplibInstrumen
// store the message on the channel so we can close the span on ackAll etc
channel[CHANNEL_SPANS_NOT_ENDED]!.push({
msg,
timeOfConsume: hrTime(),
timeOfConsume: timestampInSeconds(),
});

// store the span on the message, so we can end it when user call 'ack' on it
Expand Down Expand Up @@ -615,14 +615,14 @@ export class AmqplibInstrumentation extends InstrumentationBase<AmqplibInstrumen
}

private checkConsumeTimeoutOnChannel(channel: InstrumentationConsumeChannel) {
const currentTime = hrTime();
const currentTime = timestampInSeconds();
const spansNotEnded = channel[CHANNEL_SPANS_NOT_ENDED] ?? [];
let i: number;
const { consumeTimeoutMs } = this.getConfig();
for (i = 0; i < spansNotEnded.length; i++) {
const currMessage = spansNotEnded[i]!;
const timeFromConsume = hrTimeDuration(currMessage.timeOfConsume, currentTime);
if (hrTimeToMilliseconds(timeFromConsume) < consumeTimeoutMs!) {
const timeFromConsumeMs = (currentTime - currMessage.timeOfConsume) * 1000;
if (timeFromConsumeMs < consumeTimeoutMs!) {
break;
}
this.endConsumerSpan(currMessage.msg, null, EndOperation.InstrumentationTimeout, true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
*/
/* eslint-disable */

import { Context, createContextKey, diag, HrTime, Span, Attributes, AttributeValue } from '@opentelemetry/api';
import { Context, createContextKey, diag, Span, Attributes, AttributeValue } from '@opentelemetry/api';
import { SemconvStability } from '@opentelemetry/instrumentation';
import { ATTR_SERVER_ADDRESS, ATTR_SERVER_PORT } from '@opentelemetry/semantic-conventions';
import { ATTR_MESSAGING_SYSTEM, ATTR_NET_PEER_NAME, ATTR_NET_PEER_PORT } from './semconv';
Expand All @@ -45,7 +45,7 @@ export type InstrumentationConsumeChannel = Channel & {
connection: InstrumentationConnection;
[CHANNEL_SPANS_NOT_ENDED]?: {
msg: ConsumeMessage;
timeOfConsume: HrTime;
timeOfConsume: number;
}[];
[CHANNEL_CONSUME_TIMEOUT_TIMER]?: NodeJS.Timeout;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ import {
Histogram,
ValueType,
Attributes,
HrTime,
UpDownCounter,
} from '@opentelemetry/api';
import type { PgClient } from './pg-types';
Expand All @@ -54,10 +53,9 @@ import {
import { PgInstrumentationConfig } from './types';
import * as utils from './utils';
import { addSqlCommenterComment } from '../../utils/sql-common';
import { SDK_VERSION } from '@sentry/core';
import { SDK_VERSION, timestampInSeconds } from '@sentry/core';
const PACKAGE_NAME = '@sentry/instrumentation-pg';
import { SpanNames } from './enums/SpanNames';
import { hrTime, hrTimeDuration, hrTimeToMilliseconds } from '@opentelemetry/core';
import {
ATTR_ERROR_TYPE,
ATTR_SERVER_PORT,
Expand Down Expand Up @@ -252,7 +250,7 @@ export class PgInstrumentation extends InstrumentationBase<PgInstrumentationConf
};
}

private recordOperationDuration(attributes: Attributes, startTime: HrTime) {
private recordOperationDuration(attributes: Attributes, startTime: number) {
const metricsAttributes: Attributes = {};
const keysToCopy: string[] = [
ATTR_DB_NAMESPACE,
Expand All @@ -274,7 +272,7 @@ export class PgInstrumentation extends InstrumentationBase<PgInstrumentationConf
}
});

const durationSeconds = hrTimeToMilliseconds(hrTimeDuration(startTime, hrTime())) / 1000;
const durationSeconds = timestampInSeconds() - startTime;
this._operationDuration.record(durationSeconds, metricsAttributes);
}

Expand All @@ -286,7 +284,7 @@ export class PgInstrumentation extends InstrumentationBase<PgInstrumentationConf
if (utils.shouldSkipInstrumentation(plugin.getConfig())) {
return original.apply(this, args as never);
}
const startTime = hrTime();
const startTime = timestampInSeconds();

// client.query(text, cb?), client.query(text, values, cb?), and
// client.query(configObj, cb?) are all valid signatures. We construct
Expand Down
Loading