Skip to content
Merged
Show file tree
Hide file tree
Changes from 90 commits
Commits
Show all changes
99 commits
Select commit Hold shift + click to select a range
f21374e
chore!: update to JS SDK 2.x
trentm Feb 27, 2025
196af25
instr-pino
trentm Mar 4, 2025
857166f
bump engines.node to new min (same as for core repo)
trentm Mar 4, 2025
3f608cf
drop testing node 14 and 16 for test-all-versions in CI as well
trentm Mar 4, 2025
2536765
contrib-test-utils, instrumentation-fastify
trentm Mar 4, 2025
1c396e6
drop CI testing of Node.js v23; that can be handled separately (see h…
trentm Mar 4, 2025
68a965f
instr-kafkajs
trentm Mar 4, 2025
a909c2f
fix lint for contrib-test-utils
trentm Mar 4, 2025
aeba686
instr-router
trentm Mar 4, 2025
8e0db93
instr-socket.io
trentm Mar 4, 2025
c595cae
fix lint for instr-fastify
trentm Mar 4, 2025
59cf3ab
instr-undici
trentm Mar 4, 2025
3455906
instr-mongoose
trentm Mar 4, 2025
4e25644
instr-mysql
trentm Mar 4, 2025
c59311b
instr-mysql2
trentm Mar 4, 2025
5e6795f
instrumentation-cassandra-driver
trentm Mar 4, 2025
92f08e8
instr-express
trentm Mar 4, 2025
45a8d24
instr-tedious
trentm Mar 4, 2025
f8ff8f5
instr-redis-4
trentm Mar 4, 2025
a4340eb
instr-lru-memoizer
trentm Mar 4, 2025
91f660d
instr-mongodb
trentm Mar 4, 2025
bc48513
instr-amqplib
trentm Mar 4, 2025
75149a6
instr-koa
trentm Mar 4, 2025
4b14191
instr-memcached
trentm Mar 4, 2025
7cfb637
instr-ioredis
trentm Mar 4, 2025
b0c9be4
instr-hapi
trentm Mar 4, 2025
0809b07
instr-pg
trentm Mar 4, 2025
f42472e
instr-aws-sdk
trentm Mar 4, 2025
86a3039
lint:fix for instr-mongodb
trentm Mar 4, 2025
89c288b
lint:fix for instr-aws-sdk
trentm Mar 4, 2025
a542287
syntax fix for instr-mysql
trentm Mar 4, 2025
e79ca80
instr-redis
trentm Mar 4, 2025
fc11a5a
resource-detector-container
trentm Mar 4, 2025
41fa127
resource-detector-gcp
trentm Mar 5, 2025
874223b
lint:fix
trentm Mar 5, 2025
1b1088c
lint:fix
trentm Mar 5, 2025
3f91296
resource-detector-azure
trentm Mar 5, 2025
4777b71
resource-detector-alibaba-cloud
trentm Mar 5, 2025
052aede
resource-detector-aws
trentm Mar 6, 2025
e6c5dba
resource-detector-instana
trentm Mar 6, 2025
ec39a25
lint:fix
trentm Mar 6, 2025
f8e5f39
auto-instrumentations-node
trentm Mar 6, 2025
d05078b
rm unused function
trentm Mar 6, 2025
a22039b
add missing devDep @opentelemetry/sdk-trace-base that was resulting i…
trentm Mar 6, 2025
9b9ac23
bump to dev.1 release of the 2.x/0.200 packages
trentm Mar 6, 2025
79f9cb1
missing dep for detector-instana
trentm Mar 6, 2025
56e7936
instr-net
trentm Mar 6, 2025
956afca
instr-dns
trentm Mar 6, 2025
3d6393d
lint:fix
trentm Mar 6, 2025
b4fd769
instr-generic-pool
trentm Mar 6, 2025
c18d50a
instr-connect
trentm Mar 6, 2025
e6deeaa
instr-fs
trentm Mar 6, 2025
43fefee
instr-dataloader
trentm Mar 6, 2025
b5c7e24
instr-knex
trentm Mar 6, 2025
af81042
disable expensive TAV tests while this PR is in draft
trentm Mar 6, 2025
9ff500b
instr-cucumber
trentm Mar 6, 2025
10769ef
instr-restify
trentm Mar 6, 2025
b419889
instr-winston
trentm Mar 6, 2025
4afd69b
instr-nestjs-core
trentm Mar 6, 2025
2762f09
instr-runtime-node
trentm Mar 6, 2025
cc8c92a
instr-aws-lambda
trentm Mar 6, 2025
14200a6
instr-graphql
trentm Mar 6, 2025
7d29fa5
instr-document-load (however, tests are broken and I don't know why)
trentm Mar 7, 2025
be39ec5
instr-runtime-node: forgot to bump engines.node
trentm Mar 7, 2025
94cbd86
resource-detector-github
trentm Mar 7, 2025
d0c3cac
winston-transport
trentm Mar 7, 2025
6ac0998
sql-common
trentm Mar 7, 2025
aa7d46b
propagation-utils
trentm Mar 7, 2025
c5f4217
redis-common
trentm Mar 7, 2025
b9ca473
host-metrics
trentm Mar 7, 2025
0aa86a0
baggage-span-processor
trentm Mar 7, 2025
08de3e1
id-generator-aws-xray
trentm Mar 7, 2025
9e94114
propagator-aws-xray, propagator-aws-xray-lambda
trentm Mar 7, 2025
89a97f1
propagator-ot-trace
trentm Mar 7, 2025
e65b04d
propagator-instana
trentm Mar 7, 2025
bee8915
auto-configuration-propagators
trentm Mar 7, 2025
c1a378e
instr-user-interaction
trentm Mar 7, 2025
052563c
instr-long-task
trentm Mar 7, 2025
dc37f5f
plugin-react-load
trentm Mar 7, 2025
145c5d1
update to [email protected], set ES2022 as new base target
trentm Mar 7, 2025
8310118
lint:fix
trentm Mar 7, 2025
a891211
fix a test failure in instr-user-interaction
trentm Mar 7, 2025
741ff2e
lint:fix
trentm Mar 7, 2025
896a836
hack to attempt to grok the test hangs observed in CI
trentm Mar 7, 2025
b2cd322
fix a https://www.typescriptlang.org/tsconfig/#useDefineForClassField…
trentm Mar 7, 2025
9a2f06a
some possible additional https://www.typescriptlang.org/tsconfig/#use…
trentm Mar 7, 2025
fabce63
fix mysql2 test failure resulting from attempting to mix dynamic-impo…
trentm Mar 7, 2025
2e80939
restore full testing
trentm Mar 7, 2025
ba2bd08
Merge branch 'main' into tm-sdk2-attempt
trentm Mar 10, 2025
2565aa0
update from dev.1 prerelease of otel core packages to rc.1
trentm Mar 12, 2025
1145014
remove accidentally left .only in tests
trentm Mar 12, 2025
5d2a1b5
fix tests for instr-document-load: presence of PerformanceResourceTim…
trentm Mar 13, 2025
d447c47
use TS compile-time `private` annotation on this internal method
trentm Mar 14, 2025
af04cd7
lint:fix for style; fix a lint warning about unused _config arg
trentm Mar 14, 2025
86ec210
fix compile error, stemming from earlier lint fix :)
trentm Mar 14, 2025
9cb5f76
bump deps to released 2.0.0 / 0.200.0 versions
trentm Mar 17, 2025
e3a689f
fix resource detectors to never have their async attribute promises r…
trentm Mar 18, 2025
eec7ce5
Merge branch 'main' into tm-sdk2-attempt
trentm Mar 18, 2025
2bf52ff
try with a bigger timeout now that we are running all the resource de…
trentm Mar 18, 2025
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
5 changes: 1 addition & 4 deletions .github/workflows/test-all-versions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ jobs:
strategy:
fail-fast: false
matrix:
node: ["14", "16", "18", "20", "22"]
node: ["18", "20", "22"]
runs-on: ubuntu-latest
services:
mongo:
Expand Down Expand Up @@ -143,9 +143,6 @@ jobs:
node-version: ${{ matrix.node }}
- name: Set MySQL variables
run: mysql --user=root --password=${MYSQL_ROOT_PASSWORD} --host=${MYSQL_HOST} --port=${MYSQL_PORT} -e "SET GLOBAL log_output='TABLE'; SET GLOBAL general_log = 1;" mysql
- name: Update npm to a version that supports workspaces (v7 or later)
if: ${{ matrix.node < 16 }}
run: npm install -g npm@9 # npm@9 supports node >=14.17.0
- name: Install
run: npm ci
- name: Download Build Artifacts
Expand Down
10 changes: 6 additions & 4 deletions .github/workflows/unit-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,12 @@ jobs:
strategy:
fail-fast: false
matrix:
node: ["14", "16", "18", "20", "22"]
node:
- "18.19.0"
- "18"
- "20.6.0"
- "20"
- "22"
include:
- node: 18
code-coverage: true
Expand Down Expand Up @@ -151,9 +156,6 @@ jobs:
node-version: ${{ matrix.node }}
- name: Set MySQL variables
run: mysql --user=root --password=${MYSQL_ROOT_PASSWORD} --host=${MYSQL_HOST} --port=${MYSQL_PORT} -e "SET GLOBAL log_output='TABLE'; SET GLOBAL general_log = 1;" mysql
- name: Update npm to a version that supports workspaces (v7 or later)
if: ${{ matrix.node < 16 }}
run: npm install -g npm@9 # npm@9 supports node >=14.17.0
- name: Install
run: npm ci
- name: Download Build Artifacts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"author": "OpenTelemetry Authors",
"license": "Apache-2.0",
"engines": {
"node": ">=14"
"node": "^18.19.0 || >=20.6.0"
},
"files": [
"build/src/**/*.js",
Expand All @@ -44,21 +44,22 @@
"devDependencies": {
"@opentelemetry/api": "^1.0.0",
"@opentelemetry/contrib-test-utils": "^0.45.1",
"@opentelemetry/sdk-trace-base": "^2.0.0-rc.1",
"@types/mocha": "10.0.10",
"@types/node": "18.18.14",
"@types/sinon": "17.0.4",
"nock": "13.3.3",
"nyc": "15.1.0",
"rimraf": "5.0.10",
"sinon": "15.2.0",
"typescript": "4.4.4"
"typescript": "5.0.4"
},
"peerDependencies": {
"@opentelemetry/api": "^1.0.0"
},
"dependencies": {
"@opentelemetry/core": "^1.26.0",
"@opentelemetry/resources": "^1.10.0",
"@opentelemetry/core": "^2.0.0-rc.1",
"@opentelemetry/resources": "^2.0.0-rc.1",
"@opentelemetry/semantic-conventions": "^1.27.0"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/detectors/node/opentelemetry-resource-detector-alibaba-cloud#readme",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,9 @@
import { context } from '@opentelemetry/api';
import { suppressTracing } from '@opentelemetry/core';
import {
DetectorSync,
IResource,
Resource,
ResourceAttributes,
ResourceDetectionConfig,
ResourceDetector,
DetectedResource,
DetectedResourceAttributes,
} from '@opentelemetry/resources';
import {
CLOUDPLATFORMVALUES_ALIBABA_CLOUD_ECS,
Expand All @@ -43,7 +41,7 @@ import * as http from 'http';
* AlibabaCloud ECS and return a {@link Resource} populated with metadata about
* the ECS instance. Returns an empty Resource if detection fails.
*/
class AlibabaCloudEcsDetector implements DetectorSync {
class AlibabaCloudEcsDetector implements ResourceDetector {
/**
* See https://www.alibabacloud.com/help/doc-detail/67254.htm for
* documentation about the AlibabaCloud instance identity document.
Expand All @@ -62,35 +60,38 @@ class AlibabaCloudEcsDetector implements DetectorSync {
*
* @param config (unused) The resource detection config
*/
detect(_config?: ResourceDetectionConfig): IResource {
detect(): DetectedResource {
const attributes = context.with(suppressTracing(context.active()), () =>
this._getAttributes()
);
return new Resource({}, attributes);
return { attributes };
}

/** Gets identity and host info and returns them as attribs. Empty object if fails */
async _getAttributes(
_config?: ResourceDetectionConfig
): Promise<ResourceAttributes> {
const {
'owner-account-id': accountId,
'instance-id': instanceId,
'instance-type': instanceType,
'region-id': region,
'zone-id': availabilityZone,
} = await this._fetchIdentity();
const hostname = await this._fetchHost();
_getAttributes(): DetectedResourceAttributes {
const dataP = Promise.all([this._fetchIdentity(), this._fetchHost()]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

running some tests in Elastic's distribution I got an error of an unhandled promise rejection

node ./test/agent-metadata.test.js
TAP version 13
# agent metadata
# agent metadata default case
not ok 1 exited successfully: err=Error: Command failed: /Users/david/.nvm/versions/node/v18.19.0/bin/node ./fixtures/use-http-get.js node:internal/process/promises:288 triggerUncaughtException(err, true /* fromPromise */); ^ Error: ECS metadata api request timed out. at Timeout._onTimeout (/Users/david/Documents/repos/otel/opentelemetry-js-contrib/detectors/node/opentelemetry-resource-detector-alibaba-cloud/build/src/detectors/AlibabaCloudEcsDetector.js:91:29) at listOnTimeout (node:internal/timers:569:17) at process.processTimers (node:internal/timers:512:7) Node.js v18.19.0 
  ---
    operator: error
    at: done (/Users/david/Documents/repos/el/elastic-otel-node/packages/opentelemetry-node/test/testutils.js:648:35)
    stack: |-
      Error: Command failed: /Users/david/.nvm/versions/node/v18.19.0/bin/node ./fixtures/use-http-get.js
      node:internal/process/promises:288
                  triggerUncaughtException(err, true /* fromPromise */);
                  ^
      
      Error: ECS metadata api request timed out.
          at Timeout._onTimeout (/Users/david/Documents/repos/otel/opentelemetry-js-contrib/detectors/node/opentelemetry-resource-detector-alibaba-cloud/build/src/detectors/AlibabaCloudEcsDetector.js:91:29)
          at listOnTimeout (node:internal/timers:569:17)
          at process.processTimers (node:internal/timers:512:7)
      
      Node.js v18.19.0
      
          at ChildProcess.exithandler (node:child_process:422:12)
          at ChildProcess.emit (node:events:517:28)
          at maybeClose (node:internal/child_process:1098:16)
          at ChildProcess._handle.onexit (node:internal/child_process:303:5)
  ...
# stdout:
# |{"name":"elastic-otel-node","level":30,"preamble":true,"distroVersion":"0.7.0","env":{"os":"darwin 24.3.0","arch":"arm64","runtime":"Node.js v18.19.0"},"msg":"start Elastic Distribution of OpenTelemetry Node.js","time":"2025-03-17T12:12:47.063Z"}
# |{"name":"elastic-otel-node","level":50,"msg":"Accessing resource attributes before async attributes settled","time":"2025-03-17T12:12:47.074Z"}
# |{"name":"elastic-otel-node","level":50,"msg":"Accessing resource attributes before async attributes settled","time":"2025-03-17T12:12:47.074Z"}
# |{"name":"elastic-otel-node","level":50,"msg":"Accessing resource attributes before async attributes settled","time":"2025-03-17T12:12:47.074Z"}
# |{"name":"elastic-otel-node","level":50,"msg":"Accessing resource attributes before async attributes settled","time":"2025-03-17T12:12:47.074Z"}
# |{"name":"elastic-otel-node","level":50,"msg":"Accessing resource attributes before async attributes settled","time":"2025-03-17T12:12:47.074Z"}
# |client response: 200 {
# |  date: 'Mon, 17 Mar 2025 12:12:47 GMT',
# |  expires: '-1',
# |  'cache-control': 'private, max-age=0',
# |  'content-type': 'text/html; charset=ISO-8859-1',
# |  'content-security-policy-report-only': "object-src 'none';base-uri 'self';script-src 'nonce-8TGjP3Y6JPSYBgb6x6Gcsg' 'strict-dynamic' 'report-sample' 'unsafe-eval' 'unsafe-inline' https: http:;report-uri https://csp.withgoogle.com/csp/gws/other-hp",
# |  server: 'gws',
# |  'x-xss-protection': '0',
# |  'x-frame-options': 'SAMEORIGIN',
# |  'set-cookie': [Array],
# |  'accept-ranges': 'none',
# |  vary: 'Accept-Encoding',
# |  connection: 'close',
# |  'transfer-encoding': 'chunked'
# |}
# |client response: end
# stderr:
# |node:internal/process/promises:288
# |            triggerUncaughtException(err, true /* fromPromise */);
# |            ^
# |
# |Error: ECS metadata api request timed out.
# |    at Timeout._onTimeout (/Users/david/Documents/repos/otel/opentelemetry-js-contrib/detectors/node/opentelemetry-resource-detector-alibaba-cloud/build/src/detectors/AlibabaCloudEcsDetector.js:91:29)
# |    at listOnTimeout (node:internal/timers:569:17)
# |    at process.processTimers (node:internal/timers:512:7)
# |
# |Node.js v18.19.0
# skip checkTelemetry because process errored out

1..1
# tests 1
# pass  0
# fail  1

In this detector and other that are doing async operations we have promises that need to be handled if they reject. I think is because now the detectResources method from @opentelemetry/resources does defer the handling of the rejected ones. Checking ResourceImpl constructor we see values are kept but not handled until waitForAsyncAttributes is called (I think in exporters).

We could solve it by being more eager on handling the async attributes in ResourceImpl or by handling all possible rejections in each detector. Doing the later means we should add a second callback function for each promised value in the attribs object. Something like

    const resolveUndef = () => undefined;
    return {
      [SEMRESATTRS_CLOUD_PROVIDER]: dataP.then(
        () => CLOUDPROVIDERVALUES_ALIBABA_CLOUD,
        resolveUndef
      ),
      [SEMRESATTRS_CLOUD_PLATFORM]: dataP.then(
        () => CLOUDPLATFORMVALUES_ALIBABA_CLOUD_ECS,
        resolveUndef
      ),

      // Data from _fetchIdentity()
      [SEMRESATTRS_CLOUD_ACCOUNT_ID]: dataP.then(
        data => data[0]['owner-account-id'],
        resolveUndef
      ),
      [SEMRESATTRS_CLOUD_REGION]: dataP.then(data => data[0]['region-id']),
      [SEMRESATTRS_CLOUD_AVAILABILITY_ZONE]: dataP.then(
        data => data[0]['zone-id']
      ),
      [SEMRESATTRS_HOST_ID]: dataP.then(
        data => data[0]['instance-id'],
        resolveUndef
      ),
      [SEMRESATTRS_HOST_TYPE]: dataP.then(
         data => data[0]['instance-type'],
        resolveUndef
      ),

      // Data from _fetchHost()
      [SEMRESATTRS_HOST_NAME]: dataP.then(
         data => data[1],
        resolveUndef
      ),
    };

Copy link
Contributor Author

@trentm trentm Mar 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@david-luna Thanks! I'll have to update most of the res detectors in this PR for this.

Some notes:

  • I think there is effectively a regression in @opentelemetry/[email protected] here. It doesn't adequately guard against a rejection in async resource attribute values anymore. I'll raise an issue (and perhaps PR) for this.
  • In the meantime, for a Resource Detector to use @opentelemetry/[email protected], the burden is now on the Resource Detector author to never have its async attribute promises reject.
  • I'm really curious why tests didn't catch this: some or all of tests for @opentelemetry/resources, @opentelemetry/resource-detector-*, and @opentelemetry/auto-instrumentations-node should catch this. My total guess is that there are no out-of-process tests for these, and that mocha has some uncaughtException or unhandledRejection process event handler that accidentally traps these.
  • I think the section in the migration guide (https://github.com/open-telemetry/opentelemetry-js/blob/main/doc/upgrade-to-2.x.md#-opentelemetryresources-changes-for-implementors-of-resource-detectors) should be updated to cope with this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • I'm really curious why tests didn't catch this: some or all of tests for @opentelemetry/resources, @opentelemetry/resource-detector-*, and @opentelemetry/auto-instrumentations-node should catch this.
  • @opentelemetry/resource-detector-*: At least for @opentelemetry/resource-detector-alibaba-cloud all the tests using detectResources would immediately (in the same tick) call resource?.waitForAsyncResources(), which results in the async try/catch in that method guarding against promise rejections in the async attrs.

I have a coming test case that adds this before the resource?.waitForAsyncResources():

import { setTimeout as setTimeoutP } from 'timers/promises';

// This pause simulates the delay between `detectResources` and
// `waitForAsyncAttributes` typically called later in an exporter.
await setTimeoutP(200); // Hope this is enough time to get error response.

This triggers the error.

  • @opentelemetry/auto-instrumentations-node: Its register.test.ts does do an out of process test. However, it sets OTEL_NODE_RESOURCE_DETECTORS: 'none', hence no testing of async resource detection. With the following diff, the test fails:
--- a/metapackages/auto-instrumentations-node/test/register.test.ts
+++ b/metapackages/auto-instrumentations-node/test/register.test.ts
@@ -33,7 +33,6 @@ function runWithRegister(path: string): PromiseWithChild<{
       timeout: 1500,
       killSignal: 'SIGKILL', // SIGTERM is not sufficient to terminate some hangs
       env: Object.assign({}, process.env, {
-        OTEL_NODE_RESOURCE_DETECTORS: 'none',
         OTEL_TRACES_EXPORTER: 'console',
         OTEL_LOG_LEVEL: 'debug',

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • I think there is effectively a regression in @opentelemetry/[email protected] here. It doesn't adequately guard against a rejection in async resource attribute values anymore. I'll raise an issue (and perhaps PR) for this.

I've opened open-telemetry/opentelemetry-js#5539 for this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be fixed in commit e3a689f


return {
[SEMRESATTRS_CLOUD_PROVIDER]: CLOUDPROVIDERVALUES_ALIBABA_CLOUD,
[SEMRESATTRS_CLOUD_PLATFORM]: CLOUDPLATFORMVALUES_ALIBABA_CLOUD_ECS,
[SEMRESATTRS_CLOUD_ACCOUNT_ID]: accountId,
[SEMRESATTRS_CLOUD_REGION]: region,
[SEMRESATTRS_CLOUD_AVAILABILITY_ZONE]: availabilityZone,
[SEMRESATTRS_HOST_ID]: instanceId,
[SEMRESATTRS_HOST_TYPE]: instanceType,
[SEMRESATTRS_HOST_NAME]: hostname,
[SEMRESATTRS_CLOUD_PROVIDER]: dataP.then(
() => CLOUDPROVIDERVALUES_ALIBABA_CLOUD
),
[SEMRESATTRS_CLOUD_PLATFORM]: dataP.then(
() => CLOUDPLATFORMVALUES_ALIBABA_CLOUD_ECS
),

// Data from _fetchIdentity()
[SEMRESATTRS_CLOUD_ACCOUNT_ID]: dataP.then(
data => data[0]['owner-account-id']
),
[SEMRESATTRS_CLOUD_REGION]: dataP.then(data => data[0]['region-id']),
[SEMRESATTRS_CLOUD_AVAILABILITY_ZONE]: dataP.then(
data => data[0]['zone-id']
),
[SEMRESATTRS_HOST_ID]: dataP.then(data => data[0]['instance-id']),
[SEMRESATTRS_HOST_TYPE]: dataP.then(data => data[0]['instance-type']),

// Data from _fetchHost()
[SEMRESATTRS_HOST_NAME]: dataP.then(data => data[1]),
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

import * as nock from 'nock';
import * as assert from 'assert';
import { Resource } from '@opentelemetry/resources';
import { detectResources } from '@opentelemetry/resources';
import { CLOUDPROVIDERVALUES_ALIBABA_CLOUD } from '@opentelemetry/semantic-conventions';
import {
assertCloudResource,
Expand Down Expand Up @@ -63,7 +63,9 @@ describe('alibabaCloudEcsDetector', () => {
.get(ALIYUN_HOST_PATH)
.reply(200, () => mockedHostResponse);

const resource: Resource = await alibabaCloudEcsDetector.detect();
const resource = detectResources({
detectors: [alibabaCloudEcsDetector],
});
await resource.waitForAsyncAttributes?.();

scope.done();
Expand Down Expand Up @@ -93,7 +95,9 @@ describe('alibabaCloudEcsDetector', () => {
.get(ALIYUN_HOST_PATH)
.reply(404, () => new Error());

const resource = await alibabaCloudEcsDetector.detect();
const resource = detectResources({
detectors: [alibabaCloudEcsDetector],
});
await resource.waitForAsyncAttributes?.();

assert.deepStrictEqual(resource.attributes, {});
Expand All @@ -109,7 +113,9 @@ describe('alibabaCloudEcsDetector', () => {
.delayConnection(2000)
.reply(200, () => mockedHostResponse);

const resource = await alibabaCloudEcsDetector.detect();
const resource = detectResources({
detectors: [alibabaCloudEcsDetector],
});
await resource.waitForAsyncAttributes?.();

assert.deepStrictEqual(resource.attributes, {});
Expand All @@ -122,7 +128,9 @@ describe('alibabaCloudEcsDetector', () => {
.get(ALIYUN_IDENTITY_PATH)
.replyWithError('NOT FOUND');

const resource = await alibabaCloudEcsDetector.detect();
const resource = detectResources({
detectors: [alibabaCloudEcsDetector],
});
await resource.waitForAsyncAttributes?.();

assert.deepStrictEqual(resource.attributes, {});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
SimpleSpanProcessor,
} from '@opentelemetry/sdk-trace-base';
import { NodeSDK } from '@opentelemetry/sdk-node';
import { IResource } from '@opentelemetry/resources';
import { detectResources } from '@opentelemetry/resources';

describe('[Integration] AlibabaCloudEcsDetector', () => {
it('should not start spans for detector requests', async () => {
Expand All @@ -47,7 +47,7 @@ describe('[Integration] AlibabaCloudEcsDetector', () => {
const {
alibabaCloudEcsDetector,
} = require('../../build/src/detectors/AlibabaCloudEcsDetector');
const resource = alibabaCloudEcsDetector.detect() as IResource;
const resource = detectResources({ detectors: [alibabaCloudEcsDetector] });
await resource.waitForAsyncAttributes?.();

// Wait for the next loop to let the span close properly
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"author": "OpenTelemetry Authors",
"license": "Apache-2.0",
"engines": {
"node": ">=14"
"node": "^18.19.0 || >=20.6.0"
},
"files": [
"build/src/**/*.js",
Expand All @@ -44,22 +44,23 @@
"@opentelemetry/api": "^1.0.0",
"@opentelemetry/contrib-test-utils": "^0.45.1",
"@opentelemetry/instrumentation-fs": "^0.19.1",
"@opentelemetry/instrumentation-http": "^0.57.2",
"@opentelemetry/instrumentation-http": "^0.200.0-rc.1",
"@opentelemetry/sdk-trace-base": "^2.0.0-rc.1",
"@types/mocha": "10.0.10",
"@types/node": "18.18.14",
"@types/sinon": "17.0.4",
"nock": "13.3.3",
"nyc": "15.1.0",
"rimraf": "5.0.10",
"sinon": "15.2.0",
"typescript": "4.4.4"
"typescript": "5.0.4"
},
"peerDependencies": {
"@opentelemetry/api": "^1.0.0"
},
"dependencies": {
"@opentelemetry/core": "^1.0.0",
"@opentelemetry/resources": "^1.10.0",
"@opentelemetry/core": "^2.0.0-rc.1",
"@opentelemetry/resources": "^2.0.0-rc.1",
"@opentelemetry/semantic-conventions": "^1.27.0"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/detectors/node/opentelemetry-resource-detector-aws#readme",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,28 @@
* limitations under the License.
*/

import { context } from '@opentelemetry/api';
import { suppressTracing } from '@opentelemetry/core';

import {
Detector,
IResource,
ResourceDetectionConfig,
ResourceDetector,
DetectedResource,
DetectedResourceAttributes,
} from '@opentelemetry/resources';

import { awsBeanstalkDetectorSync } from './AwsBeanstalkDetectorSync';
import {
ATTR_SERVICE_NAME,
ATTR_SERVICE_VERSION,
} from '@opentelemetry/semantic-conventions';
import {
ATTR_CLOUD_PROVIDER,
ATTR_CLOUD_PLATFORM,
ATTR_SERVICE_NAMESPACE,
ATTR_SERVICE_INSTANCE_ID,
CLOUD_PROVIDER_VALUE_AWS,
CLOUD_PLATFORM_VALUE_AWS_ELASTIC_BEANSTALK,
} from '../semconv';
import * as fs from 'fs';
import * as util from 'util';

/**
* The AwsBeanstalkDetector can be used to detect if a process is running in AWS Elastic
Expand All @@ -29,13 +44,66 @@
*
* See https://docs.amazonaws.cn/en_us/xray/latest/devguide/xray-guide.pdf
* for more details about detecting information of Elastic Beanstalk plugins
*
* @deprecated Use {@link AwsBeanstalkDetectorSync} class instead.
*/

export class AwsBeanstalkDetector implements Detector {
detect(config?: ResourceDetectionConfig): Promise<IResource> {
return Promise.resolve(awsBeanstalkDetectorSync.detect(config));
const DEFAULT_BEANSTALK_CONF_PATH =
'/var/elasticbeanstalk/xray/environment.conf';
const WIN_OS_BEANSTALK_CONF_PATH =
'C:\\Program Files\\Amazon\\XRay\\environment.conf';

export class AwsBeanstalkDetector implements ResourceDetector {
BEANSTALK_CONF_PATH: string;
private static readFileAsync = util.promisify(fs.readFile);
private static fileAccessAsync = util.promisify(fs.access);

constructor() {
if (process.platform === 'win32') {
this.BEANSTALK_CONF_PATH = WIN_OS_BEANSTALK_CONF_PATH;

Check warning on line 61 in detectors/node/opentelemetry-resource-detector-aws/src/detectors/AwsBeanstalkDetector.ts

View check run for this annotation

Codecov / codecov/patch

detectors/node/opentelemetry-resource-detector-aws/src/detectors/AwsBeanstalkDetector.ts#L61

Added line #L61 was not covered by tests
} else {
this.BEANSTALK_CONF_PATH = DEFAULT_BEANSTALK_CONF_PATH;
}
}

detect(): DetectedResource {
const attributes = context.with(suppressTracing(context.active()), () =>
this._getAttributes()
);
return { attributes };
}

/**
* Async resource attributes for AWS Beanstalk configuration read from file.
*/
_getAttributes(): DetectedResourceAttributes {
const parsedDataP = AwsBeanstalkDetector.fileAccessAsync(
this.BEANSTALK_CONF_PATH,
fs.constants.R_OK
)
.then(() =>
AwsBeanstalkDetector.readFileAsync(this.BEANSTALK_CONF_PATH, 'utf8')
)
.then(rawData => {
return JSON.parse(rawData);
});

return {
[ATTR_CLOUD_PROVIDER]: parsedDataP.then(() => CLOUD_PROVIDER_VALUE_AWS),
[ATTR_CLOUD_PLATFORM]: parsedDataP.then(
() => CLOUD_PLATFORM_VALUE_AWS_ELASTIC_BEANSTALK
),
[ATTR_SERVICE_NAME]: parsedDataP.then(
() => CLOUD_PLATFORM_VALUE_AWS_ELASTIC_BEANSTALK
),
[ATTR_SERVICE_NAMESPACE]: parsedDataP.then(
parsedData => parsedData.environment_name
),
[ATTR_SERVICE_VERSION]: parsedDataP.then(
parsedData => parsedData.version_label
),
[ATTR_SERVICE_INSTANCE_ID]: parsedDataP.then(
parsedData => parsedData.deployment_id
),
};
}
}

Expand Down
Loading
Loading