Skip to content

Commit

Permalink
feat(opentelemetry): Update OpenTelemetry dependencies to 1.28.0 (#…
Browse files Browse the repository at this point in the history
…14547)

Updates all OpenTelemetry dependencies to 1.28.0, as well as all
instrumentation except for prisma (which is a major from 5 to 6, so
leaving this out for now...) to their latest version.
  • Loading branch information
mydea authored Dec 5, 2024
1 parent 2a41c84 commit d631127
Show file tree
Hide file tree
Showing 20 changed files with 417 additions and 248 deletions.
4 changes: 2 additions & 2 deletions .size-limit.js
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ module.exports = [
import: createImport('init'),
ignore: [...builtinModules, ...nodePrefixedBuiltinModules],
gzip: true,
limit: '140 KB',
limit: '160 KB',
},
{
name: '@sentry/node - without tracing',
Expand Down Expand Up @@ -260,7 +260,7 @@ module.exports = [
import: createImport('init'),
ignore: [...builtinModules, ...nodePrefixedBuiltinModules],
gzip: true,
limit: '130 KB',
limit: '150 KB',
},
];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ test('Lambda layer SDK bundle sends events', async ({ request }) => {
'sentry.op': 'function.aws.lambda',
'cloud.account.id': '123453789012',
'faas.id': 'arn:aws:lambda:us-east-1:123453789012:function:my-lambda',
'faas.coldstart': true,
'otel.kind': 'SERVER',
},
op: 'function.aws.lambda',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,22 @@ test('AWS Serverless SDK sends events in ESM mode', async ({ request }) => {
expect(transactionEvent.contexts?.trace).toEqual({
data: {
'sentry.sample_rate': 1,
'sentry.source': 'component',
'sentry.origin': 'auto.function.serverless',
'sentry.source': 'custom',
'sentry.origin': 'auto.otel.aws-lambda',
'sentry.op': 'function.aws.lambda',
'cloud.account.id': '123453789012',
'faas.id': 'arn:aws:lambda:us-east-1:123453789012:function:my-lambda',
'faas.coldstart': true,
'otel.kind': 'SERVER',
},
op: 'function.aws.lambda',
origin: 'auto.function.serverless',
origin: 'auto.otel.aws-lambda',
span_id: expect.stringMatching(/[a-f0-9]{16}/),
status: 'ok',
trace_id: expect.stringMatching(/[a-f0-9]{32}/),
});

expect(transactionEvent.spans).toHaveLength(2);
expect(transactionEvent.spans).toHaveLength(3);

// shows that the Otel Http instrumentation is working
expect(transactionEvent.spans).toContainEqual(
Expand All @@ -54,6 +58,19 @@ test('AWS Serverless SDK sends events in ESM mode', async ({ request }) => {
}),
);

expect(transactionEvent.spans).toContainEqual(
expect.objectContaining({
data: {
'sentry.op': 'function.aws.lambda',
'sentry.origin': 'auto.function.serverless',
'sentry.source': 'component',
},
description: 'my-lambda',
op: 'function.aws.lambda',
origin: 'auto.function.serverless',
}),
);

// shows that the manual span creation is working
expect(transactionEvent.spans).toContainEqual(
expect.objectContaining({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const EXPECTED_TRANSCATION = {
'rpc.method': 'PutObject',
'rpc.service': 'S3',
'aws.region': 'us-east-1',
'aws.s3.bucket': 'ot-demo-test',
'otel.kind': 'CLIENT',
},
}),
Expand Down
1 change: 1 addition & 0 deletions jest/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ module.exports = {
testMatch: ['<rootDir>/**/*.test.ts', '<rootDir>/**/*.test.tsx'],
moduleNameMapper: {
'^axios$': require.resolve('axios'),
'@opentelemetry/semantic-conventions/incubating': require.resolve('@opentelemetry/semantic-conventions/incubating'),
},
globals: {
'ts-jest': {
Expand Down
6 changes: 3 additions & 3 deletions packages/aws-serverless/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@
"access": "public"
},
"dependencies": {
"@opentelemetry/instrumentation": "^0.54.0",
"@opentelemetry/instrumentation-aws-lambda": "0.44.0",
"@opentelemetry/instrumentation-aws-sdk": "0.45.0",
"@opentelemetry/instrumentation": "^0.55.0",
"@opentelemetry/instrumentation-aws-lambda": "0.48.0",
"@opentelemetry/instrumentation-aws-sdk": "0.47.0",
"@sentry/core": "8.42.0",
"@sentry/node": "8.42.0",
"@types/aws-lambda": "^8.10.62"
Expand Down
1 change: 1 addition & 0 deletions packages/aws-serverless/src/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ export function wrapHandler<TEvent, TResult>(
// Only start a trace and root span if the handler is not already wrapped by Otel instrumentation
// Otherwise, we create two root spans (one from otel, one from our wrapper).
// If Otel instrumentation didn't work or was filtered by users, we still want to trace the handler.
// TODO(v9): Since bumping the OTEL Instrumentation, this is likely not needed anymore, we can possibly remove this
if (options.startTrace && !isWrappedByOtel(handler)) {
const traceData = getAwsTraceData(event as { headers?: Record<string, string> }, context);

Expand Down
3 changes: 1 addition & 2 deletions packages/nextjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,7 @@
},
"dependencies": {
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/instrumentation-http": "0.53.0",
"@opentelemetry/semantic-conventions": "^1.27.0",
"@opentelemetry/semantic-conventions": "^1.28.0",
"@rollup/plugin-commonjs": "28.0.1",
"@sentry-internal/browser-utils": "8.42.0",
"@sentry/core": "8.42.0",
Expand Down
20 changes: 10 additions & 10 deletions packages/node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,17 @@
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/context-async-hooks": "^1.25.1",
"@opentelemetry/core": "^1.25.1",
"@opentelemetry/instrumentation": "^0.54.0",
"@opentelemetry/instrumentation-amqplib": "^0.43.0",
"@opentelemetry/instrumentation-connect": "0.40.0",
"@opentelemetry/instrumentation-dataloader": "0.12.0",
"@opentelemetry/instrumentation-express": "0.44.0",
"@opentelemetry/instrumentation-fastify": "0.41.0",
"@opentelemetry/instrumentation-fs": "0.16.0",
"@opentelemetry/instrumentation": "^0.55.0",
"@opentelemetry/instrumentation-amqplib": "^0.44.0",
"@opentelemetry/instrumentation-connect": "0.41.0",
"@opentelemetry/instrumentation-dataloader": "0.14.0",
"@opentelemetry/instrumentation-express": "0.45.0",
"@opentelemetry/instrumentation-fastify": "0.42.0",
"@opentelemetry/instrumentation-fs": "0.17.0",
"@opentelemetry/instrumentation-generic-pool": "0.39.0",
"@opentelemetry/instrumentation-graphql": "0.44.0",
"@opentelemetry/instrumentation-hapi": "0.41.0",
"@opentelemetry/instrumentation-http": "0.53.0",
"@opentelemetry/instrumentation-http": "0.55.0",
"@opentelemetry/instrumentation-ioredis": "0.43.0",
"@opentelemetry/instrumentation-kafkajs": "0.4.0",
"@opentelemetry/instrumentation-knex": "0.41.0",
Expand All @@ -94,8 +94,8 @@
"@opentelemetry/instrumentation-tedious": "0.15.0",
"@opentelemetry/instrumentation-undici": "0.6.0",
"@opentelemetry/resources": "^1.26.0",
"@opentelemetry/sdk-trace-base": "^1.26.0",
"@opentelemetry/semantic-conventions": "^1.27.0",
"@opentelemetry/sdk-trace-base": "^1.28.0",
"@opentelemetry/semantic-conventions": "^1.28.0",
"@prisma/instrumentation": "5.19.1",
"@sentry/core": "8.42.0",
"@sentry/opentelemetry": "8.42.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import type * as https from 'node:https';
import { VERSION } from '@opentelemetry/core';
import type { InstrumentationConfig } from '@opentelemetry/instrumentation';
import { InstrumentationBase, InstrumentationNodeModuleDefinition } from '@opentelemetry/instrumentation';
import { getRequestInfo } from '@opentelemetry/instrumentation-http';
import type { RequestEventData, SanitizedRequestData, Scope } from '@sentry/core';
import {
addBreadcrumb,
Expand All @@ -21,7 +20,7 @@ import {
import { DEBUG_BUILD } from '../../debug-build';
import type { NodeClient } from '../../sdk/client';
import { getRequestUrl } from '../../utils/getRequestUrl';

import { getRequestInfo } from './vendor/getRequestInfo';
type Http = typeof http;
type Https = typeof https;

Expand Down Expand Up @@ -196,7 +195,7 @@ export class SentryHttpInstrumentation extends InstrumentationBase<SentryHttpIns
? (argsCopy.shift() as http.RequestOptions)
: undefined;

const { optionsParsed } = getRequestInfo(options, extraOptions);
const { optionsParsed } = getRequestInfo(instrumentation._diag, options, extraOptions);

const request = original.apply(this, args) as ReturnType<typeof http.request>;

Expand Down
157 changes: 157 additions & 0 deletions packages/node/src/integrations/http/vendor/getRequestInfo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/* eslint-disable complexity */

/**
* Vendored in from https://github.com/open-telemetry/opentelemetry-js/commit/87bd98edd24c98a5fbb9a56fed4b673b7f17a724
*/

/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import type { RequestOptions } from 'node:http';
import * as url from 'url';
import type { DiagLogger } from '@opentelemetry/api';

/**
* Makes sure options is an url object
* return an object with default value and parsed options
* @param logger component logger
* @param options original options for the request
* @param [extraOptions] additional options for the request
*/
export const getRequestInfo = (
logger: DiagLogger,
options: url.URL | RequestOptions | string,
extraOptions?: RequestOptions,
): {
origin: string;
pathname: string;
method: string;
invalidUrl: boolean;
optionsParsed: RequestOptions;
} => {
let pathname: string;
let origin: string;
let optionsParsed: RequestOptions;
let invalidUrl = false;
if (typeof options === 'string') {
try {
const convertedOptions = stringUrlToHttpOptions(options);
optionsParsed = convertedOptions;
pathname = convertedOptions.pathname || '/';
} catch (e) {
invalidUrl = true;
logger.verbose(
'Unable to parse URL provided to HTTP request, using fallback to determine path. Original error:',
e,
);
// for backward compatibility with how url.parse() behaved.
optionsParsed = {
path: options,
};
pathname = optionsParsed.path || '/';
}

origin = `${optionsParsed.protocol || 'http:'}//${optionsParsed.host}`;
if (extraOptions !== undefined) {
Object.assign(optionsParsed, extraOptions);
}
} else if (options instanceof url.URL) {
optionsParsed = {
protocol: options.protocol,
hostname:
typeof options.hostname === 'string' && options.hostname.startsWith('[')
? options.hostname.slice(1, -1)
: options.hostname,
path: `${options.pathname || ''}${options.search || ''}`,
};
if (options.port !== '') {
optionsParsed.port = Number(options.port);
}
if (options.username || options.password) {
optionsParsed.auth = `${options.username}:${options.password}`;
}
pathname = options.pathname;
origin = options.origin;
if (extraOptions !== undefined) {
Object.assign(optionsParsed, extraOptions);
}
} else {
optionsParsed = Object.assign({ protocol: options.host ? 'http:' : undefined }, options);

const hostname =
optionsParsed.host ||
(optionsParsed.port != null ? `${optionsParsed.hostname}${optionsParsed.port}` : optionsParsed.hostname);
origin = `${optionsParsed.protocol || 'http:'}//${hostname}`;

pathname = (options as url.URL).pathname;
if (!pathname && optionsParsed.path) {
try {
const parsedUrl = new URL(optionsParsed.path, origin);
pathname = parsedUrl.pathname || '/';
} catch (e) {
pathname = '/';
}
}
}

// some packages return method in lowercase..
// ensure upperCase for consistency
const method = optionsParsed.method ? optionsParsed.method.toUpperCase() : 'GET';

return { origin, pathname, method, optionsParsed, invalidUrl };
};

/**
* Mimics Node.js conversion of URL strings to RequestOptions expected by
* `http.request` and `https.request` APIs.
*
* See https://github.com/nodejs/node/blob/2505e217bba05fc581b572c685c5cf280a16c5a3/lib/internal/url.js#L1415-L1437
*
* @param stringUrl
* @throws TypeError if the URL is not valid.
*/
function stringUrlToHttpOptions(stringUrl: string): RequestOptions & { pathname: string } {
// This is heavily inspired by Node.js handling of the same situation, trying
// to follow it as closely as possible while keeping in mind that we only
// deal with string URLs, not URL objects.
const { hostname, pathname, port, username, password, search, protocol, hash, href, origin, host } = new URL(
stringUrl,
);

const options: RequestOptions & {
pathname: string;
hash: string;
search: string;
href: string;
origin: string;
} = {
protocol: protocol,
hostname: hostname && hostname[0] === '[' ? hostname.slice(1, -1) : hostname,
hash: hash,
search: search,
pathname: pathname,
path: `${pathname || ''}${search || ''}`,
href: href,
origin: origin,
host: host,
};
if (port !== '') {
options.port = Number(port);
}
if (username || password) {
options.auth = `${decodeURIComponent(username)}:${decodeURIComponent(password)}`;
}
return options;
}
10 changes: 5 additions & 5 deletions packages/node/src/sdk/initOtel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,12 +136,12 @@ export function setupOtel(client: NodeClient): BasicTracerProvider {
[ATTR_SERVICE_VERSION]: SDK_VERSION,
}),
forceFlushTimeoutMillis: 500,
spanProcessors: [
new SentrySpanProcessor({
timeout: client.getOptions().maxSpanWaitDuration,
}),
],
});
provider.addSpanProcessor(
new SentrySpanProcessor({
timeout: client.getOptions().maxSpanWaitDuration,
}),
);

// Initialize the provider
provider.register({
Expand Down
4 changes: 2 additions & 2 deletions packages/node/test/integration/transactions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -680,7 +680,7 @@ describe('Integration | Transactions', () => {

expect(spans).toHaveLength(2);

expect(spans[0]!.description).toEqual('inner span 1');
expect(spans[1]!.description).toEqual('inner span 2');
expect(spans).toContainEqual(expect.objectContaining({ description: 'inner span 1' }));
expect(spans).toContainEqual(expect.objectContaining({ description: 'inner span 2' }));
});
});
16 changes: 8 additions & 8 deletions packages/opentelemetry/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,17 @@
},
"peerDependencies": {
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/core": "^1.25.1",
"@opentelemetry/instrumentation": "^0.54.0",
"@opentelemetry/sdk-trace-base": "^1.26.0",
"@opentelemetry/semantic-conventions": "^1.27.0"
"@opentelemetry/core": "^1.28.0",
"@opentelemetry/instrumentation": "^0.55.0",
"@opentelemetry/sdk-trace-base": "^1.28.0",
"@opentelemetry/semantic-conventions": "^1.28.0"
},
"devDependencies": {
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/context-async-hooks": "^1.25.1",
"@opentelemetry/core": "^1.25.1",
"@opentelemetry/sdk-trace-base": "^1.26.0",
"@opentelemetry/semantic-conventions": "^1.27.0"
"@opentelemetry/context-async-hooks": "^1.28.0",
"@opentelemetry/core": "^1.28.0",
"@opentelemetry/sdk-trace-base": "^1.28.0",
"@opentelemetry/semantic-conventions": "^1.28.0"
},
"scripts": {
"build": "run-p build:transpile build:types",
Expand Down
Loading

0 comments on commit d631127

Please sign in to comment.