From 3389dccf697301866d82ae8e6229e6302e7f169d Mon Sep 17 00:00:00 2001 From: David Luna Date: Fri, 12 Jul 2024 09:37:53 +0200 Subject: [PATCH 01/10] refactor(detector-alibaba): change implementation to DetectorSync interface --- .../src/detectors/AlibabaCloudEcsDetector.ts | 57 +++++++----- .../detectors/AlibabaCloudEcsDetector.test.ts | 44 ++++------ .../use-alibaba-cloud-ecs-detector.js | 86 +++++++++++++++++++ 3 files changed, 140 insertions(+), 47 deletions(-) create mode 100644 detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/fixtures/use-alibaba-cloud-ecs-detector.js diff --git a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetector.ts b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetector.ts index 776e5dbccd..1fae739467 100644 --- a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetector.ts +++ b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetector.ts @@ -15,8 +15,9 @@ */ import { - Detector, + DetectorSync, Resource, + ResourceAttributes, ResourceDetectionConfig, } from '@opentelemetry/resources'; import { @@ -38,7 +39,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 Detector { +class AlibabaCloudEcsDetector implements DetectorSync { /** * See https://www.alibabacloud.com/help/doc-detail/67254.htm for * documentation about the AlibabaCloud instance identity document. @@ -57,26 +58,40 @@ class AlibabaCloudEcsDetector implements Detector { * * @param config (unused) The resource detection config */ - async detect(_config?: ResourceDetectionConfig): Promise { - 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(); + detect(_config?: ResourceDetectionConfig): Resource { + return new Resource({}, this._getAttributes()); + } - return new Resource({ - [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, - }); + /** Gets identity and host info and returns them as attribs. Empty object if fails */ + async _getAttributes( + _config?: ResourceDetectionConfig + ): Promise { + let attribs: ResourceAttributes; + try { + 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(); + + attribs = { + [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, + }; + } catch { + attribs = {}; + } + + return attribs; } /** diff --git a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/AlibabaCloudEcsDetector.test.ts b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/AlibabaCloudEcsDetector.test.ts index c4a2c41d36..b09d0f8ae2 100644 --- a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/AlibabaCloudEcsDetector.test.ts +++ b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/AlibabaCloudEcsDetector.test.ts @@ -64,6 +64,7 @@ describe('alibabaCloudEcsDetector', () => { .reply(200, () => mockedHostResponse); const resource: Resource = await alibabaCloudEcsDetector.detect(); + await resource.waitForAsyncAttributes?.(); scope.done(); @@ -84,8 +85,7 @@ describe('alibabaCloudEcsDetector', () => { }); describe('with unsuccessful request', () => { - it('should throw when receiving error response code', async () => { - const expectedError = new Error('Failed to load page, status code: 404'); + it('should return empty resource when receiving error response code', async () => { const scope = nock(ALIYUN_HOST) .persist() .get(ALIYUN_IDENTITY_PATH) @@ -93,18 +93,15 @@ describe('alibabaCloudEcsDetector', () => { .get(ALIYUN_HOST_PATH) .reply(404, () => new Error()); - try { - await alibabaCloudEcsDetector.detect(); - assert.ok(false, 'Expected to throw'); - } catch (err) { - assert.deepStrictEqual(err, expectedError); - } + const resource = await alibabaCloudEcsDetector.detect(); + await resource.waitForAsyncAttributes?.(); + + assert.deepStrictEqual(resource.attributes, {}); scope.done(); }); - it('should throw when timed out', async () => { - const expectedError = new Error('ECS metadata api request timed out.'); + it('should return empty resource when timed out', async () => { const scope = nock(ALIYUN_HOST) .get(ALIYUN_IDENTITY_PATH) .reply(200, () => mockedIdentityResponse) @@ -112,28 +109,23 @@ describe('alibabaCloudEcsDetector', () => { .delayConnection(2000) .reply(200, () => mockedHostResponse); - try { - await alibabaCloudEcsDetector.detect(); - assert.ok(false, 'Expected to throw'); - } catch (err) { - assert.deepStrictEqual(err, expectedError); - } + const resource = await alibabaCloudEcsDetector.detect(); + await resource.waitForAsyncAttributes?.(); + + assert.deepStrictEqual(resource.attributes, {}); scope.done(); }); - it('should throw when replied with an Error', async () => { - const expectedError = new Error('NOT FOUND'); + it('should return empty resource when replied with an Error', async () => { const scope = nock(ALIYUN_HOST) .get(ALIYUN_IDENTITY_PATH) - .replyWithError(expectedError.message); - - try { - await alibabaCloudEcsDetector.detect(); - assert.ok(false, 'Expected to throw'); - } catch (err) { - assert.deepStrictEqual(err, expectedError); - } + .replyWithError('NOT FOUND'); + + const resource = await alibabaCloudEcsDetector.detect(); + await resource.waitForAsyncAttributes?.(); + + assert.deepStrictEqual(resource.attributes, {}); scope.done(); }); diff --git a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/fixtures/use-alibaba-cloud-ecs-detector.js b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/fixtures/use-alibaba-cloud-ecs-detector.js new file mode 100644 index 0000000000..3074ef6003 --- /dev/null +++ b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/fixtures/use-alibaba-cloud-ecs-detector.js @@ -0,0 +1,86 @@ +/* + * 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. + */ + +// Usage: +// node use-gcp-detector.js + +const { createTestNodeSdk } = require('@opentelemetry/contrib-test-utils'); +const { HttpInstrumentation } = require('@opentelemetry/instrumentation-http'); +const { alibabaCloudEcsDetector } = require('../../build/src/index.js'); + + +const sdk = createTestNodeSdk({ + serviceName: 'use-detector-alibaba-cloud-ecs', + instrumentations: [ + new HttpInstrumentation(), + ], + resourceDetectors: [alibabaCloudEcsDetector], +}); + +sdk.start(); + +const http = require('http'); + +const server = http.createServer((req, res) => { + console.log('incoming request: %s %s %s', req.method, req.url, req.headers); + + req.resume(); + req.on('end', function () { + const body = 'pong'; + res.writeHead(200, { + 'content-type': 'text/plain', + 'content-length': body.length, + }); + res.end(body); + }); +}); + +server.listen(0, '127.0.0.1', async function () { + const port = server.address().port; + + // First request to show a client error. + const startTime = Date.now(); + await new Promise((resolve) => { + const clientReq = http.request( + `http://127.0.0.1:${port}/ping`, + function (cres) { + console.log( + 'client response: %s %s', + cres.statusCode, + cres.headers + ); + const chunks = []; + cres.on('data', function (chunk) { + chunks.push(chunk); + }); + cres.on('end', function () { + const body = chunks.join(''); + console.log('client response body: %j', body); + resolve(); + }); + } + ); + clientReq.write('ping'); + clientReq.end(); + }); + + // flush any left spans + // NOTE: this adds extra requests but its necessary to make sure + // spans have the resouce and are queued in the exporter + await alibabaCloudEcsDetector.detect().waitForAsyncAttributes(); + await sdk.shutdown(); + await new Promise(resolve => server.close(resolve)); +}); From 0fd9ba330c8ed2b45c31ea52fca34e02d7ee5069 Mon Sep 17 00:00:00 2001 From: David Luna Date: Fri, 12 Jul 2024 14:07:55 +0200 Subject: [PATCH 02/10] refactor(detector-alibaba): fix return type --- .../src/detectors/AlibabaCloudEcsDetector.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetector.ts b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetector.ts index 1fae739467..3daf784331 100644 --- a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetector.ts +++ b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetector.ts @@ -16,6 +16,7 @@ import { DetectorSync, + IResource, Resource, ResourceAttributes, ResourceDetectionConfig, @@ -58,7 +59,7 @@ class AlibabaCloudEcsDetector implements DetectorSync { * * @param config (unused) The resource detection config */ - detect(_config?: ResourceDetectionConfig): Resource { + detect(_config?: ResourceDetectionConfig): IResource { return new Resource({}, this._getAttributes()); } From 3ded77a693dbbd1ff6c4ac0a5b0f07d42e014d0d Mon Sep 17 00:00:00 2001 From: David Luna Date: Mon, 15 Jul 2024 09:49:41 +0200 Subject: [PATCH 03/10] Update detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/fixtures/use-alibaba-cloud-ecs-detector.js Co-authored-by: Chengzhong Wu --- .../test/fixtures/use-alibaba-cloud-ecs-detector.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/fixtures/use-alibaba-cloud-ecs-detector.js b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/fixtures/use-alibaba-cloud-ecs-detector.js index 3074ef6003..2ec2d8c685 100644 --- a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/fixtures/use-alibaba-cloud-ecs-detector.js +++ b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/fixtures/use-alibaba-cloud-ecs-detector.js @@ -15,7 +15,7 @@ */ // Usage: -// node use-gcp-detector.js +// node use-alibaba-cloud-ecs-detector.js const { createTestNodeSdk } = require('@opentelemetry/contrib-test-utils'); const { HttpInstrumentation } = require('@opentelemetry/instrumentation-http'); From 2b50ea1e4485491c77f2053dcf13a55c0dd0c800 Mon Sep 17 00:00:00 2001 From: David Luna Date: Mon, 15 Jul 2024 10:16:54 +0200 Subject: [PATCH 04/10] chore(detector-alibaba): remove unused fixture file --- .../use-alibaba-cloud-ecs-detector.js | 86 ------------------- 1 file changed, 86 deletions(-) delete mode 100644 detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/fixtures/use-alibaba-cloud-ecs-detector.js diff --git a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/fixtures/use-alibaba-cloud-ecs-detector.js b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/fixtures/use-alibaba-cloud-ecs-detector.js deleted file mode 100644 index 3074ef6003..0000000000 --- a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/fixtures/use-alibaba-cloud-ecs-detector.js +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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. - */ - -// Usage: -// node use-gcp-detector.js - -const { createTestNodeSdk } = require('@opentelemetry/contrib-test-utils'); -const { HttpInstrumentation } = require('@opentelemetry/instrumentation-http'); -const { alibabaCloudEcsDetector } = require('../../build/src/index.js'); - - -const sdk = createTestNodeSdk({ - serviceName: 'use-detector-alibaba-cloud-ecs', - instrumentations: [ - new HttpInstrumentation(), - ], - resourceDetectors: [alibabaCloudEcsDetector], -}); - -sdk.start(); - -const http = require('http'); - -const server = http.createServer((req, res) => { - console.log('incoming request: %s %s %s', req.method, req.url, req.headers); - - req.resume(); - req.on('end', function () { - const body = 'pong'; - res.writeHead(200, { - 'content-type': 'text/plain', - 'content-length': body.length, - }); - res.end(body); - }); -}); - -server.listen(0, '127.0.0.1', async function () { - const port = server.address().port; - - // First request to show a client error. - const startTime = Date.now(); - await new Promise((resolve) => { - const clientReq = http.request( - `http://127.0.0.1:${port}/ping`, - function (cres) { - console.log( - 'client response: %s %s', - cres.statusCode, - cres.headers - ); - const chunks = []; - cres.on('data', function (chunk) { - chunks.push(chunk); - }); - cres.on('end', function () { - const body = chunks.join(''); - console.log('client response body: %j', body); - resolve(); - }); - } - ); - clientReq.write('ping'); - clientReq.end(); - }); - - // flush any left spans - // NOTE: this adds extra requests but its necessary to make sure - // spans have the resouce and are queued in the exporter - await alibabaCloudEcsDetector.detect().waitForAsyncAttributes(); - await sdk.shutdown(); - await new Promise(resolve => server.close(resolve)); -}); From 873b9a5eed9cf4eef638ae1c4482abfbfda0f2d8 Mon Sep 17 00:00:00 2001 From: David Luna Date: Mon, 15 Jul 2024 10:25:00 +0200 Subject: [PATCH 05/10] chore(detector-alibaba): update dependencies --- .../node/opentelemetry-resource-detector-instana/package.json | 2 +- package-lock.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/detectors/node/opentelemetry-resource-detector-instana/package.json b/detectors/node/opentelemetry-resource-detector-instana/package.json index 93d915730e..5ed0ce5dd5 100644 --- a/detectors/node/opentelemetry-resource-detector-instana/package.json +++ b/detectors/node/opentelemetry-resource-detector-instana/package.json @@ -51,7 +51,7 @@ "typescript": "4.4.4" }, "dependencies": { - "@opentelemetry/resources": "^1.0.0", + "@opentelemetry/resources": "^1.10.0", "@opentelemetry/semantic-conventions": "^1.22.0" }, "peerDependencies": { diff --git a/package-lock.json b/package-lock.json index 5c23d15b67..9676448d7a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -251,7 +251,7 @@ "version": "0.10.0", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/resources": "^1.0.0", + "@opentelemetry/resources": "^1.10.0", "@opentelemetry/semantic-conventions": "^1.22.0" }, "devDependencies": { @@ -55542,7 +55542,7 @@ "requires": { "@opentelemetry/api": "^1.3.0", "@opentelemetry/contrib-test-utils": "^0.40.0", - "@opentelemetry/resources": "^1.0.0", + "@opentelemetry/resources": "^1.10.0", "@opentelemetry/sdk-node": "^0.52.0", "@opentelemetry/semantic-conventions": "^1.22.0", "@types/mocha": "8.2.3", From 42862a8dead3f99b4c292eba085a59128b7db7b2 Mon Sep 17 00:00:00 2001 From: David Luna Date: Mon, 29 Jul 2024 20:08:25 +0200 Subject: [PATCH 06/10] refactor(detector-alibaba): avoid breaking change in API --- .../src/detectors/AlibabaCloudEcsDetector.ts | 128 +------------- .../detectors/AlibabaCloudEcsDetectorSync.ts | 156 ++++++++++++++++++ .../src/detectors/index.ts | 3 +- ...r.test.ts => AlibabaCloudDetector.test.ts} | 0 .../AlibabaCloudEcsDetectorSync.test.ts | 133 +++++++++++++++ 5 files changed, 299 insertions(+), 121 deletions(-) create mode 100644 detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetectorSync.ts rename detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/{AlibabaCloudEcsDetector.test.ts => AlibabaCloudDetector.test.ts} (100%) create mode 100644 detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/AlibabaCloudEcsDetectorSync.test.ts diff --git a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetector.ts b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetector.ts index 3daf784331..acf4d19941 100644 --- a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetector.ts +++ b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetector.ts @@ -15,35 +15,23 @@ */ import { - DetectorSync, + Detector, IResource, - Resource, - ResourceAttributes, ResourceDetectionConfig, } from '@opentelemetry/resources'; -import { - CLOUDPLATFORMVALUES_ALIBABA_CLOUD_ECS, - CLOUDPROVIDERVALUES_ALIBABA_CLOUD, - SEMRESATTRS_CLOUD_ACCOUNT_ID, - SEMRESATTRS_CLOUD_AVAILABILITY_ZONE, - SEMRESATTRS_CLOUD_PLATFORM, - SEMRESATTRS_CLOUD_PROVIDER, - SEMRESATTRS_CLOUD_REGION, - SEMRESATTRS_HOST_ID, - SEMRESATTRS_HOST_NAME, - SEMRESATTRS_HOST_TYPE, -} from '@opentelemetry/semantic-conventions'; -import * as http from 'http'; +import { alibabaCloudEcsDetectorSync } from './AlibabaCloudEcsDetectorSync'; /** * The AlibabaCloudEcsDetector can be used to detect if a process is running in * 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 Detector { /** * See https://www.alibabacloud.com/help/doc-detail/67254.htm for * documentation about the AlibabaCloud instance identity document. + * + * NOTE: kept for testing purposes */ readonly ALIBABA_CLOUD_IDMS_ENDPOINT = '100.100.100.200'; readonly ALIBABA_CLOUD_INSTANCE_IDENTITY_DOCUMENT_PATH = @@ -53,110 +41,10 @@ class AlibabaCloudEcsDetector implements DetectorSync { readonly MILLISECONDS_TIME_OUT = 1000; /** - * Attempts to connect and obtain an AlibabaCloud instance Identity document. - * If the connection is successful it returns a promise containing a - * {@link Resource} populated with instance metadata. - * - * @param config (unused) The resource detection config + * Detects an AlibabaCloud instance Identity document. */ - detect(_config?: ResourceDetectionConfig): IResource { - return new Resource({}, this._getAttributes()); - } - - /** Gets identity and host info and returns them as attribs. Empty object if fails */ - async _getAttributes( - _config?: ResourceDetectionConfig - ): Promise { - let attribs: ResourceAttributes; - try { - 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(); - - attribs = { - [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, - }; - } catch { - attribs = {}; - } - - return attribs; - } - - /** - * Fetch AlibabaCloud instance document url with http requests. If the - * application is running on an ECS instance, we should be able to get back a - * valid JSON document. Parses that document and stores the identity - * properties in a local map. - */ - private async _fetchIdentity(): Promise { - const options = { - host: this.ALIBABA_CLOUD_IDMS_ENDPOINT, - path: this.ALIBABA_CLOUD_INSTANCE_IDENTITY_DOCUMENT_PATH, - method: 'GET', - timeout: this.MILLISECONDS_TIME_OUT, - }; - const identity = await this._fetchString(options); - return JSON.parse(identity); - } - - private async _fetchHost(): Promise { - const options = { - host: this.ALIBABA_CLOUD_IDMS_ENDPOINT, - path: this.ALIBABA_CLOUD_INSTANCE_HOST_DOCUMENT_PATH, - method: 'GET', - timeout: this.MILLISECONDS_TIME_OUT, - }; - return await this._fetchString(options); - } - - private async _fetchString(options: http.RequestOptions): Promise { - return new Promise((resolve, reject) => { - const timeoutId = setTimeout(() => { - req.destroy(new Error('ECS metadata api request timed out.')); - }, this.MILLISECONDS_TIME_OUT); - - const req = http.request(options, res => { - clearTimeout(timeoutId); - const { statusCode } = res; - if ( - typeof statusCode !== 'number' || - !(statusCode >= 200 && statusCode < 300) - ) { - res.destroy(); - return reject( - new Error(`Failed to load page, status code: ${statusCode}`) - ); - } - - res.setEncoding('utf8'); - let rawData = ''; - res.on('data', chunk => (rawData += chunk)); - res.on('error', err => { - reject(err); - }); - res.on('end', () => { - resolve(rawData); - }); - }); - req.on('error', err => { - clearTimeout(timeoutId); - reject(err); - }); - req.end(); - }); + detect(_config?: ResourceDetectionConfig): Promise { + return Promise.resolve(alibabaCloudEcsDetectorSync.detect(_config)); } } diff --git a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetectorSync.ts b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetectorSync.ts new file mode 100644 index 0000000000..ef44bfa7de --- /dev/null +++ b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetectorSync.ts @@ -0,0 +1,156 @@ +/* + * 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 { + DetectorSync, + IResource, + Resource, + ResourceAttributes, + ResourceDetectionConfig, +} from '@opentelemetry/resources'; +import { + CLOUDPLATFORMVALUES_ALIBABA_CLOUD_ECS, + CLOUDPROVIDERVALUES_ALIBABA_CLOUD, + SEMRESATTRS_CLOUD_ACCOUNT_ID, + SEMRESATTRS_CLOUD_AVAILABILITY_ZONE, + SEMRESATTRS_CLOUD_PLATFORM, + SEMRESATTRS_CLOUD_PROVIDER, + SEMRESATTRS_CLOUD_REGION, + SEMRESATTRS_HOST_ID, + SEMRESATTRS_HOST_NAME, + SEMRESATTRS_HOST_TYPE, +} from '@opentelemetry/semantic-conventions'; +import * as http from 'http'; + +/** + * The AlibabaCloudEcsDetector can be used to detect if a process is running in + * AlibabaCloud ECS and return a {@link Resource} populated with metadata about + * the ECS instance. Returns an empty Resource if detection fails. + */ +class AlibabaCloudEcsDetectorSync implements DetectorSync { + /** + * See https://www.alibabacloud.com/help/doc-detail/67254.htm for + * documentation about the AlibabaCloud instance identity document. + */ + readonly ALIBABA_CLOUD_IDMS_ENDPOINT = '100.100.100.200'; + readonly ALIBABA_CLOUD_INSTANCE_IDENTITY_DOCUMENT_PATH = + '/latest/dynamic/instance-identity/document'; + readonly ALIBABA_CLOUD_INSTANCE_HOST_DOCUMENT_PATH = + '/latest/meta-data/hostname'; + readonly MILLISECONDS_TIME_OUT = 1000; + + /** + * Attempts to connect and obtain an AlibabaCloud instance Identity document. + * If the connection is successful it returns a promise containing a + * {@link Resource} populated with instance metadata. + * + * @param config (unused) The resource detection config + */ + detect(_config?: ResourceDetectionConfig): IResource { + return new Resource({}, this._getAttributes()); + } + + /** Gets identity and host info and returns them as attribs. Empty object if fails */ + async _getAttributes( + _config?: ResourceDetectionConfig + ): Promise { + 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(); + + 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, + }; + } + + /** + * Fetch AlibabaCloud instance document url with http requests. If the + * application is running on an ECS instance, we should be able to get back a + * valid JSON document. Parses that document and stores the identity + * properties in a local map. + */ + private async _fetchIdentity(): Promise { + const options = { + host: this.ALIBABA_CLOUD_IDMS_ENDPOINT, + path: this.ALIBABA_CLOUD_INSTANCE_IDENTITY_DOCUMENT_PATH, + method: 'GET', + timeout: this.MILLISECONDS_TIME_OUT, + }; + const identity = await this._fetchString(options); + return JSON.parse(identity); + } + + private async _fetchHost(): Promise { + const options = { + host: this.ALIBABA_CLOUD_IDMS_ENDPOINT, + path: this.ALIBABA_CLOUD_INSTANCE_HOST_DOCUMENT_PATH, + method: 'GET', + timeout: this.MILLISECONDS_TIME_OUT, + }; + return await this._fetchString(options); + } + + private async _fetchString(options: http.RequestOptions): Promise { + return new Promise((resolve, reject) => { + const timeoutId = setTimeout(() => { + req.destroy(new Error('ECS metadata api request timed out.')); + }, this.MILLISECONDS_TIME_OUT); + + const req = http.request(options, res => { + clearTimeout(timeoutId); + const { statusCode } = res; + if ( + typeof statusCode !== 'number' || + !(statusCode >= 200 && statusCode < 300) + ) { + res.destroy(); + return reject( + new Error(`Failed to load page, status code: ${statusCode}`) + ); + } + + res.setEncoding('utf8'); + let rawData = ''; + res.on('data', chunk => (rawData += chunk)); + res.on('error', err => { + reject(err); + }); + res.on('end', () => { + resolve(rawData); + }); + }); + req.on('error', err => { + clearTimeout(timeoutId); + reject(err); + }); + req.end(); + }); + } +} + +export const alibabaCloudEcsDetectorSync = new AlibabaCloudEcsDetectorSync(); diff --git a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/index.ts b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/index.ts index 362ed6ecb7..38fdbca498 100644 --- a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/index.ts +++ b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/index.ts @@ -14,4 +14,5 @@ * limitations under the License. */ -export * from './AlibabaCloudEcsDetector'; +export { alibabaCloudEcsDetector } from './AlibabaCloudEcsDetector'; +export { alibabaCloudEcsDetectorSync } from './AlibabaCloudEcsDetectorSync'; diff --git a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/AlibabaCloudEcsDetector.test.ts b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/AlibabaCloudDetector.test.ts similarity index 100% rename from detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/AlibabaCloudEcsDetector.test.ts rename to detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/AlibabaCloudDetector.test.ts diff --git a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/AlibabaCloudEcsDetectorSync.test.ts b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/AlibabaCloudEcsDetectorSync.test.ts new file mode 100644 index 0000000000..4482cc5683 --- /dev/null +++ b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/AlibabaCloudEcsDetectorSync.test.ts @@ -0,0 +1,133 @@ +/* + * 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 * as nock from 'nock'; +import * as assert from 'assert'; +import { Resource } from '@opentelemetry/resources'; +import { CLOUDPROVIDERVALUES_ALIBABA_CLOUD } from '@opentelemetry/semantic-conventions'; +import { alibabaCloudEcsDetectorSync } from '../../src'; +import { + assertCloudResource, + assertHostResource, +} from '@opentelemetry/contrib-test-utils'; + +const ALIYUN_HOST = + 'http://' + alibabaCloudEcsDetectorSync.ALIBABA_CLOUD_IDMS_ENDPOINT; +const ALIYUN_IDENTITY_PATH = + alibabaCloudEcsDetectorSync.ALIBABA_CLOUD_INSTANCE_IDENTITY_DOCUMENT_PATH; +const ALIYUN_HOST_PATH = + alibabaCloudEcsDetectorSync.ALIBABA_CLOUD_INSTANCE_HOST_DOCUMENT_PATH; + +const mockedIdentityResponse = { + 'image-id': 'my-image-id', + 'instance-id': 'my-instance-id', + 'instance-type': 'my-instance-type', + mac: 'my-mac', + 'owner-account-id': 'my-owner-account-id', + 'private-ipv4': 'my-private-ipv4', + 'region-id': 'my-region-id', + 'serial-number': 'my-serial-number', + 'zone-id': 'my-zone-id', +}; +const mockedHostResponse = 'my-hostname'; + +describe('alibabaCloudEcsDetectorSync', () => { + beforeEach(() => { + nock.disableNetConnect(); + nock.cleanAll(); + }); + + afterEach(() => { + nock.enableNetConnect(); + }); + + describe('with successful request', () => { + it('should return alibaba cloud ecs instance resource', async () => { + const scope = nock(ALIYUN_HOST) + .persist() + .get(ALIYUN_IDENTITY_PATH) + .reply(200, () => mockedIdentityResponse) + .get(ALIYUN_HOST_PATH) + .reply(200, () => mockedHostResponse); + + const resource: Resource = await alibabaCloudEcsDetectorSync.detect(); + await resource.waitForAsyncAttributes?.(); + + scope.done(); + + assert.ok(resource); + + assertCloudResource(resource, { + provider: CLOUDPROVIDERVALUES_ALIBABA_CLOUD, + accountId: 'my-owner-account-id', + region: 'my-region-id', + zone: 'my-zone-id', + }); + assertHostResource(resource, { + id: 'my-instance-id', + hostType: 'my-instance-type', + name: 'my-hostname', + }); + }); + }); + + describe('with unsuccessful request', () => { + it('should return empty resource when receiving error response code', async () => { + const scope = nock(ALIYUN_HOST) + .persist() + .get(ALIYUN_IDENTITY_PATH) + .reply(200, () => mockedIdentityResponse) + .get(ALIYUN_HOST_PATH) + .reply(404, () => new Error()); + + const resource = await alibabaCloudEcsDetectorSync.detect(); + await resource.waitForAsyncAttributes?.(); + + assert.deepStrictEqual(resource.attributes, {}); + + scope.done(); + }); + + it('should return empty resource when timed out', async () => { + const scope = nock(ALIYUN_HOST) + .get(ALIYUN_IDENTITY_PATH) + .reply(200, () => mockedIdentityResponse) + .get(ALIYUN_HOST_PATH) + .delayConnection(2000) + .reply(200, () => mockedHostResponse); + + const resource = await alibabaCloudEcsDetectorSync.detect(); + await resource.waitForAsyncAttributes?.(); + + assert.deepStrictEqual(resource.attributes, {}); + + scope.done(); + }); + + it('should return empty resource when replied with an Error', async () => { + const scope = nock(ALIYUN_HOST) + .get(ALIYUN_IDENTITY_PATH) + .replyWithError('NOT FOUND'); + + const resource = await alibabaCloudEcsDetectorSync.detect(); + await resource.waitForAsyncAttributes?.(); + + assert.deepStrictEqual(resource.attributes, {}); + + scope.done(); + }); + }); +}); From baaa6eec30401cb1396c64fae4b506ff5e1ee554 Mon Sep 17 00:00:00 2001 From: David Luna Date: Tue, 30 Jul 2024 18:30:22 +0200 Subject: [PATCH 07/10] chore(detector-alibaba): fix lint issue --- .../src/detectors/AlibabaCloudEcsDetector.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetector.ts b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetector.ts index acf4d19941..40783cfe4b 100644 --- a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetector.ts +++ b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetector.ts @@ -30,7 +30,7 @@ class AlibabaCloudEcsDetector implements Detector { /** * See https://www.alibabacloud.com/help/doc-detail/67254.htm for * documentation about the AlibabaCloud instance identity document. - * + * * NOTE: kept for testing purposes */ readonly ALIBABA_CLOUD_IDMS_ENDPOINT = '100.100.100.200'; From 25bcb8d5af4edcb90d50c7cc2bdca1b5706dc815 Mon Sep 17 00:00:00 2001 From: David Luna Date: Wed, 31 Jul 2024 19:50:09 +0200 Subject: [PATCH 08/10] chore(detector-alibaba): move constants to a separate file --- .../src/detectors/AlibabaCloudEcsDetector.ts | 13 -------- .../detectors/AlibabaCloudEcsDetectorSync.ts | 33 +++++++++---------- .../src/detectors/constants.ts | 21 ++++++++++++ .../src/index.ts | 5 ++- .../detectors/AlibabaCloudDetector.test.ts | 16 +++++---- .../AlibabaCloudEcsDetectorSync.test.ts | 16 +++++---- 6 files changed, 58 insertions(+), 46 deletions(-) create mode 100644 detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/constants.ts diff --git a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetector.ts b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetector.ts index 40783cfe4b..8db692e81d 100644 --- a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetector.ts +++ b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetector.ts @@ -27,19 +27,6 @@ import { alibabaCloudEcsDetectorSync } from './AlibabaCloudEcsDetectorSync'; * the ECS instance. Returns an empty Resource if detection fails. */ class AlibabaCloudEcsDetector implements Detector { - /** - * See https://www.alibabacloud.com/help/doc-detail/67254.htm for - * documentation about the AlibabaCloud instance identity document. - * - * NOTE: kept for testing purposes - */ - readonly ALIBABA_CLOUD_IDMS_ENDPOINT = '100.100.100.200'; - readonly ALIBABA_CLOUD_INSTANCE_IDENTITY_DOCUMENT_PATH = - '/latest/dynamic/instance-identity/document'; - readonly ALIBABA_CLOUD_INSTANCE_HOST_DOCUMENT_PATH = - '/latest/meta-data/hostname'; - readonly MILLISECONDS_TIME_OUT = 1000; - /** * Detects an AlibabaCloud instance Identity document. */ diff --git a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetectorSync.ts b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetectorSync.ts index ef44bfa7de..77a57f57ce 100644 --- a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetectorSync.ts +++ b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetectorSync.ts @@ -33,6 +33,14 @@ import { SEMRESATTRS_HOST_NAME, SEMRESATTRS_HOST_TYPE, } from '@opentelemetry/semantic-conventions'; + +import { + ALIBABA_CLOUD_IDMS_ENDPOINT, + ALIBABA_CLOUD_INSTANCE_HOST_DOCUMENT_PATH, + ALIBABA_CLOUD_INSTANCE_IDENTITY_DOCUMENT_PATH, + MILLISECONDS_TIME_OUT, +} from './constants'; + import * as http from 'http'; /** @@ -41,17 +49,6 @@ import * as http from 'http'; * the ECS instance. Returns an empty Resource if detection fails. */ class AlibabaCloudEcsDetectorSync implements DetectorSync { - /** - * See https://www.alibabacloud.com/help/doc-detail/67254.htm for - * documentation about the AlibabaCloud instance identity document. - */ - readonly ALIBABA_CLOUD_IDMS_ENDPOINT = '100.100.100.200'; - readonly ALIBABA_CLOUD_INSTANCE_IDENTITY_DOCUMENT_PATH = - '/latest/dynamic/instance-identity/document'; - readonly ALIBABA_CLOUD_INSTANCE_HOST_DOCUMENT_PATH = - '/latest/meta-data/hostname'; - readonly MILLISECONDS_TIME_OUT = 1000; - /** * Attempts to connect and obtain an AlibabaCloud instance Identity document. * If the connection is successful it returns a promise containing a @@ -96,10 +93,10 @@ class AlibabaCloudEcsDetectorSync implements DetectorSync { */ private async _fetchIdentity(): Promise { const options = { - host: this.ALIBABA_CLOUD_IDMS_ENDPOINT, - path: this.ALIBABA_CLOUD_INSTANCE_IDENTITY_DOCUMENT_PATH, + host: ALIBABA_CLOUD_IDMS_ENDPOINT, + path: ALIBABA_CLOUD_INSTANCE_IDENTITY_DOCUMENT_PATH, method: 'GET', - timeout: this.MILLISECONDS_TIME_OUT, + timeout: MILLISECONDS_TIME_OUT, }; const identity = await this._fetchString(options); return JSON.parse(identity); @@ -107,10 +104,10 @@ class AlibabaCloudEcsDetectorSync implements DetectorSync { private async _fetchHost(): Promise { const options = { - host: this.ALIBABA_CLOUD_IDMS_ENDPOINT, - path: this.ALIBABA_CLOUD_INSTANCE_HOST_DOCUMENT_PATH, + host: ALIBABA_CLOUD_IDMS_ENDPOINT, + path: ALIBABA_CLOUD_INSTANCE_HOST_DOCUMENT_PATH, method: 'GET', - timeout: this.MILLISECONDS_TIME_OUT, + timeout: MILLISECONDS_TIME_OUT, }; return await this._fetchString(options); } @@ -119,7 +116,7 @@ class AlibabaCloudEcsDetectorSync implements DetectorSync { return new Promise((resolve, reject) => { const timeoutId = setTimeout(() => { req.destroy(new Error('ECS metadata api request timed out.')); - }, this.MILLISECONDS_TIME_OUT); + }, MILLISECONDS_TIME_OUT); const req = http.request(options, res => { clearTimeout(timeoutId); diff --git a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/constants.ts b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/constants.ts new file mode 100644 index 0000000000..f8c1d9be0f --- /dev/null +++ b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/constants.ts @@ -0,0 +1,21 @@ +/* + * 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. + */ +export const ALIBABA_CLOUD_IDMS_ENDPOINT = '100.100.100.200'; +export const ALIBABA_CLOUD_INSTANCE_IDENTITY_DOCUMENT_PATH = + '/latest/dynamic/instance-identity/document'; +export const ALIBABA_CLOUD_INSTANCE_HOST_DOCUMENT_PATH = + '/latest/meta-data/hostname'; +export const MILLISECONDS_TIME_OUT = 1000; diff --git a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/index.ts b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/index.ts index 0acba8788c..10d79139d0 100644 --- a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/index.ts +++ b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/index.ts @@ -14,4 +14,7 @@ * limitations under the License. */ -export * from './detectors'; +export { + alibabaCloudEcsDetector, + alibabaCloudEcsDetectorSync, +} from './detectors'; diff --git a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/AlibabaCloudDetector.test.ts b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/AlibabaCloudDetector.test.ts index b09d0f8ae2..1aa51d1ee6 100644 --- a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/AlibabaCloudDetector.test.ts +++ b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/AlibabaCloudDetector.test.ts @@ -18,18 +18,20 @@ import * as nock from 'nock'; import * as assert from 'assert'; import { Resource } from '@opentelemetry/resources'; import { CLOUDPROVIDERVALUES_ALIBABA_CLOUD } from '@opentelemetry/semantic-conventions'; -import { alibabaCloudEcsDetector } from '../../src'; import { assertCloudResource, assertHostResource, } from '@opentelemetry/contrib-test-utils'; +import { + ALIBABA_CLOUD_IDMS_ENDPOINT, + ALIBABA_CLOUD_INSTANCE_HOST_DOCUMENT_PATH, + ALIBABA_CLOUD_INSTANCE_IDENTITY_DOCUMENT_PATH, +} from '../../src/detectors/constants'; +import { alibabaCloudEcsDetector } from '../../src'; -const ALIYUN_HOST = - 'http://' + alibabaCloudEcsDetector.ALIBABA_CLOUD_IDMS_ENDPOINT; -const ALIYUN_IDENTITY_PATH = - alibabaCloudEcsDetector.ALIBABA_CLOUD_INSTANCE_IDENTITY_DOCUMENT_PATH; -const ALIYUN_HOST_PATH = - alibabaCloudEcsDetector.ALIBABA_CLOUD_INSTANCE_HOST_DOCUMENT_PATH; +const ALIYUN_HOST = 'http://' + ALIBABA_CLOUD_IDMS_ENDPOINT; +const ALIYUN_IDENTITY_PATH = ALIBABA_CLOUD_INSTANCE_IDENTITY_DOCUMENT_PATH; +const ALIYUN_HOST_PATH = ALIBABA_CLOUD_INSTANCE_HOST_DOCUMENT_PATH; const mockedIdentityResponse = { 'image-id': 'my-image-id', diff --git a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/AlibabaCloudEcsDetectorSync.test.ts b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/AlibabaCloudEcsDetectorSync.test.ts index 4482cc5683..0ce6efaba9 100644 --- a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/AlibabaCloudEcsDetectorSync.test.ts +++ b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/AlibabaCloudEcsDetectorSync.test.ts @@ -18,18 +18,20 @@ import * as nock from 'nock'; import * as assert from 'assert'; import { Resource } from '@opentelemetry/resources'; import { CLOUDPROVIDERVALUES_ALIBABA_CLOUD } from '@opentelemetry/semantic-conventions'; -import { alibabaCloudEcsDetectorSync } from '../../src'; import { assertCloudResource, assertHostResource, } from '@opentelemetry/contrib-test-utils'; +import { + ALIBABA_CLOUD_IDMS_ENDPOINT, + ALIBABA_CLOUD_INSTANCE_HOST_DOCUMENT_PATH, + ALIBABA_CLOUD_INSTANCE_IDENTITY_DOCUMENT_PATH, +} from '../../src/detectors/constants'; +import { alibabaCloudEcsDetectorSync } from '../../src'; -const ALIYUN_HOST = - 'http://' + alibabaCloudEcsDetectorSync.ALIBABA_CLOUD_IDMS_ENDPOINT; -const ALIYUN_IDENTITY_PATH = - alibabaCloudEcsDetectorSync.ALIBABA_CLOUD_INSTANCE_IDENTITY_DOCUMENT_PATH; -const ALIYUN_HOST_PATH = - alibabaCloudEcsDetectorSync.ALIBABA_CLOUD_INSTANCE_HOST_DOCUMENT_PATH; +const ALIYUN_HOST = 'http://' + ALIBABA_CLOUD_IDMS_ENDPOINT; +const ALIYUN_IDENTITY_PATH = ALIBABA_CLOUD_INSTANCE_IDENTITY_DOCUMENT_PATH; +const ALIYUN_HOST_PATH = ALIBABA_CLOUD_INSTANCE_HOST_DOCUMENT_PATH; const mockedIdentityResponse = { 'image-id': 'my-image-id', From fdd6524e2e7a1a6fc95f0ccf2ec487649c2b0202 Mon Sep 17 00:00:00 2001 From: David Luna Date: Thu, 1 Aug 2024 11:56:58 +0200 Subject: [PATCH 09/10] chore(detector-alibaba): remove async detector --- .../src/detectors/AlibabaCloudEcsDetector.ts | 131 ++++++++++++++- .../detectors/AlibabaCloudEcsDetectorSync.ts | 153 ------------------ .../src/detectors/constants.ts | 21 --- .../src/detectors/index.ts | 1 - .../src/index.ts | 5 +- ...est.ts => AlibabaCloudEcsDetector.test.ts} | 16 +- .../AlibabaCloudEcsDetectorSync.test.ts | 135 ---------------- 7 files changed, 133 insertions(+), 329 deletions(-) delete mode 100644 detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetectorSync.ts delete mode 100644 detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/constants.ts rename detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/{AlibabaCloudDetector.test.ts => AlibabaCloudEcsDetector.test.ts} (89%) delete mode 100644 detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/AlibabaCloudEcsDetectorSync.test.ts diff --git a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetector.ts b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetector.ts index 8db692e81d..bfcf29e3a2 100644 --- a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetector.ts +++ b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetector.ts @@ -15,23 +15,142 @@ */ import { - Detector, + DetectorSync, IResource, + Resource, + ResourceAttributes, ResourceDetectionConfig, } from '@opentelemetry/resources'; -import { alibabaCloudEcsDetectorSync } from './AlibabaCloudEcsDetectorSync'; +import { + CLOUDPLATFORMVALUES_ALIBABA_CLOUD_ECS, + CLOUDPROVIDERVALUES_ALIBABA_CLOUD, + SEMRESATTRS_CLOUD_ACCOUNT_ID, + SEMRESATTRS_CLOUD_AVAILABILITY_ZONE, + SEMRESATTRS_CLOUD_PLATFORM, + SEMRESATTRS_CLOUD_PROVIDER, + SEMRESATTRS_CLOUD_REGION, + SEMRESATTRS_HOST_ID, + SEMRESATTRS_HOST_NAME, + SEMRESATTRS_HOST_TYPE, +} from '@opentelemetry/semantic-conventions'; + +import * as http from 'http'; /** * The AlibabaCloudEcsDetector can be used to detect if a process is running in * AlibabaCloud ECS and return a {@link Resource} populated with metadata about * the ECS instance. Returns an empty Resource if detection fails. */ -class AlibabaCloudEcsDetector implements Detector { +class AlibabaCloudEcsDetector implements DetectorSync { + /** + * See https://www.alibabacloud.com/help/doc-detail/67254.htm for + * documentation about the AlibabaCloud instance identity document. + */ + readonly ALIBABA_CLOUD_IDMS_ENDPOINT = '100.100.100.200'; + readonly ALIBABA_CLOUD_INSTANCE_IDENTITY_DOCUMENT_PATH = + '/latest/dynamic/instance-identity/document'; + readonly ALIBABA_CLOUD_INSTANCE_HOST_DOCUMENT_PATH = + '/latest/meta-data/hostname'; + readonly MILLISECONDS_TIME_OUT = 1000; + + /** + * Attempts to connect and obtain an AlibabaCloud instance Identity document. + * If the connection is successful it returns a promise containing a + * {@link Resource} populated with instance metadata. + * + * @param config (unused) The resource detection config + */ + detect(_config?: ResourceDetectionConfig): IResource { + return new Resource({}, this._getAttributes()); + } + + /** Gets identity and host info and returns them as attribs. Empty object if fails */ + async _getAttributes( + _config?: ResourceDetectionConfig + ): Promise { + 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(); + + 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, + }; + } + /** - * Detects an AlibabaCloud instance Identity document. + * Fetch AlibabaCloud instance document url with http requests. If the + * application is running on an ECS instance, we should be able to get back a + * valid JSON document. Parses that document and stores the identity + * properties in a local map. */ - detect(_config?: ResourceDetectionConfig): Promise { - return Promise.resolve(alibabaCloudEcsDetectorSync.detect(_config)); + private async _fetchIdentity(): Promise { + const options = { + host: this.ALIBABA_CLOUD_IDMS_ENDPOINT, + path: this.ALIBABA_CLOUD_INSTANCE_IDENTITY_DOCUMENT_PATH, + method: 'GET', + timeout: this.MILLISECONDS_TIME_OUT, + }; + const identity = await this._fetchString(options); + return JSON.parse(identity); + } + + private async _fetchHost(): Promise { + const options = { + host: this.ALIBABA_CLOUD_IDMS_ENDPOINT, + path: this.ALIBABA_CLOUD_INSTANCE_HOST_DOCUMENT_PATH, + method: 'GET', + timeout: this.MILLISECONDS_TIME_OUT, + }; + return await this._fetchString(options); + } + + private async _fetchString(options: http.RequestOptions): Promise { + return new Promise((resolve, reject) => { + const timeoutId = setTimeout(() => { + req.destroy(new Error('ECS metadata api request timed out.')); + }, this.MILLISECONDS_TIME_OUT); + + const req = http.request(options, res => { + clearTimeout(timeoutId); + const { statusCode } = res; + if ( + typeof statusCode !== 'number' || + !(statusCode >= 200 && statusCode < 300) + ) { + res.destroy(); + return reject( + new Error(`Failed to load page, status code: ${statusCode}`) + ); + } + + res.setEncoding('utf8'); + let rawData = ''; + res.on('data', chunk => (rawData += chunk)); + res.on('error', err => { + reject(err); + }); + res.on('end', () => { + resolve(rawData); + }); + }); + req.on('error', err => { + clearTimeout(timeoutId); + reject(err); + }); + req.end(); + }); } } diff --git a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetectorSync.ts b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetectorSync.ts deleted file mode 100644 index 77a57f57ce..0000000000 --- a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/AlibabaCloudEcsDetectorSync.ts +++ /dev/null @@ -1,153 +0,0 @@ -/* - * 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 { - DetectorSync, - IResource, - Resource, - ResourceAttributes, - ResourceDetectionConfig, -} from '@opentelemetry/resources'; -import { - CLOUDPLATFORMVALUES_ALIBABA_CLOUD_ECS, - CLOUDPROVIDERVALUES_ALIBABA_CLOUD, - SEMRESATTRS_CLOUD_ACCOUNT_ID, - SEMRESATTRS_CLOUD_AVAILABILITY_ZONE, - SEMRESATTRS_CLOUD_PLATFORM, - SEMRESATTRS_CLOUD_PROVIDER, - SEMRESATTRS_CLOUD_REGION, - SEMRESATTRS_HOST_ID, - SEMRESATTRS_HOST_NAME, - SEMRESATTRS_HOST_TYPE, -} from '@opentelemetry/semantic-conventions'; - -import { - ALIBABA_CLOUD_IDMS_ENDPOINT, - ALIBABA_CLOUD_INSTANCE_HOST_DOCUMENT_PATH, - ALIBABA_CLOUD_INSTANCE_IDENTITY_DOCUMENT_PATH, - MILLISECONDS_TIME_OUT, -} from './constants'; - -import * as http from 'http'; - -/** - * The AlibabaCloudEcsDetector can be used to detect if a process is running in - * AlibabaCloud ECS and return a {@link Resource} populated with metadata about - * the ECS instance. Returns an empty Resource if detection fails. - */ -class AlibabaCloudEcsDetectorSync implements DetectorSync { - /** - * Attempts to connect and obtain an AlibabaCloud instance Identity document. - * If the connection is successful it returns a promise containing a - * {@link Resource} populated with instance metadata. - * - * @param config (unused) The resource detection config - */ - detect(_config?: ResourceDetectionConfig): IResource { - return new Resource({}, this._getAttributes()); - } - - /** Gets identity and host info and returns them as attribs. Empty object if fails */ - async _getAttributes( - _config?: ResourceDetectionConfig - ): Promise { - 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(); - - 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, - }; - } - - /** - * Fetch AlibabaCloud instance document url with http requests. If the - * application is running on an ECS instance, we should be able to get back a - * valid JSON document. Parses that document and stores the identity - * properties in a local map. - */ - private async _fetchIdentity(): Promise { - const options = { - host: ALIBABA_CLOUD_IDMS_ENDPOINT, - path: ALIBABA_CLOUD_INSTANCE_IDENTITY_DOCUMENT_PATH, - method: 'GET', - timeout: MILLISECONDS_TIME_OUT, - }; - const identity = await this._fetchString(options); - return JSON.parse(identity); - } - - private async _fetchHost(): Promise { - const options = { - host: ALIBABA_CLOUD_IDMS_ENDPOINT, - path: ALIBABA_CLOUD_INSTANCE_HOST_DOCUMENT_PATH, - method: 'GET', - timeout: MILLISECONDS_TIME_OUT, - }; - return await this._fetchString(options); - } - - private async _fetchString(options: http.RequestOptions): Promise { - return new Promise((resolve, reject) => { - const timeoutId = setTimeout(() => { - req.destroy(new Error('ECS metadata api request timed out.')); - }, MILLISECONDS_TIME_OUT); - - const req = http.request(options, res => { - clearTimeout(timeoutId); - const { statusCode } = res; - if ( - typeof statusCode !== 'number' || - !(statusCode >= 200 && statusCode < 300) - ) { - res.destroy(); - return reject( - new Error(`Failed to load page, status code: ${statusCode}`) - ); - } - - res.setEncoding('utf8'); - let rawData = ''; - res.on('data', chunk => (rawData += chunk)); - res.on('error', err => { - reject(err); - }); - res.on('end', () => { - resolve(rawData); - }); - }); - req.on('error', err => { - clearTimeout(timeoutId); - reject(err); - }); - req.end(); - }); - } -} - -export const alibabaCloudEcsDetectorSync = new AlibabaCloudEcsDetectorSync(); diff --git a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/constants.ts b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/constants.ts deleted file mode 100644 index f8c1d9be0f..0000000000 --- a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/constants.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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. - */ -export const ALIBABA_CLOUD_IDMS_ENDPOINT = '100.100.100.200'; -export const ALIBABA_CLOUD_INSTANCE_IDENTITY_DOCUMENT_PATH = - '/latest/dynamic/instance-identity/document'; -export const ALIBABA_CLOUD_INSTANCE_HOST_DOCUMENT_PATH = - '/latest/meta-data/hostname'; -export const MILLISECONDS_TIME_OUT = 1000; diff --git a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/index.ts b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/index.ts index 38fdbca498..1f43069640 100644 --- a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/index.ts +++ b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/detectors/index.ts @@ -15,4 +15,3 @@ */ export { alibabaCloudEcsDetector } from './AlibabaCloudEcsDetector'; -export { alibabaCloudEcsDetectorSync } from './AlibabaCloudEcsDetectorSync'; diff --git a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/index.ts b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/index.ts index 10d79139d0..b14741ba21 100644 --- a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/index.ts +++ b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/src/index.ts @@ -14,7 +14,4 @@ * limitations under the License. */ -export { - alibabaCloudEcsDetector, - alibabaCloudEcsDetectorSync, -} from './detectors'; +export { alibabaCloudEcsDetector } from './detectors'; diff --git a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/AlibabaCloudDetector.test.ts b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/AlibabaCloudEcsDetector.test.ts similarity index 89% rename from detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/AlibabaCloudDetector.test.ts rename to detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/AlibabaCloudEcsDetector.test.ts index 1aa51d1ee6..028d6cc463 100644 --- a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/AlibabaCloudDetector.test.ts +++ b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/AlibabaCloudEcsDetector.test.ts @@ -22,16 +22,14 @@ import { assertCloudResource, assertHostResource, } from '@opentelemetry/contrib-test-utils'; -import { - ALIBABA_CLOUD_IDMS_ENDPOINT, - ALIBABA_CLOUD_INSTANCE_HOST_DOCUMENT_PATH, - ALIBABA_CLOUD_INSTANCE_IDENTITY_DOCUMENT_PATH, -} from '../../src/detectors/constants'; import { alibabaCloudEcsDetector } from '../../src'; -const ALIYUN_HOST = 'http://' + ALIBABA_CLOUD_IDMS_ENDPOINT; -const ALIYUN_IDENTITY_PATH = ALIBABA_CLOUD_INSTANCE_IDENTITY_DOCUMENT_PATH; -const ALIYUN_HOST_PATH = ALIBABA_CLOUD_INSTANCE_HOST_DOCUMENT_PATH; +const ALIYUN_HOST = + 'http://' + alibabaCloudEcsDetector.ALIBABA_CLOUD_IDMS_ENDPOINT; +const ALIYUN_IDENTITY_PATH = + alibabaCloudEcsDetector.ALIBABA_CLOUD_INSTANCE_IDENTITY_DOCUMENT_PATH; +const ALIYUN_HOST_PATH = + alibabaCloudEcsDetector.ALIBABA_CLOUD_INSTANCE_HOST_DOCUMENT_PATH; const mockedIdentityResponse = { 'image-id': 'my-image-id', @@ -46,7 +44,7 @@ const mockedIdentityResponse = { }; const mockedHostResponse = 'my-hostname'; -describe('alibabaCloudEcsDetector', () => { +describe('alibabaCloudEcsDetectorSync', () => { beforeEach(() => { nock.disableNetConnect(); nock.cleanAll(); diff --git a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/AlibabaCloudEcsDetectorSync.test.ts b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/AlibabaCloudEcsDetectorSync.test.ts deleted file mode 100644 index 0ce6efaba9..0000000000 --- a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/AlibabaCloudEcsDetectorSync.test.ts +++ /dev/null @@ -1,135 +0,0 @@ -/* - * 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 * as nock from 'nock'; -import * as assert from 'assert'; -import { Resource } from '@opentelemetry/resources'; -import { CLOUDPROVIDERVALUES_ALIBABA_CLOUD } from '@opentelemetry/semantic-conventions'; -import { - assertCloudResource, - assertHostResource, -} from '@opentelemetry/contrib-test-utils'; -import { - ALIBABA_CLOUD_IDMS_ENDPOINT, - ALIBABA_CLOUD_INSTANCE_HOST_DOCUMENT_PATH, - ALIBABA_CLOUD_INSTANCE_IDENTITY_DOCUMENT_PATH, -} from '../../src/detectors/constants'; -import { alibabaCloudEcsDetectorSync } from '../../src'; - -const ALIYUN_HOST = 'http://' + ALIBABA_CLOUD_IDMS_ENDPOINT; -const ALIYUN_IDENTITY_PATH = ALIBABA_CLOUD_INSTANCE_IDENTITY_DOCUMENT_PATH; -const ALIYUN_HOST_PATH = ALIBABA_CLOUD_INSTANCE_HOST_DOCUMENT_PATH; - -const mockedIdentityResponse = { - 'image-id': 'my-image-id', - 'instance-id': 'my-instance-id', - 'instance-type': 'my-instance-type', - mac: 'my-mac', - 'owner-account-id': 'my-owner-account-id', - 'private-ipv4': 'my-private-ipv4', - 'region-id': 'my-region-id', - 'serial-number': 'my-serial-number', - 'zone-id': 'my-zone-id', -}; -const mockedHostResponse = 'my-hostname'; - -describe('alibabaCloudEcsDetectorSync', () => { - beforeEach(() => { - nock.disableNetConnect(); - nock.cleanAll(); - }); - - afterEach(() => { - nock.enableNetConnect(); - }); - - describe('with successful request', () => { - it('should return alibaba cloud ecs instance resource', async () => { - const scope = nock(ALIYUN_HOST) - .persist() - .get(ALIYUN_IDENTITY_PATH) - .reply(200, () => mockedIdentityResponse) - .get(ALIYUN_HOST_PATH) - .reply(200, () => mockedHostResponse); - - const resource: Resource = await alibabaCloudEcsDetectorSync.detect(); - await resource.waitForAsyncAttributes?.(); - - scope.done(); - - assert.ok(resource); - - assertCloudResource(resource, { - provider: CLOUDPROVIDERVALUES_ALIBABA_CLOUD, - accountId: 'my-owner-account-id', - region: 'my-region-id', - zone: 'my-zone-id', - }); - assertHostResource(resource, { - id: 'my-instance-id', - hostType: 'my-instance-type', - name: 'my-hostname', - }); - }); - }); - - describe('with unsuccessful request', () => { - it('should return empty resource when receiving error response code', async () => { - const scope = nock(ALIYUN_HOST) - .persist() - .get(ALIYUN_IDENTITY_PATH) - .reply(200, () => mockedIdentityResponse) - .get(ALIYUN_HOST_PATH) - .reply(404, () => new Error()); - - const resource = await alibabaCloudEcsDetectorSync.detect(); - await resource.waitForAsyncAttributes?.(); - - assert.deepStrictEqual(resource.attributes, {}); - - scope.done(); - }); - - it('should return empty resource when timed out', async () => { - const scope = nock(ALIYUN_HOST) - .get(ALIYUN_IDENTITY_PATH) - .reply(200, () => mockedIdentityResponse) - .get(ALIYUN_HOST_PATH) - .delayConnection(2000) - .reply(200, () => mockedHostResponse); - - const resource = await alibabaCloudEcsDetectorSync.detect(); - await resource.waitForAsyncAttributes?.(); - - assert.deepStrictEqual(resource.attributes, {}); - - scope.done(); - }); - - it('should return empty resource when replied with an Error', async () => { - const scope = nock(ALIYUN_HOST) - .get(ALIYUN_IDENTITY_PATH) - .replyWithError('NOT FOUND'); - - const resource = await alibabaCloudEcsDetectorSync.detect(); - await resource.waitForAsyncAttributes?.(); - - assert.deepStrictEqual(resource.attributes, {}); - - scope.done(); - }); - }); -}); From 57bf61a738e993505e89a1fd8b4469bdeb191c64 Mon Sep 17 00:00:00 2001 From: David Luna Date: Thu, 1 Aug 2024 11:59:35 +0200 Subject: [PATCH 10/10] chore(detector-alibaba): reset test name --- .../test/detectors/AlibabaCloudEcsDetector.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/AlibabaCloudEcsDetector.test.ts b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/AlibabaCloudEcsDetector.test.ts index 028d6cc463..15cd13dd99 100644 --- a/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/AlibabaCloudEcsDetector.test.ts +++ b/detectors/node/opentelemetry-resource-detector-alibaba-cloud/test/detectors/AlibabaCloudEcsDetector.test.ts @@ -44,7 +44,7 @@ const mockedIdentityResponse = { }; const mockedHostResponse = 'my-hostname'; -describe('alibabaCloudEcsDetectorSync', () => { +describe('alibabaCloudEcsDetector', () => { beforeEach(() => { nock.disableNetConnect(); nock.cleanAll();