@azure/monitor-opentelemetry
Version:
Azure Monitor OpenTelemetry (Node.js)
249 lines • 10.8 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getRequestDimensions = getRequestDimensions;
exports.getDependencyDimensions = getDependencyDimensions;
exports.getExceptionDimensions = getExceptionDimensions;
exports.getTraceDimensions = getTraceDimensions;
exports.getBaseDimensions = getBaseDimensions;
exports.getDependencyTarget = getDependencyTarget;
exports.isSqlDB = isSqlDB;
exports.isExceptionTelemetry = isExceptionTelemetry;
exports.isTraceTelemetry = isTraceTelemetry;
exports.isSyntheticLoad = isSyntheticLoad;
exports.convertDimensions = convertDimensions;
exports.getPhysicalMemory = getPhysicalMemory;
exports.getProcessorTimeNormalized = getProcessorTimeNormalized;
exports.getProcessorTime = getProcessorTime;
exports.getCloudRole = getCloudRole;
exports.getCloudRoleInstance = getCloudRoleInstance;
const tslib_1 = require("tslib");
const api_1 = require("@opentelemetry/api");
const semantic_conventions_1 = require("@opentelemetry/semantic-conventions");
const types_js_1 = require("./types.js");
const utils_js_1 = require("./quickpulse/utils.js");
const logger_js_1 = require("../shared/logging/logger.js");
const os = tslib_1.__importStar(require("node:os"));
const process = tslib_1.__importStar(require("node:process"));
function getRequestDimensions(span) {
const dimensions = getBaseDimensions(span.resource);
dimensions.metricId = types_js_1.StandardMetricIds.REQUEST_DURATION;
const statusCode = String((0, utils_js_1.getHttpStatusCode)(span.attributes));
dimensions.requestResultCode = statusCode;
// OTel treats 4xx request responses as UNSET SpanStatusCode, but we should count them as failed
dimensions.requestSuccess =
span.status.code !== api_1.SpanStatusCode.ERROR && (Number(statusCode) || 0) < 400 ? "True" : "False";
if (isSyntheticLoad(span)) {
dimensions.operationSynthetic = "True";
}
return convertDimensions(dimensions);
}
function getDependencyDimensions(span) {
const dimensions = getBaseDimensions(span.resource);
dimensions.metricId = types_js_1.StandardMetricIds.DEPENDENCIES_DURATION;
const statusCode = String((0, utils_js_1.getHttpStatusCode)(span.attributes));
dimensions.dependencyTarget = getDependencyTarget(span.attributes);
dimensions.dependencyResultCode = statusCode;
dimensions.dependencyType = "http";
dimensions.dependencySuccess = span.status.code !== api_1.SpanStatusCode.ERROR ? "True" : "False";
if (isSyntheticLoad(span)) {
dimensions.operationSynthetic = "True";
}
return convertDimensions(dimensions);
}
function getExceptionDimensions(resource) {
const dimensions = getBaseDimensions(resource);
dimensions.metricId = types_js_1.StandardMetricIds.EXCEPTIONS_COUNT;
return dimensions;
}
function getTraceDimensions(resource) {
const dimensions = getBaseDimensions(resource);
dimensions.metricId = types_js_1.StandardMetricIds.TRACES_COUNT;
return dimensions;
}
function getBaseDimensions(resource) {
const dimensions = {};
dimensions.IsAutocollected = "True";
if (resource) {
dimensions.cloudRoleName = getCloudRole(resource);
dimensions.cloudRoleInstance = getCloudRoleInstance(resource);
}
return dimensions;
}
// Get metric dependency target, avoiding high cardinality.
function getDependencyTarget(attributes) {
if (!attributes) {
return "";
}
const peerService = attributes[semantic_conventions_1.SEMATTRS_PEER_SERVICE];
const hostPort = (0, utils_js_1.getNetHostPort)(attributes);
const netPeerName = (0, utils_js_1.getNetPeerName)(attributes);
if (peerService) {
return String(peerService);
}
else if (hostPort && netPeerName) {
return `${netPeerName}:${hostPort}`;
}
else if (netPeerName) {
return String(netPeerName);
}
return "";
}
function isSqlDB(dbSystem) {
return (dbSystem === semantic_conventions_1.DBSYSTEMVALUES_DB2 ||
dbSystem === semantic_conventions_1.DBSYSTEMVALUES_DERBY ||
dbSystem === semantic_conventions_1.DBSYSTEMVALUES_MARIADB ||
dbSystem === semantic_conventions_1.DBSYSTEMVALUES_MSSQL ||
dbSystem === semantic_conventions_1.DBSYSTEMVALUES_ORACLE ||
dbSystem === semantic_conventions_1.DBSYSTEMVALUES_SQLITE ||
dbSystem === semantic_conventions_1.DBSYSTEMVALUES_OTHER_SQL ||
dbSystem === semantic_conventions_1.DBSYSTEMVALUES_HSQLDB ||
dbSystem === semantic_conventions_1.DBSYSTEMVALUES_H2);
}
function isExceptionTelemetry(logRecord) {
const baseType = logRecord.attributes["_MS.baseType"];
// If Application Insights Legacy logs
if (baseType && baseType === "ExceptionData") {
return true;
}
else if (logRecord.attributes[semantic_conventions_1.SEMATTRS_EXCEPTION_MESSAGE] ||
logRecord.attributes[semantic_conventions_1.SEMATTRS_EXCEPTION_TYPE]) {
return true;
}
return false;
}
function isTraceTelemetry(logRecord) {
const baseType = logRecord.attributes["_MS.baseType"];
// If Application Insights Legacy logs
if (baseType && baseType === "MessageData") {
return true;
}
else if (!logRecord.attributes[semantic_conventions_1.SEMATTRS_EXCEPTION_MESSAGE] &&
!logRecord.attributes[semantic_conventions_1.SEMATTRS_EXCEPTION_TYPE]) {
return true;
}
return false;
}
function isSyntheticLoad(record) {
// eslint-disable-next-line @typescript-eslint/no-base-to-string
const userAgent = String((0, utils_js_1.getUserAgent)(record.attributes));
return userAgent !== null && userAgent.includes("AlwaysOn") ? true : false;
}
function convertDimensions(dimensions) {
const convertedDimensions = {};
for (const dim in dimensions) {
convertedDimensions[types_js_1.StandardMetricPropertyNames[dim]] = dimensions[dim];
}
return convertedDimensions;
}
// to get physical memory bytes
function getPhysicalMemory() {
if (process === null || process === void 0 ? void 0 : process.memoryUsage) {
return process.memoryUsage.rss();
}
else {
logger_js_1.Logger.getInstance().debug("process.memoryUsage is not available");
return 0;
}
}
// This function can get the normalized cpu, but it assumes that after this function is called,
// that the process.hrtime.bigint() & process.cpuUsage() are called/stored to be used as the
// parameters for the next call.
function getProcessorTimeNormalized(lastHrTime, lastCpuUsage) {
let numCpus = os.cpus().length;
const usageDif = process.cpuUsage(lastCpuUsage);
const elapsedTimeNs = process.hrtime.bigint() - lastHrTime;
const usageDifMs = (usageDif.user + usageDif.system) / 1000.0;
const elapsedTimeMs = elapsedTimeNs === BigInt(0) ? 1 : Number(elapsedTimeNs) / 1000000.0;
// just for division safety, don't know a case in which this would actually happen
numCpus = numCpus === 0 ? 1 : numCpus;
return (usageDifMs / elapsedTimeMs / numCpus) * 100;
}
// This function can get the cpu %, but it assumes that after this function is called,
// that the process.hrtime.bigint() & process.cpuUsage() are called/stored to be used as the
// parameters for the next call.
function getProcessorTime(lastHrTime, lastCpuUsage) {
if (process === null || process === void 0 ? void 0 : process.cpuUsage) {
const usageDif = process.cpuUsage(lastCpuUsage);
const elapsedTimeNs = process.hrtime.bigint() - lastHrTime;
const usageDifMs = (usageDif.user + usageDif.system) / 1000.0;
const elapsedTimeMs = elapsedTimeNs === BigInt(0) ? 1 : Number(elapsedTimeNs) / 1000000.0;
return (usageDifMs / elapsedTimeMs) * 100;
}
else {
logger_js_1.Logger.getInstance().debug("process.cpuUsage is not available");
return 0;
}
}
/**
* Gets the cloud role name based on the resource attributes
*/
function getCloudRole(resource) {
let cloudRole = "";
// Service attributes
const serviceName = resource.attributes[semantic_conventions_1.SEMRESATTRS_SERVICE_NAME];
const serviceNamespace = resource.attributes[semantic_conventions_1.SEMRESATTRS_SERVICE_NAMESPACE];
if (serviceName) {
// Custom Service name provided by customer is highest precedence
if (!String(serviceName).startsWith("unknown_service")) {
if (serviceNamespace) {
return `${serviceNamespace}.${serviceName}`;
}
else {
return String(serviceName);
}
}
else {
// Service attributes will be only used if K8S attributes are not present
if (serviceNamespace) {
cloudRole = `${serviceNamespace}.${serviceName}`;
}
else {
cloudRole = String(serviceName);
}
}
}
// Kubernetes attributes should take precedence
const kubernetesDeploymentName = resource.attributes[semantic_conventions_1.SEMRESATTRS_K8S_DEPLOYMENT_NAME];
if (kubernetesDeploymentName) {
return String(kubernetesDeploymentName);
}
const kuberneteReplicasetName = resource.attributes[semantic_conventions_1.SEMRESATTRS_K8S_REPLICASET_NAME];
if (kuberneteReplicasetName) {
return String(kuberneteReplicasetName);
}
const kubernetesStatefulSetName = resource.attributes[semantic_conventions_1.SEMRESATTRS_K8S_STATEFULSET_NAME];
if (kubernetesStatefulSetName) {
return String(kubernetesStatefulSetName);
}
const kubernetesJobName = resource.attributes[semantic_conventions_1.SEMRESATTRS_K8S_JOB_NAME];
if (kubernetesJobName) {
return String(kubernetesJobName);
}
const kubernetesCronjobName = resource.attributes[semantic_conventions_1.SEMRESATTRS_K8S_CRONJOB_NAME];
if (kubernetesCronjobName) {
return String(kubernetesCronjobName);
}
const kubernetesDaemonsetName = resource.attributes[semantic_conventions_1.SEMRESATTRS_K8S_DAEMONSET_NAME];
if (kubernetesDaemonsetName) {
return String(kubernetesDaemonsetName);
}
return cloudRole;
}
/**
* Gets the cloud role instance based on the resource attributes
*/
function getCloudRoleInstance(resource) {
// Kubernetes attributes should take precedence
const kubernetesPodName = resource.attributes[semantic_conventions_1.SEMRESATTRS_K8S_POD_NAME];
if (kubernetesPodName) {
return String(kubernetesPodName);
}
// Service attributes
const serviceInstanceId = resource.attributes[semantic_conventions_1.SEMRESATTRS_SERVICE_INSTANCE_ID];
if (serviceInstanceId) {
return String(serviceInstanceId);
}
// Default
return os && os.hostname();
}
//# sourceMappingURL=utils.js.map