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
2 changes: 1 addition & 1 deletion packages/browser/src/tracing/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ function isPerformanceResourceTiming(entry: PerformanceEntry): entry is Performa
* @param span A span that has yet to be finished, must contain `url` on data.
*/
function addHTTPTimings(span: Span): void {
const { url } = spanToJSON(span).data || {};
const { url } = spanToJSON(span).data;

if (!url || typeof url !== 'string') {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ describe('browserTracingIntegration', () => {
const pageloadSpan = getActiveSpan();

expect(spanToJSON(pageloadSpan!).description).toBe('changed');
expect(spanToJSON(pageloadSpan!).data?.[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]).toBe('custom');
expect(spanToJSON(pageloadSpan!).data[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]).toBe('custom');
});

describe('startBrowserTracingNavigationSpan', () => {
Expand Down Expand Up @@ -608,7 +608,7 @@ describe('browserTracingIntegration', () => {
const pageloadSpan = getActiveSpan();

expect(spanToJSON(pageloadSpan!).description).toBe('changed');
expect(spanToJSON(pageloadSpan!).data?.[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]).toBe('custom');
expect(spanToJSON(pageloadSpan!).data[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]).toBe('custom');
});

it('sets the navigation span name on `scope.transactionName`', () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/tracing/dynamicSamplingContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export function getDynamicSamplingContextFromSpan(span: Span): Readonly<Partial<
// Else, we generate it from the span
const dsc = getDynamicSamplingContextFromClient(span.spanContext().traceId, client);
const jsonSpan = spanToJSON(rootSpan);
const attributes = jsonSpan.data || {};
const attributes = jsonSpan.data;
const maybeSampleRate = attributes[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE];

if (maybeSampleRate != null) {
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/tracing/idleSpan.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { getClient, getCurrentScope } from '../currentScopes';
import type { Span, SpanAttributes, StartSpanOptions } from '../types-hoist';
import type { Span, StartSpanOptions } from '../types-hoist';

import { DEBUG_BUILD } from '../debug-build';
import { SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON } from '../semanticAttributes';
Expand Down Expand Up @@ -255,7 +255,7 @@ export function startIdleSpan(startSpanOptions: StartSpanOptions, options: Parti
return;
}

const attributes: SpanAttributes = spanJSON.data || {};
const attributes = spanJSON.data;
if (!attributes[SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON]) {
span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON, _finishReason);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/core/test/lib/tracing/sentrySpan.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ describe('SentrySpan', () => {

const spanJson = spanToJSON(span);
expect(spanJson.description).toEqual('new name');
expect(spanJson.data?.[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]).toEqual('custom');
expect(spanJson.data[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]).toEqual('custom');
});
});

Expand Down
2 changes: 1 addition & 1 deletion packages/nestjs/src/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export function init(options: NodeOptions | undefined = {}): NodeClient | undefi
}

function addNestSpanAttributes(span: Span): void {
const attributes = spanToJSON(span).data || {};
const attributes = spanToJSON(span).data;

// this is one of: app_creation, request_context, handler
const type = attributes['nestjs.type'];
Expand Down
2 changes: 1 addition & 1 deletion packages/nestjs/src/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ Module({
export { SentryModule };

function addNestSpanAttributes(span: Span): void {
const attributes = spanToJSON(span).data || {};
const attributes = spanToJSON(span).data;

// this is one of: app_creation, request_context, handler
const type = attributes['nestjs.type'];
Expand Down
1 change: 0 additions & 1 deletion packages/nextjs/src/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,6 @@ export function init(options: NodeOptions): NodeClient | undefined {
event.type === 'transaction' &&
event.contexts?.trace?.data?.['next.span_type'] === 'BaseServer.handleRequest'
) {
event.contexts.trace.data = event.contexts.trace.data || {};
event.contexts.trace.data[SEMANTIC_ATTRIBUTE_SENTRY_OP] = 'http.server';
event.contexts.trace.op = 'http.server';

Expand Down
2 changes: 1 addition & 1 deletion packages/node/src/integrations/tracing/connect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export const setupConnectErrorHandler = (app: ConnectApp): void => {
};

function addConnectSpanAttributes(span: Span): void {
const attributes = spanToJSON(span).data || {};
const attributes = spanToJSON(span).data;

// this is one of: middleware, request_handler
const type = attributes['connect.type'];
Expand Down
2 changes: 1 addition & 1 deletion packages/node/src/integrations/tracing/express.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const instrumentExpress = generateInstrumentOnce(
requestHook(span) {
addOriginToSpan(span, 'auto.http.otel.express');

const attributes = spanToJSON(span).data || {};
const attributes = spanToJSON(span).data;
// this is one of: middleware, request_handler, router
const type = attributes['express.type'];

Expand Down
2 changes: 1 addition & 1 deletion packages/node/src/integrations/tracing/fastify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ export function setupFastifyErrorHandler(fastify: Fastify): void {
}

function addFastifySpanAttributes(span: Span): void {
const attributes = spanToJSON(span).data || {};
const attributes = spanToJSON(span).data;

// this is one of: middleware, request_handler
const type = attributes['fastify.type'];
Expand Down
4 changes: 2 additions & 2 deletions packages/node/src/integrations/tracing/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export const instrumentGraphql = generateInstrumentOnce<GraphqlOptions>(
responseHook(span) {
addOriginToSpan(span, 'auto.graphql.otel.graphql');

const attributes = spanToJSON(span).data || {};
const attributes = spanToJSON(span).data;

// If operation.name is not set, we fall back to use operation.type only
const operationType = attributes['graphql.operation.type'];
Expand All @@ -58,7 +58,7 @@ export const instrumentGraphql = generateInstrumentOnce<GraphqlOptions>(

// We guard to only do this on http.server spans

const rootSpanAttributes = spanToJSON(rootSpan).data || {};
const rootSpanAttributes = spanToJSON(rootSpan).data;

const existingOperations = rootSpanAttributes[SEMANTIC_ATTRIBUTE_SENTRY_GRAPHQL_OPERATION] || [];

Expand Down
2 changes: 1 addition & 1 deletion packages/node/src/integrations/tracing/hapi/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ export async function setupHapiErrorHandler(server: Server): Promise<void> {
}

function addHapiSpanAttributes(span: Span): void {
const attributes = spanToJSON(span).data || {};
const attributes = spanToJSON(span).data;

// this is one of: router, plugin, server.ext
const type = attributes['hapi.type'];
Expand Down
2 changes: 1 addition & 1 deletion packages/node/src/integrations/tracing/knex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const _knexIntegration = (() => {
const { data } = spanToJSON(span);
// knex.version is always set in the span data
// https://github.com/open-telemetry/opentelemetry-js-contrib/blob/0309caeafc44ac9cb13a3345b790b01b76d0497d/plugins/node/opentelemetry-instrumentation-knex/src/instrumentation.ts#L138
if (data && 'knex.version' in data) {
if ('knex.version' in data) {
span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, 'auto.db.otel.knex');
}
});
Expand Down
2 changes: 1 addition & 1 deletion packages/node/src/integrations/tracing/koa.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ export const setupKoaErrorHandler = (app: { use: (arg0: (ctx: any, next: any) =>
function addKoaSpanAttributes(span: Span): void {
span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, 'auto.http.otel.koa');

const attributes = spanToJSON(span).data || {};
const attributes = spanToJSON(span).data;

// this is one of: middleware, router
const type = attributes['koa.type'];
Expand Down
2 changes: 1 addition & 1 deletion packages/node/src/integrations/tracing/nest/nest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ export function setupNestErrorHandler(app: MinimalNestJsApp, baseFilter: NestJsE
}

function addNestSpanAttributes(span: Span): void {
const attributes = spanToJSON(span).data || {};
const attributes = spanToJSON(span).data;

// this is one of: app_creation, request_context, handler
const type = attributes['nestjs.type'];
Expand Down
4 changes: 2 additions & 2 deletions packages/node/src/integrations/tracing/redis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ const cacheResponseHook: RedisResponseCustomAttributeFunction = (span: Span, red

// otel/ioredis seems to be using the old standard, as there was a change to those params: https://github.com/open-telemetry/opentelemetry-specification/issues/3199
// We are using params based on the docs: https://opentelemetry.io/docs/specs/semconv/attributes-registry/network/
const networkPeerAddress = spanToJSON(span).data?.['net.peer.name'];
const networkPeerPort = spanToJSON(span).data?.['net.peer.port'];
const networkPeerAddress = spanToJSON(span).data['net.peer.name'];
const networkPeerPort = spanToJSON(span).data['net.peer.port'];
if (networkPeerPort && networkPeerAddress) {
span.setAttributes({ 'network.peer.address': networkPeerAddress, 'network.peer.port': networkPeerPort });
}
Expand Down
2 changes: 1 addition & 1 deletion packages/node/src/integrations/tracing/tedious.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const _tediousIntegration = (() => {
client.on('spanStart', span => {
const { description, data } = spanToJSON(span);
// Tedius integration always set a span name and `db.system` attribute to `mssql`.
if (!description || data?.['db.system'] !== 'mssql') {
if (!description || data['db.system'] !== 'mssql') {
return;
}

Expand Down
13 changes: 5 additions & 8 deletions packages/node/src/integrations/tracing/vercelai/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,21 @@ const _vercelAIIntegration = (() => {
for (const span of event.spans) {
const { data: attributes, description: name } = span;

if (!attributes || !name || span.origin !== 'auto.vercelai.otel') {
if (!name || span.origin !== 'auto.vercelai.otel') {
continue;
}

// attributes around token usage can only be set on span finish
span.data = span.data || {};

if (attributes['ai.usage.completionTokens'] != undefined) {
span.data['ai.completion_tokens.used'] = attributes['ai.usage.completionTokens'];
attributes['ai.completion_tokens.used'] = attributes['ai.usage.completionTokens'];
}
if (attributes['ai.usage.promptTokens'] != undefined) {
span.data['ai.prompt_tokens.used'] = attributes['ai.usage.promptTokens'];
attributes['ai.prompt_tokens.used'] = attributes['ai.usage.promptTokens'];
}
if (
typeof attributes['ai.usage.completionTokens'] == 'number' &&
typeof attributes['ai.usage.promptTokens'] == 'number'
) {
span.data['ai.total_tokens.used'] =
attributes['ai.total_tokens.used'] =
attributes['ai.usage.completionTokens'] + attributes['ai.usage.promptTokens'];
}
}
Expand All @@ -51,7 +48,7 @@ const _vercelAIIntegration = (() => {

const { data: attributes, description: name } = spanToJSON(span);

if (!attributes || !name) {
if (!name) {
return;
}

Expand Down
2 changes: 1 addition & 1 deletion packages/opentelemetry/src/propagator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ function getCurrentURL(span: Span): string | undefined {
const spanData = spanToJSON(span).data;
// `ATTR_URL_FULL` is the new attribute, but we still support the old one, `SEMATTRS_HTTP_URL`, for now.
// eslint-disable-next-line deprecation/deprecation
const urlAttribute = spanData?.[SEMATTRS_HTTP_URL] || spanData?.[ATTR_URL_FULL];
const urlAttribute = spanData[SEMATTRS_HTTP_URL] || spanData[ATTR_URL_FULL];
if (typeof urlAttribute === 'string') {
return urlAttribute;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export function enhanceDscWithOpenTelemetryRootSpanName(client: Client): void {
// This mutates the passed-in DSC

const jsonSpan = spanToJSON(rootSpan);
const attributes = jsonSpan.data || {};
const attributes = jsonSpan.data;
const source = attributes[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE];

const { description } = spanHasName(rootSpan) ? parseSpanDescription(rootSpan) : { description: undefined };
Expand Down
2 changes: 1 addition & 1 deletion packages/remix/src/utils/integrations/opentelemetry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const _remixIntegration = (() => {
}) satisfies IntegrationFn;

const addRemixSpanAttributes = (span: Span): void => {
const attributes = spanToJSON(span).data || {};
const attributes = spanToJSON(span).data;

// this is one of: loader, action, requestHandler
const type = attributes['code.function'];
Expand Down
2 changes: 1 addition & 1 deletion packages/vue/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ export function instrumentVueRouter(
if (options.instrumentPageLoad && isPageLoadNavigation) {
const activeRootSpan = getActiveRootSpan();
if (activeRootSpan) {
const existingAttributes = spanToJSON(activeRootSpan).data || {};
const existingAttributes = spanToJSON(activeRootSpan).data;
if (existingAttributes[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE] !== 'custom') {
activeRootSpan.updateName(spanName);
activeRootSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, transactionSource);
Expand Down
25 changes: 15 additions & 10 deletions packages/vue/test/router.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import type { Span, SpanAttributes } from '@sentry/core';
import type { Route } from '../src/router';
import { instrumentVueRouter } from '../src/router';

const MOCK_SPAN = {
spanContext: () => ({ traceId: '1234', spanId: '5678' }),
};

const captureExceptionSpy = vi.spyOn(SentryBrowser, 'captureException');
vi.mock('@sentry/core', async () => {
const actual = await vi.importActual('@sentry/core');
Expand Down Expand Up @@ -76,7 +80,7 @@ describe('instrumentVueRouter()', () => {
});

it('should return instrumentation that instruments VueRouter.onError', () => {
const mockStartSpan = vi.fn();
const mockStartSpan = vi.fn().mockReturnValue(MOCK_SPAN);
instrumentVueRouter(
mockVueRouter,
{ routeLabel: 'name', instrumentPageLoad: true, instrumentNavigation: true },
Expand All @@ -103,7 +107,7 @@ describe('instrumentVueRouter()', () => {
])(
'should return instrumentation that instruments VueRouter.beforeEach(%s, %s) for navigations',
(fromKey, toKey, transactionName, transactionSource) => {
const mockStartSpan = vi.fn();
const mockStartSpan = vi.fn().mockReturnValue(MOCK_SPAN);
instrumentVueRouter(
mockVueRouter,
{ routeLabel: 'name', instrumentPageLoad: true, instrumentNavigation: true },
Expand Down Expand Up @@ -143,7 +147,8 @@ describe('instrumentVueRouter()', () => {
'should return instrumentation that instruments VueRouter.beforeEach(%s, %s) for pageloads',
(fromKey, toKey, transactionName, transactionSource) => {
const mockRootSpan = {
getSpanJSON: vi.fn().mockReturnValue({ op: 'pageload' }),
...MOCK_SPAN,
getSpanJSON: vi.fn().mockReturnValue({ op: 'pageload', data: {} }),
updateName: vi.fn(),
setAttribute: vi.fn(),
setAttributes: vi.fn(),
Expand Down Expand Up @@ -183,7 +188,7 @@ describe('instrumentVueRouter()', () => {
);

it('allows to configure routeLabel=path', () => {
const mockStartSpan = vi.fn();
const mockStartSpan = vi.fn().mockReturnValue(MOCK_SPAN);
instrumentVueRouter(
mockVueRouter,
{ routeLabel: 'path', instrumentPageLoad: true, instrumentNavigation: true },
Expand Down Expand Up @@ -211,7 +216,7 @@ describe('instrumentVueRouter()', () => {
});

it('allows to configure routeLabel=name', () => {
const mockStartSpan = vi.fn();
const mockStartSpan = vi.fn().mockReturnValue(MOCK_SPAN);
instrumentVueRouter(
mockVueRouter,
{ routeLabel: 'name', instrumentPageLoad: true, instrumentNavigation: true },
Expand Down Expand Up @@ -240,6 +245,7 @@ describe('instrumentVueRouter()', () => {

it("doesn't overwrite a pageload transaction name it was set to custom before the router resolved the route", () => {
const mockRootSpan = {
...MOCK_SPAN,
updateName: vi.fn(),
setAttribute: vi.fn(),
setAttributes: vi.fn(),
Expand Down Expand Up @@ -294,9 +300,7 @@ describe('instrumentVueRouter()', () => {
});

it("updates the scope's `transactionName` when a route is resolved", () => {
const mockStartSpan = vi.fn().mockImplementation(_ => {
return {};
});
const mockStartSpan = vi.fn().mockReturnValue(MOCK_SPAN);

const scopeSetTransactionNameSpy = vi.fn();

Expand Down Expand Up @@ -329,6 +333,7 @@ describe('instrumentVueRouter()', () => {
'should return instrumentation that considers the instrumentPageLoad = %p',
(instrumentPageLoad, expectedCallsAmount) => {
const mockRootSpan = {
...MOCK_SPAN,
updateName: vi.fn(),
setData: vi.fn(),
setAttribute: vi.fn(),
Expand Down Expand Up @@ -367,7 +372,7 @@ describe('instrumentVueRouter()', () => {
])(
'should return instrumentation that considers the instrumentNavigation = %p',
(instrumentNavigation, expectedCallsAmount) => {
const mockStartSpan = vi.fn();
const mockStartSpan = vi.fn().mockReturnValue(MOCK_SPAN);
instrumentVueRouter(
mockVueRouter,
{ routeLabel: 'name', instrumentPageLoad: true, instrumentNavigation },
Expand All @@ -386,7 +391,7 @@ describe('instrumentVueRouter()', () => {
);

it("doesn't throw when `next` is not available in the beforeEach callback (Vue Router 4)", () => {
const mockStartSpan = vi.fn();
const mockStartSpan = vi.fn().mockReturnValue(MOCK_SPAN);
instrumentVueRouter(
mockVueRouter,
{ routeLabel: 'path', instrumentPageLoad: true, instrumentNavigation: true },
Expand Down
Loading