@opentelemetry/resource-detector-gcp
Version:
OpenTelemetry SDK resource detector for GCP
166 lines • 6.01 kB
JavaScript
/*
* Copyright The OpenTelemetry Authors
* Copyright 2022 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import { context } from '@opentelemetry/api';
import { suppressTracing } from '@opentelemetry/core';
import { CLOUD_PLATFORM_VALUE_GCP_APP_ENGINE, CLOUD_PLATFORM_VALUE_GCP_CLOUD_FUNCTIONS, CLOUD_PLATFORM_VALUE_GCP_CLOUD_RUN, CLOUD_PLATFORM_VALUE_GCP_COMPUTE_ENGINE, CLOUD_PLATFORM_VALUE_GCP_KUBERNETES_ENGINE, CLOUD_PROVIDER_VALUE_GCP, ATTR_CLOUD_ACCOUNT_ID, ATTR_CLOUD_AVAILABILITY_ZONE, ATTR_CLOUD_PLATFORM, ATTR_CLOUD_PROVIDER, ATTR_CLOUD_REGION, ATTR_FAAS_INSTANCE, ATTR_FAAS_NAME, ATTR_FAAS_VERSION, ATTR_HOST_ID, ATTR_HOST_NAME, ATTR_HOST_TYPE, ATTR_K8S_CLUSTER_NAME, } from '../semconv';
import { emptyResource, resourceFromAttributes, } from '@opentelemetry/resources';
import * as metadata from 'gcp-metadata';
import * as faas from './faas';
import * as gae from './gae';
import * as gce from './gce';
import * as gke from './gke';
const ATTRIBUTE_NAMES = [
ATTR_CLOUD_PLATFORM,
ATTR_CLOUD_AVAILABILITY_ZONE,
ATTR_CLOUD_REGION,
ATTR_K8S_CLUSTER_NAME,
ATTR_HOST_TYPE,
ATTR_HOST_ID,
ATTR_HOST_NAME,
ATTR_CLOUD_PROVIDER,
ATTR_CLOUD_ACCOUNT_ID,
ATTR_FAAS_NAME,
ATTR_FAAS_VERSION,
ATTR_FAAS_INSTANCE,
];
async function detect() {
if (!(await metadata.isAvailable())) {
return emptyResource();
}
// Note the order of these if checks is significant with more specific resources coming
// first. E.g. Cloud Functions gen2 are executed in Cloud Run so it must be checked first.
if (await gke.onGke()) {
return await gkeResource();
}
else if (await faas.onCloudFunctions()) {
return await cloudFunctionsResource();
}
else if (await faas.onCloudRun()) {
return await cloudRunResource();
}
else if (await gae.onAppEngine()) {
return await gaeResource();
}
else if (await gce.onGce()) {
return await gceResource();
}
return emptyResource();
}
async function gkeResource() {
const [zoneOrRegion, k8sClusterName, hostId] = await Promise.all([
gke.availabilityZoneOrRegion(),
gke.clusterName(),
gke.hostId(),
]);
return await makeResource({
[]: CLOUD_PLATFORM_VALUE_GCP_KUBERNETES_ENGINE,
[]: zoneOrRegion.value,
[]: k8sClusterName,
[]: hostId,
});
}
async function cloudRunResource() {
const [faasName, faasVersion, faasInstance, faasCloudRegion] = await Promise.all([
faas.faasName(),
faas.faasVersion(),
faas.faasInstance(),
faas.faasCloudRegion(),
]);
return await makeResource({
[]: CLOUD_PLATFORM_VALUE_GCP_CLOUD_RUN,
[]: faasName,
[]: faasVersion,
[]: faasInstance,
[]: faasCloudRegion,
});
}
async function cloudFunctionsResource() {
const [faasName, faasVersion, faasInstance, faasCloudRegion] = await Promise.all([
faas.faasName(),
faas.faasVersion(),
faas.faasInstance(),
faas.faasCloudRegion(),
]);
return await makeResource({
[]: CLOUD_PLATFORM_VALUE_GCP_CLOUD_FUNCTIONS,
[]: faasName,
[]: faasVersion,
[]: faasInstance,
[]: faasCloudRegion,
});
}
async function gaeResource() {
let zone, region;
if (await gae.onAppEngineStandard()) {
[] = await Promise.all([
gae.standardAvailabilityZone(),
gae.standardCloudRegion(),
]);
}
else {
({ zone, region } = await gce.availabilityZoneAndRegion());
}
const [faasName, faasVersion, faasInstance] = await Promise.all([
gae.serviceName(),
gae.serviceVersion(),
gae.serviceInstance(),
]);
return await makeResource({
[]: CLOUD_PLATFORM_VALUE_GCP_APP_ENGINE,
[]: faasName,
[]: faasVersion,
[]: faasInstance,
[]: zone,
[]: region,
});
}
async function gceResource() {
const [zoneAndRegion, hostType, hostId, hostName] = await Promise.all([
gce.availabilityZoneAndRegion(),
gce.hostType(),
gce.hostId(),
gce.hostName(),
]);
return await makeResource({
[]: CLOUD_PLATFORM_VALUE_GCP_COMPUTE_ENGINE,
[]: zoneAndRegion.zone,
[]: zoneAndRegion.region,
[]: hostType,
[]: hostId,
[]: hostName,
});
}
async function makeResource(attrs) {
const project = await metadata.project('project-id');
return resourceFromAttributes({
[]: CLOUD_PROVIDER_VALUE_GCP,
[]: project,
...attrs,
});
}
/**
* Google Cloud resource detector which populates attributes based on the environment this
* process is running in. If not on GCP, returns an empty resource.
*/
export class GcpDetector {
async _asyncAttributes() {
const resource = await context.with(suppressTracing(context.active()), detect);
return resource.attributes;
}
detect() {
const asyncAttributes = this._asyncAttributes();
const attributes = {};
ATTRIBUTE_NAMES.forEach(name => {
// Each resource attribute is determined asynchronously in _gatherData().
attributes[name] = asyncAttributes.then(data => data[name]);
});
return { attributes };
}
}
export const gcpDetector = new GcpDetector();
//# sourceMappingURL=GcpDetector.js.map