From 33c57cc84a8b87ad3a58dde2014738deab1c375b Mon Sep 17 00:00:00 2001 From: Matthew Wear Date: Wed, 8 Feb 2023 00:33:46 -0800 Subject: [PATCH] feat(detector-gcp): collect hostname resource attribute from GCP Metadata API (#1364) * feat: collect hostname resource attribute from GCP Metadata API * chore: remove unneeded changelog entry --------- Co-authored-by: Amir Blum --- .../src/detectors/GcpDetector.ts | 24 ++++++++++++++----- .../test/detectors/GcpDetector.test.ts | 18 ++++++++++---- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/detectors/node/opentelemetry-resource-detector-gcp/src/detectors/GcpDetector.ts b/detectors/node/opentelemetry-resource-detector-gcp/src/detectors/GcpDetector.ts index 1d4139d70..080bbc02e 100644 --- a/detectors/node/opentelemetry-resource-detector-gcp/src/detectors/GcpDetector.ts +++ b/detectors/node/opentelemetry-resource-detector-gcp/src/detectors/GcpDetector.ts @@ -52,16 +52,19 @@ class GcpDetector implements Detector { return Resource.empty(); } - const [projectId, instanceId, zoneId, clusterName] = await Promise.all([ - this._getProjectId(), - this._getInstanceId(), - this._getZone(), - this._getClusterName(), - ]); + const [projectId, instanceId, zoneId, clusterName, hostname] = + await Promise.all([ + this._getProjectId(), + this._getInstanceId(), + this._getZone(), + this._getClusterName(), + this._getHostname(), + ]); const attributes: ResourceAttributes = {}; attributes[SemanticResourceAttributes.CLOUD_ACCOUNT_ID] = projectId; attributes[SemanticResourceAttributes.HOST_ID] = instanceId; + attributes[SemanticResourceAttributes.HOST_NAME] = hostname; attributes[SemanticResourceAttributes.CLOUD_AVAILABILITY_ZONE] = zoneId; attributes[SemanticResourceAttributes.CLOUD_PROVIDER] = CloudProviderValues.GCP; @@ -125,6 +128,15 @@ class GcpDetector implements Detector { return ''; } } + + /** Gets hostname from GCP instance metadata. */ + private async _getHostname(): Promise { + try { + return await gcpMetadata.instance('hostname'); + } catch { + return ''; + } + } } export const gcpDetector = new GcpDetector(); diff --git a/detectors/node/opentelemetry-resource-detector-gcp/test/detectors/GcpDetector.test.ts b/detectors/node/opentelemetry-resource-detector-gcp/test/detectors/GcpDetector.test.ts index ee1b59b4e..b101f76b6 100644 --- a/detectors/node/opentelemetry-resource-detector-gcp/test/detectors/GcpDetector.test.ts +++ b/detectors/node/opentelemetry-resource-detector-gcp/test/detectors/GcpDetector.test.ts @@ -42,6 +42,7 @@ 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'; (semver.satisfies(process.version, '>=10') ? describe : describe.skip)( 'gcpDetector', @@ -81,7 +82,9 @@ const CLUSTER_NAME_PATH = BASE_PATH + '/instance/attributes/cluster-name'; .get(ZONE_PATH) .reply(200, () => 'project/zone/my-zone', HEADERS) .get(CLUSTER_NAME_PATH) - .reply(404); + .reply(404) + .get(HOSTNAME_PATH) + .reply(200, () => 'dev.my-project.local', HEADERS); const secondaryScope = nock(SECONDARY_HOST_ADDRESS) .get(INSTANCE_PATH) .reply(200, {}, HEADERS); @@ -94,7 +97,10 @@ const CLUSTER_NAME_PATH = BASE_PATH + '/instance/attributes/cluster-name'; accountId: 'my-project-id', zone: 'my-zone', }); - assertHostResource(resource, { id: '4520031799277581759' }); + assertHostResource(resource, { + id: '4520031799277581759', + name: 'dev.my-project.local', + }); }); it('should populate K8s attributes when KUBERNETES_SERVICE_HOST is set', async () => { @@ -112,7 +118,9 @@ const CLUSTER_NAME_PATH = BASE_PATH + '/instance/attributes/cluster-name'; .get(PROJECT_ID_PATH) .reply(200, () => 'my-project-id', HEADERS) .get(ZONE_PATH) - .reply(200, () => 'project/zone/my-zone', HEADERS); + .reply(200, () => 'project/zone/my-zone', HEADERS) + .get(HOSTNAME_PATH) + .reply(200, () => 'dev.my-project.local', HEADERS); const secondaryScope = nock(SECONDARY_HOST_ADDRESS) .get(INSTANCE_PATH) .reply(200, {}, HEADERS); @@ -144,7 +152,9 @@ const CLUSTER_NAME_PATH = BASE_PATH + '/instance/attributes/cluster-name'; .get(INSTANCE_ID_PATH) .reply(400, undefined, HEADERS) .get(CLUSTER_NAME_PATH) - .reply(413); + .reply(413) + .get(HOSTNAME_PATH) + .reply(400, undefined, HEADERS); const secondaryScope = nock(SECONDARY_HOST_ADDRESS) .get(INSTANCE_PATH) .reply(200, {}, HEADERS);