Skip to content

Commit 9cc4c42

Browse files
msonnbclaude
andcommitted
feat(google-cloud-serverless)!: Use http.client span op for GCP HTTP requests
The endpoint-derived suffix fragmented grouping and was unbounded for non-`googleapis.com` endpoints. Service identity moves to the `server.address` attribute; `http.request.method` is now set as well. Ref: JS-3105 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 70b578b commit 9cc4c42

4 files changed

Lines changed: 18 additions & 17 deletions

File tree

MIGRATION.md

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -254,16 +254,6 @@ Affected SDKs: All SDKs.
254254

255255
If you reference these attributes in custom instrumentation, `beforeSendSpan`, dashboards, or alerts, update them to the new names.
256256

257-
### Span operation changes
258-
259-
Affected SDKs: All SDKs.
260-
261-
Span operations (`sentry.op`) were aligned with the values defined in `@sentry/conventions`:
262-
263-
- `@sentry/node`: Firebase Functions spans now use `function.gcp` instead of `http.request`. The wrapper instruments all function trigger types (HTTP, Firestore, scheduler, storage), so a fixed HTTP op was wrong. The trigger type remains available on the `faas.trigger` attribute.
264-
265-
If you reference these operations in dashboards, alerts, or `beforeSendSpan`, update them to the new values.
266-
267257
### `thirdPartyErrorFilterIntegration` filters internal frames by default
268258

269259
Affected SDKs: All SDKs.

packages/google-cloud-serverless/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
"access": "public"
4242
},
4343
"dependencies": {
44+
"@sentry/conventions": "^0.16.0",
4445
"@sentry/core": "10.67.0",
4546
"@sentry/node": "10.67.0"
4647
},

packages/google-cloud-serverless/src/integrations/google-cloud-http.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
import type * as common from '@google-cloud/common';
2+
import { HTTP_REQUEST_METHOD, SERVER_ADDRESS } from '@sentry/conventions/attributes';
3+
import { WEB_SERVER_HTTP_CLIENT_SPAN_OP } from '@sentry/conventions/op';
24
import type { Client, IntegrationFn } from '@sentry/core';
35
import {
46
defineIntegration,
57
fill,
68
getClient,
9+
isURLObjectRelative,
10+
parseStringToURLObject,
711
SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
812
SentryNonRecordingSpan,
913
} from '@sentry/core';
@@ -54,9 +58,11 @@ function wrapRequestFunction(orig: RequestFunction): RequestFunction {
5458
? startInactiveSpan({
5559
name: `${httpMethod} ${reqOpts.uri}`,
5660
onlyIfParent: true,
57-
op: `http.client.${identifyService(this.apiEndpoint)}`,
61+
op: WEB_SERVER_HTTP_CLIENT_SPAN_OP,
5862
attributes: {
5963
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.serverless',
64+
[HTTP_REQUEST_METHOD]: httpMethod,
65+
[SERVER_ADDRESS]: getServerAddress(this.apiEndpoint),
6066
},
6167
})
6268
: new SentryNonRecordingSpan();
@@ -67,8 +73,8 @@ function wrapRequestFunction(orig: RequestFunction): RequestFunction {
6773
};
6874
}
6975

70-
/** Identifies service by its base url */
71-
function identifyService(apiEndpoint: string): string {
72-
const match = apiEndpoint.match(/^https:\/\/(\w+)\.googleapis.com$/);
73-
return match?.[1] || apiEndpoint.replace(/^(http|https)?:\/\//, '');
76+
/** Extracts the host of the API endpoint the request is sent to */
77+
function getServerAddress(apiEndpoint: string): string {
78+
const url = parseStringToURLObject(apiEndpoint);
79+
return url && !isURLObjectRelative(url) ? url.host : apiEndpoint;
7480
}

packages/google-cloud-serverless/test/integrations/google-cloud-http.test.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,19 +76,23 @@ describe('GoogleCloudHttp tracing', () => {
7676
const resp = await bigquery.query('SELECT true AS foo');
7777
expect(resp).toEqual([[{ foo: true }]]);
7878
expect(mockStartInactiveSpan).toBeCalledWith({
79-
op: 'http.client.bigquery',
79+
op: 'http.client',
8080
name: 'POST /jobs',
8181
onlyIfParent: true,
8282
attributes: {
8383
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.serverless',
84+
'http.request.method': 'POST',
85+
'server.address': 'bigquery.googleapis.com',
8486
},
8587
});
8688
expect(mockStartInactiveSpan).toBeCalledWith({
87-
op: 'http.client.bigquery',
89+
op: 'http.client',
8890
name: expect.stringMatching(/^GET \/queries\/.+/),
8991
onlyIfParent: true,
9092
attributes: {
9193
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.serverless',
94+
'http.request.method': 'GET',
95+
'server.address': 'bigquery.googleapis.com',
9296
},
9397
});
9498
});

0 commit comments

Comments
 (0)