@opentelemetry/resource-detector-gcp
Version:
OpenTelemetry SDK resource detector for GCP
177 lines • 6.92 kB
JavaScript
/*
* Copyright 2022 Google LLC
* 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 { context } from '@opentelemetry/api';
import { suppressTracing } from '@opentelemetry/core';
import { CLOUDPLATFORMVALUES_GCP_APP_ENGINE, CLOUDPLATFORMVALUES_GCP_CLOUD_FUNCTIONS, CLOUDPLATFORMVALUES_GCP_CLOUD_RUN, CLOUDPLATFORMVALUES_GCP_COMPUTE_ENGINE, CLOUDPLATFORMVALUES_GCP_KUBERNETES_ENGINE, CLOUDPROVIDERVALUES_GCP, SEMRESATTRS_CLOUD_ACCOUNT_ID, SEMRESATTRS_CLOUD_AVAILABILITY_ZONE, SEMRESATTRS_CLOUD_PLATFORM, SEMRESATTRS_CLOUD_PROVIDER, SEMRESATTRS_CLOUD_REGION, SEMRESATTRS_FAAS_INSTANCE, SEMRESATTRS_FAAS_NAME, SEMRESATTRS_FAAS_VERSION, SEMRESATTRS_HOST_ID, SEMRESATTRS_HOST_NAME, SEMRESATTRS_HOST_TYPE, SEMRESATTRS_K8S_CLUSTER_NAME, } from '@opentelemetry/semantic-conventions';
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 = [
SEMRESATTRS_CLOUD_PLATFORM,
SEMRESATTRS_CLOUD_AVAILABILITY_ZONE,
SEMRESATTRS_CLOUD_REGION,
SEMRESATTRS_K8S_CLUSTER_NAME,
SEMRESATTRS_HOST_TYPE,
SEMRESATTRS_HOST_ID,
SEMRESATTRS_HOST_NAME,
SEMRESATTRS_CLOUD_PROVIDER,
SEMRESATTRS_CLOUD_ACCOUNT_ID,
SEMRESATTRS_FAAS_NAME,
SEMRESATTRS_FAAS_VERSION,
SEMRESATTRS_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({
[]: CLOUDPLATFORMVALUES_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({
[]: CLOUDPLATFORMVALUES_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({
[]: CLOUDPLATFORMVALUES_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({
[]: CLOUDPLATFORMVALUES_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({
[]: CLOUDPLATFORMVALUES_GCP_COMPUTE_ENGINE,
[]: zoneAndRegion.zone,
[]: zoneAndRegion.region,
[]: hostType,
[]: hostId,
[]: hostName,
});
}
async function makeResource(attrs) {
const project = await metadata.project('project-id');
return resourceFromAttributes({
[]: CLOUDPROVIDERVALUES_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