diff --git a/docs/release-notes/index.md b/docs/release-notes/index.md index b2516404..cac0c03b 100644 --- a/docs/release-notes/index.md +++ b/docs/release-notes/index.md @@ -29,6 +29,15 @@ To check for security updates, go to [Security announcements for the Elastic sta % ### Fixes [edot-node-X.X.X-fixes] % * +## version.next [edot-node-X.X.X-release-notes] + +### Features and enhancements [edot-node-X.X.X-features-enhancements] +* + +### Fixes [edot-node-X.X.X-fixes] + +* Restore upstream Google Cloud Platorm resource detector. ([#1042](https://github.com/elastic/elastic-otel-node/pull/1042)) + ## 1.5.0 [edot-node-1.5.0-release-notes] ### Chores [edot-node-1.5.0-chores] diff --git a/packages/opentelemetry-node/lib/detector-gcp.js b/packages/opentelemetry-node/lib/detector-gcp.js deleted file mode 100644 index b256a1c1..00000000 --- a/packages/opentelemetry-node/lib/detector-gcp.js +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @typedef {import('@opentelemetry/resources').ResourceDetector} ResourceDetector - */ - -const {suppressTracing} = require('@opentelemetry/core'); -const {context} = require('@opentelemetry/api'); -const { - CLOUDPROVIDERVALUES_GCP, - SEMRESATTRS_CLOUD_ACCOUNT_ID, - SEMRESATTRS_CLOUD_AVAILABILITY_ZONE, - SEMRESATTRS_CLOUD_PROVIDER, - SEMRESATTRS_CONTAINER_NAME, - SEMRESATTRS_HOST_ID, - SEMRESATTRS_HOST_NAME, - SEMRESATTRS_K8S_CLUSTER_NAME, - SEMRESATTRS_K8S_NAMESPACE_NAME, - SEMRESATTRS_K8S_POD_NAME, -} = require('@opentelemetry/semantic-conventions'); -const jsonBigint = require('json-bigint'); - -// TODO: Switch back to `@opentelemetry/resource-detector-gcp` when -// https://github.com/open-telemetry/opentelemetry-js-contrib/issues/2320 is complete -/** @type {ResourceDetector} */ -const gcpDetector = { - detect() { - const metadataPromise = context.with( - suppressTracing(context.active()), - async () => { - const available = await isAvailable(); - if (!available) { - return undefined; - } - return { - projectId: metadataQuery('project/project-id'), - instanceId: metadataQuery('instance/id').then((id) => - id.toString() - ), - zoneId: metadataQuery('instance/zone'), - clusterName: metadataQuery( - 'instance/attributes/cluster-name' - ), - hostname: metadataQuery('instance/hostname'), - }; - } - ); - - const attributes = { - [SEMRESATTRS_CLOUD_PROVIDER]: metadataPromise.then( - (md) => md && CLOUDPROVIDERVALUES_GCP - ), - [SEMRESATTRS_CLOUD_ACCOUNT_ID]: metadataPromise.then( - (md) => md?.projectId - ), - [SEMRESATTRS_HOST_ID]: metadataPromise.then((md) => md?.instanceId), - [SEMRESATTRS_HOST_NAME]: metadataPromise.then((md) => md?.hostname), - [SEMRESATTRS_CLOUD_AVAILABILITY_ZONE]: metadataPromise.then( - (md) => md?.zoneId - ), - }; - - // Add resource attributes for K8s. - // ref: https://github.com/open-telemetry/opentelemetry-js-contrib/blob/main/detectors/node/opentelemetry-resource-detector-gcp/src/detectors/GcpDetector.ts#L69-L80 - if (process.env.KUBERNETES_SERVICE_HOST) { - attributes[SEMRESATTRS_K8S_CLUSTER_NAME] = metadataPromise.then( - (md) => md?.clusterName - ); - attributes[SEMRESATTRS_K8S_NAMESPACE_NAME] = metadataPromise.then( - (md) => md && process.env.NAMESPACE - ); - attributes[SEMRESATTRS_K8S_POD_NAME] = metadataPromise.then( - (md) => md && process.env.HOSTNAME - ); - attributes[SEMRESATTRS_CONTAINER_NAME] = metadataPromise.then( - (md) => md && process.env.CONTAINER_NAME - ); - } - return {attributes}; - }, -}; - -/** - * @returns {Promise} - */ -function isAvailable() { - return metadataRequest('instance') - .then(() => true) - .catch(() => false); -} - -/** - * Queries in gcp detector return '' if request failed - * e.g. https://github.com/open-telemetry/opentelemetry-js-contrib/blob/d2c1be459651521c6595bd5209526890eceb2a8f/detectors/node/opentelemetry-resource-detector-gcp/src/detectors/GcpDetector.ts#L92-L96 - * @param {string} path - * @returns {Promise} - */ -function metadataQuery(path) { - return metadataRequest(path).catch(() => ''); -} - -/** - * Returns the metadata from a given path. - * @param {string} path - * @returns {Promise} - */ -function metadataRequest(path) { - const baseUrl = 'http://metadata.google.internal:80'; - const options = { - method: 'GET', - headers: {'Metadata-Flavor': 'Google'}, - signal: AbortSignal.timeout(1000), - }; - return fetch(`${baseUrl}/computeMetadata/v1/${path}`, options) - .then((res) => { - // Validate status - if (!(res.status >= 200 && res.status < 300)) { - throw new Error( - `Invalid response from metadata service: invalid status code: ${res.status} text: ${res.statusText}` - ); - } - // Validation from gcp-metadata - // https://github.com/googleapis/gcp-metadata/blob/d8a868e5f487dcc3dd4bfd2d59d8c331fcf2895b/src/index.ts#L177 - const headerVal = res.headers.get('metadata-flavor'); - if (res.headers.get('Metadata-Flavor') !== 'Google') { - throw new Error( - `Invalid response from metadata service: incorrect 'Metadata-Flavor' header. Expected 'Google', got ${ - headerVal || 'no header' - }` - ); - } - return res.text(); - }) - .then((txt) => { - // ref: https://github.com/googleapis/gcp-metadata/blob/d8a868e5f487dcc3dd4bfd2d59d8c331fcf2895b/src/index.ts#L184 - try { - return jsonBigint.parse(txt); - } catch { - // nothing - } - return txt; - }); -} - -module.exports = { - gcpDetector, -}; diff --git a/packages/opentelemetry-node/lib/detectors.js b/packages/opentelemetry-node/lib/detectors.js index 175dd278..5c570196 100644 --- a/packages/opentelemetry-node/lib/detectors.js +++ b/packages/opentelemetry-node/lib/detectors.js @@ -26,6 +26,8 @@ const { const { containerDetector, } = require('@opentelemetry/resource-detector-container'); +const {gcpDetector} = require('@opentelemetry/resource-detector-gcp'); + const { envDetector, hostDetector, @@ -35,7 +37,6 @@ const { } = require('@opentelemetry/resources'); const {log} = require('./logging'); -const {gcpDetector} = require('./detector-gcp'); // @ts-ignore - compiler options do not allow lookp outside `lib` folder const ELASTIC_SDK_VERSION = require('../package.json').version; @@ -72,8 +73,6 @@ const defaultDetectors = { awsEksDetector, awsLambdaDetector, ], - // TODO: Switch back to `@opentelemetry/resource-detector-gcp` when - // https://github.com/open-telemetry/opentelemetry-js-contrib/issues/2320 is complete gcp: gcpDetector, azure: [azureAppServiceDetector, azureFunctionsDetector, azureVmDetector], }; diff --git a/packages/opentelemetry-node/lib/sdk.js b/packages/opentelemetry-node/lib/sdk.js index 74eeb0fe..3d32e134 100644 --- a/packages/opentelemetry-node/lib/sdk.js +++ b/packages/opentelemetry-node/lib/sdk.js @@ -7,6 +7,9 @@ const os = require('os'); +const { + AsyncLocalStorageContextManager, +} = require('@opentelemetry/context-async-hooks'); const { getBooleanFromEnv, getStringFromEnv, @@ -94,6 +97,13 @@ function setupShutdownHandlers(shutdownFn) { function startNodeSDK(cfg = {}) { log.trace('startNodeSDK cfg:', cfg); + // This is a temporary fix for traces being sent for GCP resource detector + // ref: https://github.com/open-telemetry/opentelemetry-js-contrib/issues/2320 + // which hopefully will be fixed in https://github.com/open-telemetry/opentelemetry-js/pull/5930 + // TL;DR: context manager is Noop hen calling `detect`, hence the suppress tracing key + // in the context is not propagated to other functions + api.context.setGlobalContextManager(new AsyncLocalStorageContextManager()); + // TODO: test behaviour with OTEL_SDK_DISABLED. // Do we still log preamble? See NodeSDK _disabled handling. // Do we still attempt to enableHostMetrics()? diff --git a/packages/opentelemetry-node/package-lock.json b/packages/opentelemetry-node/package-lock.json index 35e106f5..623823fa 100644 --- a/packages/opentelemetry-node/package-lock.json +++ b/packages/opentelemetry-node/package-lock.json @@ -10,6 +10,7 @@ "license": "Apache-2.0", "dependencies": { "@elastic/opamp-client-node": "^0.2.0", + "@opentelemetry/context-async-hooks": "^2.1.0", "@opentelemetry/core": "^2.0.0", "@opentelemetry/exporter-logs-otlp-grpc": "^0.206.0", "@opentelemetry/exporter-logs-otlp-http": "^0.206.0", @@ -62,6 +63,7 @@ "@opentelemetry/resource-detector-aws": "^2.0.0", "@opentelemetry/resource-detector-azure": "^0.14.0", "@opentelemetry/resource-detector-container": "^0.7.0", + "@opentelemetry/resource-detector-gcp": "^0.40.0", "@opentelemetry/resources": "^2.0.0", "@opentelemetry/sdk-logs": "^0.206.0", "@opentelemetry/sdk-metrics": "^2.0.0", @@ -69,7 +71,6 @@ "@opentelemetry/semantic-conventions": "^1.30.0", "@opentelemetry/winston-transport": "^0.17.0", "import-in-the-middle": "^1.12.0", - "json-bigint": "^1.0.0", "safe-stable-stringify": "^2.4.3" }, "devDependencies": { @@ -99,7 +100,6 @@ "mongoose": "^8.9.4", "mysql": "^2.18.1", "mysql2": "^3.11.5", - "nock": "^14.0.2", "openai": "^5.20.0", "oracledb": "^6.9.0", "pg": "^8.13.0", @@ -2185,45 +2185,6 @@ "sparse-bitfield": "^3.0.3" } }, - "node_modules/@mswjs/interceptors": { - "version": "0.39.5", - "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.39.5.tgz", - "integrity": "sha512-B9nHSJYtsv79uo7QdkZ/b/WoKm20IkVSmTc/WCKarmDtFwM0dRx2ouEniqwNkzCSLn3fydzKmnMzjtfdOWt3VQ==", - "dev": true, - "dependencies": { - "@open-draft/deferred-promise": "^2.2.0", - "@open-draft/logger": "^0.3.0", - "@open-draft/until": "^2.0.0", - "is-node-process": "^1.2.0", - "outvariant": "^1.4.3", - "strict-event-emitter": "^0.5.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@open-draft/deferred-promise": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz", - "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", - "dev": true - }, - "node_modules/@open-draft/logger": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz", - "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", - "dev": true, - "dependencies": { - "is-node-process": "^1.2.0", - "outvariant": "^1.4.0" - } - }, - "node_modules/@open-draft/until": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz", - "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==", - "dev": true - }, "node_modules/@opentelemetry/api": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", @@ -3323,6 +3284,71 @@ "@opentelemetry/api": "^1.0.0" } }, + "node_modules/@opentelemetry/resource-detector-gcp": { + "version": "0.40.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-gcp/-/resource-detector-gcp-0.40.0.tgz", + "integrity": "sha512-uAsUV8K4R9OJ3cgPUGYDqQByxOMTz4StmzJyofIv7+W+c1dTSEc1WVjWpTS2PAmywik++JlSmd8O4rMRJZpO8Q==", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/resources": "^2.0.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "gcp-metadata": "^6.0.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/resource-detector-gcp/node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "engines": { + "node": ">= 14" + } + }, + "node_modules/@opentelemetry/resource-detector-gcp/node_modules/gaxios": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.7.1.tgz", + "integrity": "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.9", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/resource-detector-gcp/node_modules/gcp-metadata": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.1.tgz", + "integrity": "sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A==", + "dependencies": { + "gaxios": "^6.1.1", + "google-logging-utils": "^0.0.2", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/resource-detector-gcp/node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/@opentelemetry/resources": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.1.0.tgz", @@ -5794,6 +5820,11 @@ "node": ">= 0.6" } }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, "node_modules/fast-decode-uri-component": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz", @@ -6206,6 +6237,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/google-logging-utils": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-0.0.2.tgz", + "integrity": "sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ==", + "engines": { + "node": ">=14" + } + }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -6656,12 +6695,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-node-process": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz", - "integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==", - "dev": true - }, "node_modules/is-number-object": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", @@ -6737,7 +6770,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, "engines": { "node": ">=8" }, @@ -6886,12 +6918,6 @@ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true - }, "node_modules/jsonwebtoken": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", @@ -7543,18 +7569,42 @@ "node": ">= 0.6" } }, - "node_modules/nock": { - "version": "14.0.10", - "resolved": "https://registry.npmjs.org/nock/-/nock-14.0.10.tgz", - "integrity": "sha512-Q7HjkpyPeLa0ZVZC5qpxBt5EyLczFJ91MEewQiIi9taWuA0KB/MDJlUWtON+7dGouVdADTQsf9RA7TZk6D8VMw==", - "dev": true, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "dependencies": { - "@mswjs/interceptors": "^0.39.5", - "json-stringify-safe": "^5.0.1", - "propagate": "^2.0.0" + "whatwg-url": "^5.0.0" }, "engines": { - "node": ">=18.20.0 <20 || >=20.12.1" + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" } }, "node_modules/object-inspect": { @@ -7709,12 +7759,6 @@ "node": ">=14.17" } }, - "node_modules/outvariant": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz", - "integrity": "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==", - "dev": true - }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -7958,15 +8002,6 @@ "integrity": "sha512-/MyYDxttz7DfGMMHiysAsFE4qF+pQYAA8ziO/3NcRVrQ5fSk+Mns4QZA/oRPFzvcqNoVJXQNWNAsdwBXLUkQKw==", "dev": true }, - "node_modules/propagate": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", - "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, "node_modules/protobufjs": { "version": "7.5.3", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.3.tgz", @@ -8642,12 +8677,6 @@ "npm": ">=6" } }, - "node_modules/strict-event-emitter": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz", - "integrity": "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==", - "dev": true - }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -9145,7 +9174,6 @@ "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "dev": true, "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" diff --git a/packages/opentelemetry-node/package.json b/packages/opentelemetry-node/package.json index 40c1c52e..89765117 100644 --- a/packages/opentelemetry-node/package.json +++ b/packages/opentelemetry-node/package.json @@ -73,6 +73,7 @@ }, "dependencies": { "@elastic/opamp-client-node": "^0.2.0", + "@opentelemetry/context-async-hooks": "^2.1.0", "@opentelemetry/core": "^2.0.0", "@opentelemetry/exporter-logs-otlp-grpc": "^0.206.0", "@opentelemetry/exporter-logs-otlp-http": "^0.206.0", @@ -125,6 +126,7 @@ "@opentelemetry/resource-detector-aws": "^2.0.0", "@opentelemetry/resource-detector-azure": "^0.14.0", "@opentelemetry/resource-detector-container": "^0.7.0", + "@opentelemetry/resource-detector-gcp": "^0.40.0", "@opentelemetry/resources": "^2.0.0", "@opentelemetry/sdk-logs": "^0.206.0", "@opentelemetry/sdk-metrics": "^2.0.0", @@ -132,7 +134,6 @@ "@opentelemetry/semantic-conventions": "^1.30.0", "@opentelemetry/winston-transport": "^0.17.0", "import-in-the-middle": "^1.12.0", - "json-bigint": "^1.0.0", "safe-stable-stringify": "^2.4.3" }, "devDependencies": { @@ -162,7 +163,6 @@ "mongoose": "^8.9.4", "mysql": "^2.18.1", "mysql2": "^3.11.5", - "nock": "^14.0.2", "openai": "^5.20.0", "oracledb": "^6.9.0", "pg": "^8.13.0", diff --git a/packages/opentelemetry-node/test/detector-gcp.test.js b/packages/opentelemetry-node/test/detector-gcp.test.js deleted file mode 100644 index 3a6ea507..00000000 --- a/packages/opentelemetry-node/test/detector-gcp.test.js +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -// Test that GCP detector queries the metadata correctly. It's a JS version of -// https://github.com/open-telemetry/opentelemetry-js-contrib/blob/main/detectors/node/opentelemetry-resource-detector-gcp/test/detectors/GcpDetector.test.ts - -const {test} = require('tape'); -const nock = require('nock'); -const { - CLOUDPROVIDERVALUES_GCP, - SEMRESATTRS_CLOUD_ACCOUNT_ID, - SEMRESATTRS_CLOUD_AVAILABILITY_ZONE, - SEMRESATTRS_CLOUD_PROVIDER, - SEMRESATTRS_CONTAINER_NAME, - SEMRESATTRS_HOST_ID, - SEMRESATTRS_HOST_NAME, - SEMRESATTRS_K8S_CLUSTER_NAME, - SEMRESATTRS_K8S_NAMESPACE_NAME, - SEMRESATTRS_K8S_POD_NAME, -} = require('@opentelemetry/semantic-conventions'); - -const {gcpDetector} = require('../lib/detector-gcp'); - -const HOST_ADDRESS = 'http://metadata.google.internal'; -const HEADERS = { - 'Metadata-Flavor': 'Google', -}; -const BASE_PATH = '/computeMetadata/v1'; -const INSTANCE_PATH = BASE_PATH + '/instance'; -const INSTANCE_ID_PATH = BASE_PATH + '/instance/id'; -const PROJECT_ID_PATH = BASE_PATH + '/project/project-id'; -const ZONE_PATH = BASE_PATH + '/instance/zone'; -const CLUSTER_NAME_PATH = BASE_PATH + '/instance/attributes/cluster-name'; -const HOSTNAME_PATH = BASE_PATH + '/instance/hostname'; - -const envvars = [ - 'KUBERNETES_SERVICE_HOST', - 'NAMESPACE', - 'CONTAINER_NAME', - 'HOSTNAME', -]; -const cleanEnv = () => envvars.forEach((k) => delete process.env[k]); - -// Necessary for proper mocking -nock.disableNetConnect(); - -test('gcpDetector - should return resource with GCP metadata', async (t) => { - const scope = nock(HOST_ADDRESS) - .get(INSTANCE_PATH) - .reply(200, {}, HEADERS) - .get(INSTANCE_ID_PATH) - // This number is too large to be safely represented by a JS number - // See https://github.com/googleapis/gcp-metadata/tree/fc2f0778138b36285643b2f716c485bf9614611f#take-care-with-large-number-valued-properties - .reply(200, () => '4520031799277581759', HEADERS) - .get(PROJECT_ID_PATH) - .reply(200, () => 'my-project-id', HEADERS) - .get(ZONE_PATH) - .reply(200, () => 'project/zone/my-zone', HEADERS) - .get(HOSTNAME_PATH) - .reply(200, () => 'dev.my-project.local', HEADERS); - - const {attributes} = gcpDetector.detect(); - t.equal( - await attributes[SEMRESATTRS_CLOUD_PROVIDER], - CLOUDPROVIDERVALUES_GCP - ); - t.equal(await attributes[SEMRESATTRS_CLOUD_ACCOUNT_ID], 'my-project-id'); - t.equal(await attributes[SEMRESATTRS_HOST_ID], '4520031799277581759'); - t.equal(await attributes[SEMRESATTRS_HOST_NAME], 'dev.my-project.local'); - t.equal( - await attributes[SEMRESATTRS_CLOUD_AVAILABILITY_ZONE], - 'project/zone/my-zone' - ); - t.equal(await attributes[SEMRESATTRS_K8S_CLUSTER_NAME], undefined); - t.equal(await attributes[SEMRESATTRS_K8S_NAMESPACE_NAME], undefined); - t.equal(await attributes[SEMRESATTRS_K8S_POD_NAME], undefined); - t.equal(await attributes[SEMRESATTRS_CONTAINER_NAME], undefined); - - scope.done(); -}); - -test('gcpDetector - should populate K8s attributes when KUBERNETES_SERVICE_HOST is set', async (t) => { - process.env.KUBERNETES_SERVICE_HOST = 'my-host'; - process.env.NAMESPACE = 'my-namespace'; - process.env.HOSTNAME = 'my-hostname'; - process.env.CONTAINER_NAME = 'my-container-name'; - const scope = nock(HOST_ADDRESS) - .get(INSTANCE_PATH) - .reply(200, {}, HEADERS) - .get(INSTANCE_ID_PATH) - .reply(200, () => '4520031799277581759', HEADERS) - .get(CLUSTER_NAME_PATH) - .reply(200, () => 'my-cluster', HEADERS) - .get(PROJECT_ID_PATH) - .reply(200, () => 'my-project-id', HEADERS) - .get(ZONE_PATH) - .reply(200, () => 'project/zone/my-zone', HEADERS) - .get(HOSTNAME_PATH) - .reply(200, () => 'dev.my-project.local', HEADERS); - - const {attributes} = gcpDetector.detect(); - t.equal( - await attributes[SEMRESATTRS_CLOUD_PROVIDER], - CLOUDPROVIDERVALUES_GCP - ); - t.equal(await attributes[SEMRESATTRS_CLOUD_ACCOUNT_ID], 'my-project-id'); - t.equal(await attributes[SEMRESATTRS_HOST_ID], '4520031799277581759'); - t.equal(await attributes[SEMRESATTRS_HOST_NAME], 'dev.my-project.local'); - t.equal( - await attributes[SEMRESATTRS_CLOUD_AVAILABILITY_ZONE], - 'project/zone/my-zone' - ); - t.equal(await attributes[SEMRESATTRS_K8S_CLUSTER_NAME], 'my-cluster'); - t.equal(await attributes[SEMRESATTRS_K8S_NAMESPACE_NAME], 'my-namespace'); - t.equal(await attributes[SEMRESATTRS_K8S_POD_NAME], 'my-hostname'); - t.equal(await attributes[SEMRESATTRS_CONTAINER_NAME], 'my-container-name'); - scope.done(); - cleanEnv(); -}); - -test('gcpDetector - should return resource and empty data for non-available metadata attributes', async (t) => { - // Set KUBERNETES_SERVICE_HOST to have the implementation call - // CLUSTER_NAME_PATH, to be able to test it handling the HTTP 413. - process.env.KUBERNETES_SERVICE_HOST = 'my-host'; - const scope = nock(HOST_ADDRESS) - .get(INSTANCE_PATH) - .reply(200, {}, HEADERS) - .get(PROJECT_ID_PATH) - .reply(200, () => 'my-project-id', HEADERS) - .get(ZONE_PATH) - .reply(413) - .get(INSTANCE_ID_PATH) - .reply(400, undefined, HEADERS) - .get(CLUSTER_NAME_PATH) - .reply(413) - .get(HOSTNAME_PATH) - .reply(400, undefined, HEADERS); - - const {attributes} = gcpDetector.detect(); - t.equal( - await attributes[SEMRESATTRS_CLOUD_PROVIDER], - CLOUDPROVIDERVALUES_GCP - ); - t.equal(await attributes[SEMRESATTRS_CLOUD_ACCOUNT_ID], 'my-project-id'); - t.equal(await attributes[SEMRESATTRS_HOST_ID], ''); - t.equal(await attributes[SEMRESATTRS_HOST_NAME], ''); - t.equal(await attributes[SEMRESATTRS_CLOUD_AVAILABILITY_ZONE], ''); - t.equal(await attributes[SEMRESATTRS_K8S_CLUSTER_NAME], ''); - t.equal(await attributes[SEMRESATTRS_K8S_NAMESPACE_NAME], undefined); - t.equal(await attributes[SEMRESATTRS_K8S_POD_NAME], undefined); - t.equal(await attributes[SEMRESATTRS_CONTAINER_NAME], undefined); - scope.done(); - cleanEnv(); -}); - -test('gcpDetector - should return empty resource if not detected', async (t) => { - const {attributes} = gcpDetector.detect(); - t.equal(await attributes[SEMRESATTRS_CLOUD_PROVIDER], undefined); - t.equal(await attributes[SEMRESATTRS_CLOUD_ACCOUNT_ID], undefined); - t.equal(await attributes[SEMRESATTRS_HOST_ID], undefined); - t.equal(await attributes[SEMRESATTRS_HOST_NAME], undefined); - t.equal(await attributes[SEMRESATTRS_CLOUD_AVAILABILITY_ZONE], undefined); - t.equal(await attributes[SEMRESATTRS_K8S_CLUSTER_NAME], undefined); - t.equal(await attributes[SEMRESATTRS_K8S_NAMESPACE_NAME], undefined); - t.equal(await attributes[SEMRESATTRS_K8S_POD_NAME], undefined); - t.equal(await attributes[SEMRESATTRS_CONTAINER_NAME], undefined); -}); - -// Re-enable module -nock.enableNetConnect(); diff --git a/packages/opentelemetry-node/types/detector-gcp.d.ts b/packages/opentelemetry-node/types/detector-gcp.d.ts deleted file mode 100644 index 7ccc4526..00000000 --- a/packages/opentelemetry-node/types/detector-gcp.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -export type ResourceDetector = import('@opentelemetry/resources').ResourceDetector; -/** @type {ResourceDetector} */ -export const gcpDetector: ResourceDetector;