From 4e2c12064c765e8530574a08089111c10bbe28bb Mon Sep 17 00:00:00 2001 From: Ievgenii Saikevych Date: Wed, 24 Oct 2018 17:38:12 -0700 Subject: [PATCH 1/3] Adds monitored resource to [core] --- packages/opencensus-core/package-lock.json | 146 +++++++++++++++-- packages/opencensus-core/package.json | 4 +- .../aws-identity-document-utils.ts | 100 ++++++++++++ .../monitored-resource/gcp-metadata-config.ts | 138 ++++++++++++++++ .../monitored-resource/monitored-resource.ts | 50 ++++++ .../src/common/monitored-resource/types.ts | 75 +++++++++ .../src/common/monitored-resource/util.ts | 49 ++++++ packages/opencensus-core/src/index.ts | 4 + .../test/test-monitored-resource.ts | 154 ++++++++++++++++++ 9 files changed, 709 insertions(+), 11 deletions(-) create mode 100644 packages/opencensus-core/src/common/monitored-resource/aws-identity-document-utils.ts create mode 100644 packages/opencensus-core/src/common/monitored-resource/gcp-metadata-config.ts create mode 100644 packages/opencensus-core/src/common/monitored-resource/monitored-resource.ts create mode 100644 packages/opencensus-core/src/common/monitored-resource/types.ts create mode 100644 packages/opencensus-core/src/common/monitored-resource/util.ts create mode 100644 packages/opencensus-core/test/test-monitored-resource.ts diff --git a/packages/opencensus-core/package-lock.json b/packages/opencensus-core/package-lock.json index 4ead81120..d20577c9e 100644 --- a/packages/opencensus-core/package-lock.json +++ b/packages/opencensus-core/package-lock.json @@ -1,4 +1,7 @@ { + "name": "@opencensus/core", + "version": "0.0.6", + "lockfileVersion": 1, "requires": true, "lockfileVersion": 1, "dependencies": { @@ -15,10 +18,20 @@ "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-2.2.48.tgz", "integrity": "sha512-nlK/iyETgafGli8Zh9zJVCTicvU3iajSkRwOh3Hhiva598CMqNJ4NcVCGMTGKpGpTYj/9R8RLzS9NAykSSCqGw==" }, + "@types/nock": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@types/nock/-/nock-9.3.0.tgz", + "integrity": "sha512-ZHf/X8rTQ5Tb1rHjxIJYqm55uO265agE3G7NoSXVa2ep+EcJXgB2fsme+zBvK7MhrxTwkC/xkB6THyv50u0MGw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/node": { - "version": "9.4.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-9.4.7.tgz", - "integrity": "sha512-4Ba90mWNx8ddbafuyGGwjkZMigi+AWfYLSDCpovwsE63ia8w93r3oJ8PIAQc3y8U+XHcnMOHPIzNe3o438Ywcw==" + "version": "9.6.35", + "resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.35.tgz", + "integrity": "sha512-h5zvHS8wXHGa+Gcqs9K8vqCgOtqjr0+NqG/DDJmQIX1wpR9HivAfgV8bjcD3mGM4bPfQw5Aneb2Pn8355L83jA==", + "dev": true }, "@types/once": { "version": "1.4.0", @@ -126,6 +139,12 @@ "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true + }, "async-listener": { "version": "0.6.9", "resolved": "https://registry.npmjs.org/async-listener/-/async-listener-0.6.9.tgz", @@ -263,6 +282,20 @@ "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=" }, + "chai": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", + "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", + "dev": true, + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "pathval": "^1.1.0", + "type-detect": "^4.0.5" + } + }, "chalk": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", @@ -293,6 +326,12 @@ "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=" }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true + }, "clang-format": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/clang-format/-/clang-format-1.2.2.tgz", @@ -443,10 +482,26 @@ } } }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, + "requires": { + "type-detect": "^4.0.0" + } + }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", + "dev": true + }, "deep-extend": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", - "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=" + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true }, "diff": { "version": "3.5.0", @@ -534,6 +589,12 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true + }, "get-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", @@ -803,6 +864,12 @@ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz", "integrity": "sha512-xyQpxeWWMKyJps9CuGJYeng6ssI5bpqS9ltQpdVQ90t4ql6NdnxFKh95JcRt2cun/DjMVNrdjniLPuMA69xmCw==" }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, "latest-version": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", @@ -1028,6 +1095,40 @@ "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=" }, + "nock": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/nock/-/nock-10.0.1.tgz", + "integrity": "sha512-M0aL9IDbUFURmokoXqejZQybZk8EtlYjUBjaoICVbW62uOlyPRsnEsceyOlUik4spCOt50ptwM4BTPt20ITtcQ==", + "dev": true, + "requires": { + "chai": "^4.1.2", + "debug": "^4.1.0", + "deep-equal": "^1.0.0", + "json-stringify-safe": "^5.0.1", + "lodash": "^4.17.5", + "mkdirp": "^0.5.0", + "propagate": "^1.0.0", + "qs": "^6.5.1", + "semver": "^5.5.0" + }, + "dependencies": { + "debug": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", + "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, "normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", @@ -3597,6 +3698,12 @@ "pify": "^3.0.0" } }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "dev": true + }, "pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", @@ -3607,22 +3714,35 @@ "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" }, + "propagate": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/propagate/-/propagate-1.0.0.tgz", + "integrity": "sha1-AMLa7t2iDofjeCs0Stuhzd1q1wk=", + "dev": true + }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + }, "quick-lru": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=" }, "rc": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.6.tgz", - "integrity": "sha1-6xiYnG1PTxYsOZ953dKfODVWgJI=", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, "requires": { - "deep-extend": "~0.4.0", + "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" @@ -3951,6 +4071,12 @@ "tslib": "^1.8.1" } }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, "typescript": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.6.2.tgz", diff --git a/packages/opencensus-core/package.json b/packages/opencensus-core/package.json index e0f438784..a837673ff 100644 --- a/packages/opencensus-core/package.json +++ b/packages/opencensus-core/package.json @@ -40,7 +40,8 @@ "devDependencies": { "@types/continuation-local-storage": "^3.2.1", "@types/mocha": "^2.2.48", - "@types/node": "^9.4.7", + "@types/nock": "^9.3.0", + "@types/node": "^9.6.35", "@types/once": "^1.4.0", "@types/semver": "^5.5.0", "@types/shimmer": "^1.0.1", @@ -49,6 +50,7 @@ "intercept-stdout": "^0.1.2", "mocha": "^5.0.4", "ncp": "^2.0.0", + "nock": "^10.0.1", "nyc": "11.6.0", "ts-node": "^4.0.0", "typescript": "~2.6.1" diff --git a/packages/opencensus-core/src/common/monitored-resource/aws-identity-document-utils.ts b/packages/opencensus-core/src/common/monitored-resource/aws-identity-document-utils.ts new file mode 100644 index 000000000..00e9df67f --- /dev/null +++ b/packages/opencensus-core/src/common/monitored-resource/aws-identity-document-utils.ts @@ -0,0 +1,100 @@ +/** + * Copyright 2018, OpenCensus 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 + * + * http://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 {get} from 'http'; +import * as logger from '../../common/console-logger'; +import * as loggerTypes from '../../common/types'; + +/** Util methods for getting and parsing AWS instance identity document. */ +export class AwsIdentityDocumentUtils { + /** Aws instance identity URL */ + static HOST = '169.254.169.254'; + static readonly PATH = '/latest/dynamic/instance-identity/document'; + static readonly PORT = 80; + static runned = false; + static metadata: Record = {}; + static promise: Promise>; + static readonly logger: loggerTypes.Logger = logger.logger(); + + /** + * Establishes an HTTP connection to AWS instance identity document url. + * If the application is running on an EC2 instance, we should be able + * to get back a valid JSON document. Parses that document and stores + * the identity properties in a local map. + */ + static run() { + if (AwsIdentityDocumentUtils.runned) { + return AwsIdentityDocumentUtils.promise; + } + AwsIdentityDocumentUtils.promise = + AwsIdentityDocumentUtils.getDocument().then(metadata => { + if (Object.keys(metadata).length) { + AwsIdentityDocumentUtils.metadata = metadata; + AwsIdentityDocumentUtils.runned = true; + } + return metadata; + }); + return AwsIdentityDocumentUtils.promise; + } + + /** + * Fetches the requested instance metadata entry. + * @param name Attribute name relative to the computeMetadata/v1 prefix + */ + private static getDocument() { + const promise = new Promise((resolve, reject) => { + get({ + host: AwsIdentityDocumentUtils.HOST, + path: AwsIdentityDocumentUtils.PATH, + port: AwsIdentityDocumentUtils.PORT + }, + (response) => { + let body = ''; + response.on('data', chunk => body += chunk); + response.on('end', () => { + if (response.statusCode >= 200 && response.statusCode < 300) { + try { + const data = JSON.parse(body); + resolve(data); + } catch (e) { + response.resume(); + } + } else { + const errorMessage = + `Request Failed. Status code: ${response.statusCode}`; + AwsIdentityDocumentUtils.logger.error(errorMessage); + reject(errorMessage); + response.resume(); + } + }); + }); + }); + return promise.catch(e => e); + } + + /** + * AWS Instance Identity Document is a JSON file. + * See + * docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-identity-documents.html. + */ + getMetadata() { + return AwsIdentityDocumentUtils.metadata; + } + + static isRunning() { + return AwsIdentityDocumentUtils.runned; + } +} diff --git a/packages/opencensus-core/src/common/monitored-resource/gcp-metadata-config.ts b/packages/opencensus-core/src/common/monitored-resource/gcp-metadata-config.ts new file mode 100644 index 000000000..828144b41 --- /dev/null +++ b/packages/opencensus-core/src/common/monitored-resource/gcp-metadata-config.ts @@ -0,0 +1,138 @@ +/** + * Copyright 2018, OpenCensus 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 + * + * http://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 {get} from 'http'; +import {isString} from 'util'; + +import * as logger from '../../common/console-logger'; +import * as loggerTypes from '../../common/types'; + +import {monitoredResourceAttributes} from './types'; + +export class GcpMetadataConfig { + static URL = 'metadata/computeMetadata/v1'; + static PORT = 80; + static readonly HEADER = {'Metadata-Flavor': 'Google'}; + /** Kubenertes environment variables */ + static readonly KUBERNETES_SERVICE_HOST = 'KUBERNETES_SERVICE_HOST'; + static runned = false; + /** Persistant metadata */ + static metadata: Record = {}; + static readonly logger: loggerTypes.Logger = logger.logger(); + static promise: Promise>; + + /** + * Initializes metadata service once and load gcp metadata into map. + */ + static run() { + if (GcpMetadataConfig.runned) { + return GcpMetadataConfig.promise; + } + GcpMetadataConfig.promise = + GcpMetadataConfig.getAttribute('instance_id').then(id => { + if (isString(id)) { + GcpMetadataConfig.metadata['instance_id'] = id; + GcpMetadataConfig.runned = true; + return GcpMetadataConfig.getAttributes(); + } + return Promise.resolve(GcpMetadataConfig.metadata); + }); + return GcpMetadataConfig.promise; + } + + private static getAttributes() { + let attributes; + if (GcpMetadataConfig.KUBERNETES_SERVICE_HOST in process.env) { + attributes = monitoredResourceAttributes.GKE; + } else { + attributes = monitoredResourceAttributes.GCE; + } + const promises: Array> = []; + Object.keys(attributes) + .filter(key => key !== 'instance_id') + .forEach(key => { + promises.push(GcpMetadataConfig.getAttribute(key).then(value => { + if (value) { + GcpMetadataConfig.metadata[key] = value; + } + return value; + })); + }); + return Promise.all(promises) + .then(() => GcpMetadataConfig.metadata) + .catch(e => e); + } + + /** + * Fetches the requested instance metadata entry. + * @param name Attribute name relative to the computeMetadata/v1 prefix + */ + static getAttribute(name: string): Promise { + const options = { + host: GcpMetadataConfig.URL, + path: '/' + monitoredResourceAttributes.GKE[name], + port: GcpMetadataConfig.PORT, + headers: GcpMetadataConfig.HEADER + }; + const promise = new Promise((resolve, reject) => { + try { + get(options, response => { + if (response.statusCode >= 200 && response.statusCode < 300) { + let rawData = ''; + response.on('data', chunk => rawData += chunk); + response.on('end', () => resolve(rawData)); + } else { + const errorMessage = + `Request Failed. Status code: ${response.statusCode}`; + this.logger.error(errorMessage); + response.resume(); + reject(errorMessage); + } + }).on('error', (e) => { + reject(e); + }); + } catch (e) { + reject(e); + } + }); + return promise.catch(e => e); + } + + /** + * Gets metadata for GCP GCE instance. + */ + getGceMetadata() { + return GcpMetadataConfig.metadata; + } + + /** + * Gets metadata for GCP GKE container. + */ + getGkeMetadata() { + Object.keys(monitoredResourceAttributes.GKE).forEach(key => { + const value = monitoredResourceAttributes.GKE[key]; + const attributeValue = process.env[value]; + if (attributeValue) { + GcpMetadataConfig.metadata[key] = attributeValue; + } + }); + return GcpMetadataConfig.metadata; + } + + static isRunning(): boolean { + return GcpMetadataConfig.runned; + } +} diff --git a/packages/opencensus-core/src/common/monitored-resource/monitored-resource.ts b/packages/opencensus-core/src/common/monitored-resource/monitored-resource.ts new file mode 100644 index 000000000..ac385c71a --- /dev/null +++ b/packages/opencensus-core/src/common/monitored-resource/monitored-resource.ts @@ -0,0 +1,50 @@ +/** + * Represents an auto-detected monitored resource used by application for + * exporting stats. It has a resource type associated with a mapping + * from resource labels to values. + */ +import {AwsIdentityDocumentUtils} from './aws-identity-document-utils'; +import {GcpMetadataConfig} from './gcp-metadata-config'; +import * as types from './types'; + +/** + * Represents gce_instance type monitored resource. + * For definition refer to + * https://cloud.google.com/monitoring/api/resources#tag_gce_instance + */ +export class GcpGceMonitoredResource implements types.MonitoredResource { + type = types.MonitoredResources.GCP_GCE_INSTANCE; + + getLabels() { + const gcp = new GcpMetadataConfig(); + return gcp.getGceMetadata(); + } +} + +/** + * Represents gke_container type monitored resource. + * For definition refer to + * https://cloud.google.com/monitoring/api/resources#tag_gke_container + */ +export class GcpGkeMonitoredResource implements types.MonitoredResource { + type = types.MonitoredResources.GCP_GKE_CONTAINER; + + getLabels() { + const gcp = new GcpMetadataConfig(); + return gcp.getGkeMetadata(); + } +} + +/** + * Represents aws_ec2_instance type monitored resource. + * For definition refer to + * https://cloud.google.com/monitoring/api/resources#tag_aws_ec2_instance + */ +export class AwsMonitoredResource implements types.MonitoredResource { + type = types.MonitoredResources.AWS_EC2_INSTANCE; + + getLabels() { + const aws = new AwsIdentityDocumentUtils(); + return aws.getMetadata(); + } +} diff --git a/packages/opencensus-core/src/common/monitored-resource/types.ts b/packages/opencensus-core/src/common/monitored-resource/types.ts new file mode 100644 index 000000000..d4dbdc786 --- /dev/null +++ b/packages/opencensus-core/src/common/monitored-resource/types.ts @@ -0,0 +1,75 @@ +export enum MonitoredResources { + GCP_GCE_INSTANCE = 'gce_instance', + GCP_GKE_CONTAINER = 'gke_container', + AWS_EC2_INSTANCE = 'aws_ec2_instance' +} + +export const monitoredResourceAttributes: Record< + string, Record> = { + /** + * GCE common attributes + * See: + * https://cloud.google.com/appengine/docs/flexible/python/runtime#environment_variables + */ + GCE: { + /** + * Numeric VM instance identifier assigned by Compute Engine. + */ + instance_id: 'instance/id', + /** + * ProjectID is the identifier of the GCP project associated with this + * resource, such as "my-project". + */ + project_id: 'project/project-id', + /** Compute Engine zone in which the VM is running. */ + zone: 'instance/zone', + }, + GKE: { + /** + * Name for the cluster container is running in. + */ + cluster_name: 'instance/attributes/cluster-name', + /** + * Numeric VM instance identifier assigned by Compute Engine. + */ + instance_id: 'instance/id', + /** + * ProjectID is the identifier of the GCP project associated with this + * resource, such as "my-project". + */ + project_id: 'project/project-id', + /** + * Compute Engine zone in which the VM is running. + */ + zone: 'instance/zone', + }, + AWS: { + /** + * The AWS region for the VM. The format of this field is "aws:{region}", + * where supported values for {region} are listed at + * http://docs.aws.amazon.com/general/latest/gr/rande.html. + */ + region: 'region', + /** + * The AWS account number for the VM. + */ + accountId: 'aws_account', + /** + * The instance id of the instance. + */ + instanceId: 'instance_id' + } +}; + +export type MonitoredResourceType = + MonitoredResources.GCP_GKE_CONTAINER| + MonitoredResources.GCP_GCE_INSTANCE|MonitoredResources.AWS_EC2_INSTANCE; +export type MonitoredResourceMetadata = + Promise|string>|Record|string; + +export interface MonitoredResource { + readonly type: MonitoredResourceType; + getLabels(): MonitoredResourceMetadata; +} + +export declare let monitoredResourceMetadata: Record; \ No newline at end of file diff --git a/packages/opencensus-core/src/common/monitored-resource/util.ts b/packages/opencensus-core/src/common/monitored-resource/util.ts new file mode 100644 index 000000000..9129d576e --- /dev/null +++ b/packages/opencensus-core/src/common/monitored-resource/util.ts @@ -0,0 +1,49 @@ +/** + * Copyright 2018, OpenCensus 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 + * + * http://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 {AwsIdentityDocumentUtils} from './aws-identity-document-utils'; +import {GcpMetadataConfig} from './gcp-metadata-config'; +import * as resources from './monitored-resource'; +import {MonitoredResource} from './types'; + +/** + * Utilities for auto detecting monitored resource based on the + * environment where the application is running. + */ +export class MonitoredResourceUtil { + /** + * Returns a self-configured monitored resource, or null if the application + * is not running on a supported environment. + */ + static getDefaultResource(): Promise { + return GcpMetadataConfig.run().then(metadata => { + if (process.env['KUBERNETES_SERVICE_HOST']) { + return new resources.GcpGkeMonitoredResource(); + } + + if (GcpMetadataConfig.isRunning()) { + return new resources.GcpGceMonitoredResource(); + } + + return AwsIdentityDocumentUtils.run().then(() => { + if (AwsIdentityDocumentUtils.isRunning()) { + return new resources.AwsMonitoredResource(); + } + return Promise.resolve(null); + }); + }); + } +} diff --git a/packages/opencensus-core/src/index.ts b/packages/opencensus-core/src/index.ts index 4e46a6bd6..0a8f2c7cc 100644 --- a/packages/opencensus-core/src/index.ts +++ b/packages/opencensus-core/src/index.ts @@ -24,6 +24,7 @@ export * from './trace/instrumentation/types'; export * from './trace/propagation/types'; export * from './exporters/types'; export * from './common/types'; +export * from './common/monitored-resource/types'; // classes @@ -40,6 +41,9 @@ export * from './trace/instrumentation/base-plugin'; export * from './exporters/exporter-buffer'; export * from './exporters/console-exporter'; +// Monitored resource +export * from './common/monitored-resource/util'; + // STATS CLASSES // classes diff --git a/packages/opencensus-core/test/test-monitored-resource.ts b/packages/opencensus-core/test/test-monitored-resource.ts new file mode 100644 index 000000000..4fb5e99b4 --- /dev/null +++ b/packages/opencensus-core/test/test-monitored-resource.ts @@ -0,0 +1,154 @@ +/** + * Copyright 2018, OpenCensus 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 + * + * http://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 assert from 'assert'; +import * as fs from 'fs'; +import * as nock from 'nock'; + +import * as logger from '../src/common/console-logger'; +import {AwsIdentityDocumentUtils} from '../src/common/monitored-resource/aws-identity-document-utils'; +import {GcpMetadataConfig} from '../src/common/monitored-resource/gcp-metadata-config'; +import * as resources from '../src/common/monitored-resource/monitored-resource'; +import {monitoredResourceAttributes, MonitoredResources} from '../src/common/monitored-resource/types'; +import {MonitoredResourceUtil} from '../src/common/monitored-resource/util'; + +describe('MonitoredResourceUtil get default resource', () => { + const testLogger = logger.logger(); + let dryrun = true; + const GOOGLE_APPLICATION_CREDENTIALS = + process.env.GOOGLE_APPLICATION_CREDENTIALS as string; + const OPENCENSUS_NETWORK_TESTS = + process.env.OPENCENSUS_NETWORK_TESTS as string; + let PROJECT_ID = 'fake-project-id'; + + const env = Object.assign({}, process.env); + const gcpUrl = GcpMetadataConfig.URL; + + before(() => { + if (GOOGLE_APPLICATION_CREDENTIALS) { + dryrun = !fs.existsSync(GOOGLE_APPLICATION_CREDENTIALS) && + !fs.existsSync(OPENCENSUS_NETWORK_TESTS); + if (!dryrun) { + const credentials = require(GOOGLE_APPLICATION_CREDENTIALS); + PROJECT_ID = credentials.project_id; + testLogger.debug( + 'GOOGLE_APPLICATION_CREDENTIALS: %s', + GOOGLE_APPLICATION_CREDENTIALS); + testLogger.debug('projectId = %s', PROJECT_ID); + } + } + if (dryrun) { + nock.disableNetConnect(); + } + testLogger.debug('dryrun=%s', dryrun); + GcpMetadataConfig.URL = 'fake.service.io'; + }); + + after(() => { + GcpMetadataConfig.URL = gcpUrl; + }); + + beforeEach(() => { + process.env = Object.assign({}, env); + nock.cleanAll(); + }); + + function doGcpMetadataConfigNock(key: string) { + const resource = monitoredResourceAttributes[key]; + Object.keys(resource).forEach(prop => { + const url = `http://${GcpMetadataConfig.URL}:${GcpMetadataConfig.PORT}`; + nock(url).persist().get('/' + resource[prop]).reply(200, resource[prop]); + }); + } + + describe('GcpGkeMonitoredResource', () => { + after(() => { + GcpMetadataConfig.metadata = {}; + GcpMetadataConfig.runned = false; + }); + + beforeEach(() => { + process.env['KUBERNETES_SERVICE_HOST'] = 'kubernetis.test'; + doGcpMetadataConfigNock('GKE'); + }); + + it('should initialize GCP GKE if KUBERNETES_SERVICE_HOST defined', + async () => { + await MonitoredResourceUtil.getDefaultResource().then(resource => { + assert.notEqual(resource, null); + assert.ok(resource instanceof resources.GcpGkeMonitoredResource); + assert.strictEqual( + resource.type, MonitoredResources.GCP_GKE_CONTAINER); + }); + }); + + it('should has metadata', async () => { + await MonitoredResourceUtil.getDefaultResource().then(resource => { + assert.deepEqual(resource.getLabels(), monitoredResourceAttributes.GKE); + }); + }); + }); + + describe('GcpGceMonitoredResource', () => { + after(() => { + GcpMetadataConfig.metadata = {}; + GcpMetadataConfig.runned = false; + }); + beforeEach(() => { + doGcpMetadataConfigNock('GCE'); + }); + it('should initialize GCP GCE if metadata is received', async () => { + await MonitoredResourceUtil.getDefaultResource().then(resource => { + assert.notEqual(resource, null); + assert.ok(resource instanceof resources.GcpGceMonitoredResource); + assert.strictEqual(resource.type, MonitoredResources.GCP_GCE_INSTANCE); + }); + }); + + it('should has metadata', async () => { + await MonitoredResourceUtil.getDefaultResource().then(resource => { + assert.deepEqual(resource.getLabels(), monitoredResourceAttributes.GCE); + }); + }); + }); + + describe('AwsMonitoredResource', () => { + function doNock() { + const resource = monitoredResourceAttributes.AWS; + const url = `http://${AwsIdentityDocumentUtils.HOST}:${ + AwsIdentityDocumentUtils.PORT}`; + nock(url).get(AwsIdentityDocumentUtils.PATH).reply(200, resource); + } + + it('should initialize AWS identity document util if is running on AWS', + async () => { + doNock(); + await MonitoredResourceUtil.getDefaultResource().then(resource => { + assert.notEqual(resource, null); + assert.ok(resource instanceof resources.AwsMonitoredResource); + assert.strictEqual( + resource.type, MonitoredResources.AWS_EC2_INSTANCE); + }); + }); + + it('should has metadata', async () => { + doNock(); + await MonitoredResourceUtil.getDefaultResource().then(resource => { + assert.deepEqual(resource.getLabels(), monitoredResourceAttributes.AWS); + }); + }); + }); +}); From ce3d154efdb40aff3c1f183ca4858bbdaed27c82 Mon Sep 17 00:00:00 2001 From: Ievgenii Saikevych Date: Thu, 1 Nov 2018 11:14:19 -0700 Subject: [PATCH 2/3] Uses instance attributes instead global --- .../monitored-resource/gcp-metadata-config.ts | 36 ++++++++++--------- .../src/common/monitored-resource/types.ts | 3 +- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/packages/opencensus-core/src/common/monitored-resource/gcp-metadata-config.ts b/packages/opencensus-core/src/common/monitored-resource/gcp-metadata-config.ts index 828144b41..97b55a5cc 100644 --- a/packages/opencensus-core/src/common/monitored-resource/gcp-metadata-config.ts +++ b/packages/opencensus-core/src/common/monitored-resource/gcp-metadata-config.ts @@ -33,6 +33,7 @@ export class GcpMetadataConfig { static metadata: Record = {}; static readonly logger: loggerTypes.Logger = logger.logger(); static promise: Promise>; + static readonly ID_KEY = 'instance/id'; /** * Initializes metadata service once and load gcp metadata into map. @@ -41,35 +42,36 @@ export class GcpMetadataConfig { if (GcpMetadataConfig.runned) { return GcpMetadataConfig.promise; } + let attributes: Record; + if (GcpMetadataConfig.KUBERNETES_SERVICE_HOST in process.env) { + attributes = monitoredResourceAttributes.GKE; + } else { + attributes = monitoredResourceAttributes.GCE; + } GcpMetadataConfig.promise = - GcpMetadataConfig.getAttribute('instance_id').then(id => { + GcpMetadataConfig.getAttribute('instance/id').then(id => { if (isString(id)) { GcpMetadataConfig.metadata['instance_id'] = id; GcpMetadataConfig.runned = true; - return GcpMetadataConfig.getAttributes(); + return GcpMetadataConfig.getAttributes(attributes); } return Promise.resolve(GcpMetadataConfig.metadata); }); return GcpMetadataConfig.promise; } - private static getAttributes() { - let attributes; - if (GcpMetadataConfig.KUBERNETES_SERVICE_HOST in process.env) { - attributes = monitoredResourceAttributes.GKE; - } else { - attributes = monitoredResourceAttributes.GCE; - } + private static getAttributes(attributes: Record) { const promises: Array> = []; Object.keys(attributes) .filter(key => key !== 'instance_id') .forEach(key => { - promises.push(GcpMetadataConfig.getAttribute(key).then(value => { - if (value) { - GcpMetadataConfig.metadata[key] = value; - } - return value; - })); + promises.push( + GcpMetadataConfig.getAttribute(attributes[key]).then(value => { + if (value) { + GcpMetadataConfig.metadata[key] = value; + } + return value; + })); }); return Promise.all(promises) .then(() => GcpMetadataConfig.metadata) @@ -80,10 +82,10 @@ export class GcpMetadataConfig { * Fetches the requested instance metadata entry. * @param name Attribute name relative to the computeMetadata/v1 prefix */ - static getAttribute(name: string): Promise { + static getAttribute(attribute: string): Promise { const options = { host: GcpMetadataConfig.URL, - path: '/' + monitoredResourceAttributes.GKE[name], + path: '/' + attribute, port: GcpMetadataConfig.PORT, headers: GcpMetadataConfig.HEADER }; diff --git a/packages/opencensus-core/src/common/monitored-resource/types.ts b/packages/opencensus-core/src/common/monitored-resource/types.ts index d4dbdc786..56511c32e 100644 --- a/packages/opencensus-core/src/common/monitored-resource/types.ts +++ b/packages/opencensus-core/src/common/monitored-resource/types.ts @@ -64,8 +64,7 @@ export const monitoredResourceAttributes: Record< export type MonitoredResourceType = MonitoredResources.GCP_GKE_CONTAINER| MonitoredResources.GCP_GCE_INSTANCE|MonitoredResources.AWS_EC2_INSTANCE; -export type MonitoredResourceMetadata = - Promise|string>|Record|string; +export type MonitoredResourceMetadata = Record|string; export interface MonitoredResource { readonly type: MonitoredResourceType; From 50e3a257219870a26ddd2dc4aed672549ad0b7fe Mon Sep 17 00:00:00 2001 From: Ievgenii Saikevych Date: Fri, 16 Nov 2018 13:57:08 -0800 Subject: [PATCH 3/3] Uses limited information from AWS --- packages/opencensus-core/package-lock.json | 45 +++++-------------- .../aws-identity-document-utils.ts | 9 +++- 2 files changed, 19 insertions(+), 35 deletions(-) diff --git a/packages/opencensus-core/package-lock.json b/packages/opencensus-core/package-lock.json index d20577c9e..cb3ade9b5 100644 --- a/packages/opencensus-core/package-lock.json +++ b/packages/opencensus-core/package-lock.json @@ -1,7 +1,4 @@ { - "name": "@opencensus/core", - "version": "0.0.6", - "lockfileVersion": 1, "requires": true, "lockfileVersion": 1, "dependencies": { @@ -22,7 +19,6 @@ "version": "9.3.0", "resolved": "https://registry.npmjs.org/@types/nock/-/nock-9.3.0.tgz", "integrity": "sha512-ZHf/X8rTQ5Tb1rHjxIJYqm55uO265agE3G7NoSXVa2ep+EcJXgB2fsme+zBvK7MhrxTwkC/xkB6THyv50u0MGw==", - "dev": true, "requires": { "@types/node": "*" } @@ -30,8 +26,7 @@ "@types/node": { "version": "9.6.35", "resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.35.tgz", - "integrity": "sha512-h5zvHS8wXHGa+Gcqs9K8vqCgOtqjr0+NqG/DDJmQIX1wpR9HivAfgV8bjcD3mGM4bPfQw5Aneb2Pn8355L83jA==", - "dev": true + "integrity": "sha512-h5zvHS8wXHGa+Gcqs9K8vqCgOtqjr0+NqG/DDJmQIX1wpR9HivAfgV8bjcD3mGM4bPfQw5Aneb2Pn8355L83jA==" }, "@types/once": { "version": "1.4.0", @@ -142,8 +137,7 @@ "assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==" }, "async-listener": { "version": "0.6.9", @@ -286,7 +280,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", - "dev": true, "requires": { "assertion-error": "^1.1.0", "check-error": "^1.0.2", @@ -329,8 +322,7 @@ "check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "dev": true + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" }, "clang-format": { "version": "1.2.2", @@ -486,7 +478,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dev": true, "requires": { "type-detect": "^4.0.0" } @@ -494,14 +485,12 @@ "deep-equal": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", - "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", - "dev": true + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" }, "deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" }, "diff": { "version": "3.5.0", @@ -592,8 +581,7 @@ "get-func-name": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", - "dev": true + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=" }, "get-stream": { "version": "3.0.0", @@ -867,8 +855,7 @@ "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, "latest-version": { "version": "3.1.0", @@ -1099,7 +1086,6 @@ "version": "10.0.1", "resolved": "https://registry.npmjs.org/nock/-/nock-10.0.1.tgz", "integrity": "sha512-M0aL9IDbUFURmokoXqejZQybZk8EtlYjUBjaoICVbW62uOlyPRsnEsceyOlUik4spCOt50ptwM4BTPt20ITtcQ==", - "dev": true, "requires": { "chai": "^4.1.2", "debug": "^4.1.0", @@ -1116,7 +1102,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", - "dev": true, "requires": { "ms": "^2.1.1" } @@ -1124,8 +1109,7 @@ "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" } } }, @@ -3701,8 +3685,7 @@ "pathval": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", - "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", - "dev": true + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=" }, "pify": { "version": "3.0.0", @@ -3717,8 +3700,7 @@ "propagate": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/propagate/-/propagate-1.0.0.tgz", - "integrity": "sha1-AMLa7t2iDofjeCs0Stuhzd1q1wk=", - "dev": true + "integrity": "sha1-AMLa7t2iDofjeCs0Stuhzd1q1wk=" }, "pseudomap": { "version": "1.0.2", @@ -3728,8 +3710,7 @@ "qs": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" }, "quick-lru": { "version": "1.1.0", @@ -3740,7 +3721,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, "requires": { "deep-extend": "^0.6.0", "ini": "~1.3.0", @@ -4074,8 +4054,7 @@ "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" }, "typescript": { "version": "2.6.2", diff --git a/packages/opencensus-core/src/common/monitored-resource/aws-identity-document-utils.ts b/packages/opencensus-core/src/common/monitored-resource/aws-identity-document-utils.ts index 00e9df67f..8aa5a2e98 100644 --- a/packages/opencensus-core/src/common/monitored-resource/aws-identity-document-utils.ts +++ b/packages/opencensus-core/src/common/monitored-resource/aws-identity-document-utils.ts @@ -17,6 +17,7 @@ import {get} from 'http'; import * as logger from '../../common/console-logger'; import * as loggerTypes from '../../common/types'; +import {monitoredResourceAttributes} from './types'; /** Util methods for getting and parsing AWS instance identity document. */ export class AwsIdentityDocumentUtils { @@ -41,8 +42,12 @@ export class AwsIdentityDocumentUtils { } AwsIdentityDocumentUtils.promise = AwsIdentityDocumentUtils.getDocument().then(metadata => { - if (Object.keys(metadata).length) { - AwsIdentityDocumentUtils.metadata = metadata; + const data: Record = {}; + Object.keys(monitoredResourceAttributes.AWS).forEach(key => { + data[key] = metadata[key]; + }); + if (Object.keys(data).length) { + AwsIdentityDocumentUtils.metadata = data; AwsIdentityDocumentUtils.runned = true; } return metadata;