Skip to content

Commit 6b3db7b

Browse files
author
Luca Forstner
authored
feat(node): Add basic cloud resource context (#8764)
1 parent 51159b7 commit 6b3db7b

File tree

3 files changed

+106
-4
lines changed

3 files changed

+106
-4
lines changed

packages/node/src/integrations/context.ts

Lines changed: 85 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* eslint-disable max-lines */
22
import type {
33
AppContext,
4+
CloudResourceContext,
45
Contexts,
56
CultureContext,
67
DeviceContext,
@@ -29,6 +30,7 @@ interface ContextOptions {
2930
os?: boolean;
3031
device?: DeviceContextOptions | boolean;
3132
culture?: boolean;
33+
cloudResource?: boolean;
3234
}
3335

3436
/** Add node modules / packages to the event */
@@ -48,9 +50,15 @@ export class Context implements Integration {
4850
*/
4951
private _cachedContext: Promise<Contexts> | undefined;
5052

51-
public constructor(private readonly _options: ContextOptions = { app: true, os: true, device: true, culture: true }) {
52-
//
53-
}
53+
public constructor(
54+
private readonly _options: ContextOptions = {
55+
app: true,
56+
os: true,
57+
device: true,
58+
culture: true,
59+
cloudResource: true,
60+
},
61+
) {}
5462

5563
/**
5664
* @inheritDoc
@@ -73,6 +81,7 @@ export class Context implements Integration {
7381
os: { ...updatedContext.os, ...event.contexts?.os },
7482
device: { ...updatedContext.device, ...event.contexts?.device },
7583
culture: { ...updatedContext.culture, ...event.contexts?.culture },
84+
cloud_resource: { ...updatedContext.cloud_resource, ...event.contexts?.cloud_resource },
7685
};
7786

7887
return event;
@@ -120,6 +129,10 @@ export class Context implements Integration {
120129
}
121130
}
122131

132+
if (this._options.cloudResource) {
133+
contexts.cloud_resource = getCloudResourceContext();
134+
}
135+
123136
return contexts;
124137
}
125138
}
@@ -380,3 +393,72 @@ async function getLinuxInfo(): Promise<OsContext> {
380393

381394
return linuxInfo;
382395
}
396+
397+
/**
398+
* Grabs some information about hosting provider based on best effort.
399+
*/
400+
function getCloudResourceContext(): CloudResourceContext | undefined {
401+
if (process.env.VERCEL) {
402+
// https://vercel.com/docs/concepts/projects/environment-variables/system-environment-variables#system-environment-variables
403+
return {
404+
'cloud.provider': 'vercel',
405+
'cloud.region': process.env.VERCEL_REGION,
406+
};
407+
} else if (process.env.AWS_REGION) {
408+
// https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html
409+
return {
410+
'cloud.provider': 'aws',
411+
'cloud.region': process.env.AWS_REGION,
412+
'cloud.platform': process.env.AWS_EXECUTION_ENV,
413+
};
414+
} else if (process.env.GCP_PROJECT) {
415+
// https://cloud.google.com/composer/docs/how-to/managing/environment-variables#reserved_variables
416+
return {
417+
'cloud.provider': 'gcp',
418+
};
419+
} else if (process.env.ALIYUN_REGION_ID) {
420+
// TODO: find where I found these environment variables - at least gc.github.com returns something
421+
return {
422+
'cloud.provider': 'alibaba_cloud',
423+
'cloud.region': process.env.ALIYUN_REGION_ID,
424+
};
425+
} else if (process.env.WEBSITE_SITE_NAME && process.env.REGION_NAME) {
426+
// https://learn.microsoft.com/en-us/azure/app-service/reference-app-settings?tabs=kudu%2Cdotnet#app-environment
427+
return {
428+
'cloud.provider': 'azure',
429+
'cloud.region': process.env.REGION_NAME,
430+
};
431+
} else if (process.env.IBM_CLOUD_REGION) {
432+
// TODO: find where I found these environment variables - at least gc.github.com returns something
433+
return {
434+
'cloud.provider': 'ibm_cloud',
435+
'cloud.region': process.env.IBM_CLOUD_REGION,
436+
};
437+
} else if (process.env.TENCENTCLOUD_REGION) {
438+
// https://www.tencentcloud.com/document/product/583/32748
439+
return {
440+
'cloud.provider': 'tencent_cloud',
441+
'cloud.region': process.env.TENCENTCLOUD_REGION,
442+
'cloud.account.id': process.env.TENCENTCLOUD_APPID,
443+
'cloud.availability_zone': process.env.TENCENTCLOUD_ZONE,
444+
};
445+
} else if (process.env.NETLIFY) {
446+
// https://docs.netlify.com/configure-builds/environment-variables/#read-only-variables
447+
return {
448+
'cloud.provider': 'netlify',
449+
};
450+
} else if (process.env.FLY_REGION) {
451+
// https://fly.io/docs/reference/runtime-environment/
452+
return {
453+
'cloud.provider': 'fly.io',
454+
'cloud.region': process.env.FLY_REGION,
455+
};
456+
} else if (process.env.DYNO) {
457+
// https://devcenter.heroku.com/articles/dynos#local-environment-variables
458+
return {
459+
'cloud.provider': 'heroku',
460+
};
461+
} else {
462+
return undefined;
463+
}
464+
}

packages/types/src/context.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export interface Contexts extends Record<string, Context | undefined> {
99
culture?: CultureContext;
1010
response?: ResponseContext;
1111
trace?: TraceContext;
12+
cloud_resource?: CloudResourceContext;
1213
}
1314

1415
export interface AppContext extends Record<string, unknown> {
@@ -93,3 +94,13 @@ export interface TraceContext extends Record<string, unknown> {
9394
tags?: { [key: string]: Primitive };
9495
trace_id: string;
9596
}
97+
98+
export interface CloudResourceContext extends Record<string, unknown> {
99+
['cloud.provider']?: string;
100+
['cloud.account.id']?: string;
101+
['cloud.region']?: string;
102+
['cloud.availability_zone']?: string;
103+
['cloud.platform']?: string;
104+
['host.id']?: string;
105+
['host.type']?: string;
106+
}

packages/types/src/index.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,16 @@ export type {
99
} from './breadcrumb';
1010
export type { Client } from './client';
1111
export type { ClientReport, Outcome, EventDropReason } from './clientreport';
12-
export type { Context, Contexts, DeviceContext, OsContext, AppContext, CultureContext, TraceContext } from './context';
12+
export type {
13+
Context,
14+
Contexts,
15+
DeviceContext,
16+
OsContext,
17+
AppContext,
18+
CultureContext,
19+
TraceContext,
20+
CloudResourceContext,
21+
} from './context';
1322
export type { DataCategory } from './datacategory';
1423
export type { DsnComponents, DsnLike, DsnProtocol } from './dsn';
1524
export type { DebugImage, DebugMeta } from './debugMeta';

0 commit comments

Comments
 (0)