Resource Detectors in OpenTelemetry JavaScript

Resource detectors automatically detect and collect information about the environment in which your application is running. This information is attached to telemetry data (traces, metrics, and logs) to provide additional context for monitoring and debugging.

OpenTelemetry JavaScript provides several built-in resource detectors, and you can create custom detectors to gather application-specific information.

By default, OpenTelemetry JavaScript uses basic resource detection, but you can configure additional detectors:

js
const { NodeSDK } = require('@opentelemetry/sdk-node')
const {
  resourceFromAttributes,
  envDetector,
  processDetector,
  osDetector,
  hostDetector,
} = require('@opentelemetry/resources')

const sdk = new NodeSDK({
  resource: resourceFromAttributes({
    'service.name': 'my-service',
    'service.version': '1.0.0',
  }),
  resourceDetectors: [envDetector, processDetector, osDetector, hostDetector],
})

sdk.start()

Built-in detectors

Environment Variable Detector

Detects resource attributes from OTEL_RESOURCE_ATTRIBUTES and OTEL_SERVICE_NAME environment variables.

js
const { envDetector } = require('@opentelemetry/resources')

// Use in resource detectors array
resourceDetectors: [envDetector]

Environment variables:

bash
export OTEL_SERVICE_NAME="user-api"
export OTEL_RESOURCE_ATTRIBUTES="service.version=1.2.0,deployment.environment.name=production"

Process Detector

Detects process-related attributes like PID, executable name, and command line arguments.

js
const { processDetector } = require('@opentelemetry/resources')

resourceDetectors: [processDetector]

Detected attributes:

  • process.pid - Process ID
  • process.executable.name - Executable name
  • process.executable.path - Executable path
  • process.command_line - Command line arguments
  • process.command_args - Command arguments array

OS Detector

Detects operating system information.

js
const { osDetector } = require('@opentelemetry/resources')

resourceDetectors: [osDetector]

Detected attributes:

  • os.type - Operating system type (e.g., linux, darwin, win32)
  • os.description - OS description
  • os.name - OS name
  • os.version - OS version

Host Detector

Detects host-related information.

js
const { hostDetector } = require('@opentelemetry/resources')

resourceDetectors: [hostDetector]

Detected attributes:

  • host.name - Hostname
  • host.arch - Host architecture

Node.js integration

js
const { NodeSDK } = require('@opentelemetry/sdk-node')
const {
  resourceFromAttributes,
  envDetector,
  processDetector,
  osDetector,
  hostDetector,
} = require('@opentelemetry/resources')
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http')

const sdk = new NodeSDK({
  resource: resourceFromAttributes({
    'service.name': 'user-api',
    'service.version': '1.2.0',
    'deployment.environment.name': 'production',
  }),
  resourceDetectors: [envDetector, processDetector, osDetector, hostDetector],
  traceExporter: new OTLPTraceExporter({
    url: 'https://api.uptrace.dev/v1/traces',
    headers: { 'uptrace-dsn': process.env.UPTRACE_DSN },
  }),
})

sdk.start()

Browser integration

For browser applications, resource detection is more limited due to security restrictions:

js
import { resourceFromAttributes } from '@opentelemetry/resources'
import { WebTracerProvider } from '@opentelemetry/sdk-trace-web'

const resource = resourceFromAttributes({
  'service.name': 'web-app',
  'service.version': '1.0.0',
  'browser.name': navigator.userAgent,
  'browser.language': navigator.language,
  'browser.platform': navigator.platform,
})

const provider = new WebTracerProvider({
  resource: resource,
})

Cloud detectors

AWS

For AWS environments, install the AWS detector package:

shell
npm install @opentelemetry/resource-detector-aws
js
const { envDetector, processDetector } = require('@opentelemetry/resources')
const {
  awsEc2Detector,
  awsEcsDetector,
  awsEksDetector,
  awsLambdaDetector,
} = require('@opentelemetry/resource-detector-aws')

const sdk = new NodeSDK({
  resourceDetectors: [
    envDetector,
    processDetector,
    awsEc2Detector,
    awsEcsDetector,
    awsEksDetector,
    awsLambdaDetector,
  ],
  traceExporter: new OTLPTraceExporter({
    url: 'https://api.uptrace.dev/v1/traces',
    headers: { 'uptrace-dsn': process.env.UPTRACE_DSN },
  }),
})

sdk.start()

Detected AWS attributes:

  • cloud.provider - AWS
  • cloud.platform - EC2, ECS, EKS, Lambda
  • cloud.region - AWS region
  • cloud.availability_zone - Availability zone
  • host.id - Instance ID
  • container.id - Container ID (ECS/EKS)
  • k8s.cluster.name - EKS cluster name

Google Cloud Platform

For GCP environments, install the GCP detector package:

shell
npm install @opentelemetry/resource-detector-gcp

Note: This detector requires Node.js 18.19+ due to dependencies that use modern Node.js features.

js
const { envDetector, processDetector } = require('@opentelemetry/resources')
const { gcpDetector } = require('@opentelemetry/resource-detector-gcp')

const sdk = new NodeSDK({
  resourceDetectors: [envDetector, processDetector, gcpDetector],
  traceExporter: new OTLPTraceExporter({
    url: 'https://api.uptrace.dev/v1/traces',
    headers: { 'uptrace-dsn': process.env.UPTRACE_DSN },
  }),
})

sdk.start()

Azure

Note: Azure resource detectors are not currently available as standalone packages in the OpenTelemetry JavaScript ecosystem. For Azure environments, use environment variables or custom detectors to add Azure-specific resource attributes:

js
const {
  resourceFromAttributes,
  envDetector,
  processDetector,
} = require('@opentelemetry/resources')

const customAzureResource = resourceFromAttributes({
  'cloud.provider': 'azure',
  'cloud.platform': process.env.AZURE_PLATFORM || 'azure_vm',
  'cloud.region': process.env.AZURE_REGION,
  'azure.vm.name': process.env.COMPUTERNAME,
  'azure.resource_group': process.env.AZURE_RESOURCE_GROUP,
})

const sdk = new NodeSDK({
  resource: customAzureResource,
  resourceDetectors: [envDetector, processDetector],
})

sdk.start()

Container detectors

Docker

For Docker environments, install the container detector:

shell
npm install @opentelemetry/resource-detector-container
js
const { envDetector, processDetector } = require('@opentelemetry/resources')
const {
  containerDetector,
} = require('@opentelemetry/resource-detector-container')

const sdk = new NodeSDK({
  resourceDetectors: [envDetector, processDetector, containerDetector],
})

sdk.start()

Detected container attributes:

  • container.name - Container name
  • container.id - Container ID
  • container.image.name - Image name
  • container.image.tag - Image tag

Custom resource detector

Create custom detectors by implementing the ResourceDetector interface. The detect() method is synchronous and returns an object with an attributes map:

js
const { envDetector, processDetector } = require('@opentelemetry/resources')

class CustomDetector {
  detect() {
    return {
      attributes: {
        'deployment.datacenter': this.getDataCenter(),
        'application.team': 'platform',
        'application.owner': process.env.APP_OWNER || 'unknown',
        'git.commit.sha': process.env.GIT_COMMIT || 'unknown',
      },
    }
  }

  getDataCenter() {
    return process.env.DATACENTER || 'unknown'
  }
}

const sdk = new NodeSDK({
  resourceDetectors: [envDetector, processDetector, new CustomDetector()],
})

sdk.start()

Advanced custom detector

For values that require async work, return a promise for the attribute value. The SDK resolves it before exporting, and attributes that resolve to undefined are dropped:

js
const { envDetector, processDetector } = require('@opentelemetry/resources')
const fs = require('fs').promises

const namespaceFile = '/var/run/secrets/kubernetes.io/serviceaccount/namespace'

class KubernetesDetector {
  detect() {
    // Resolves to undefined when not running in Kubernetes.
    const namespace = fs
      .readFile(namespaceFile, 'utf8')
      .then((ns) => ns.trim())
      .catch(() => undefined)

    return {
      attributes: {
        'k8s.namespace.name': namespace,
        'k8s.pod.name': namespace.then((ns) =>
          ns ? process.env.HOSTNAME : undefined,
        ),
        'k8s.cluster.name': namespace.then((ns) =>
          ns ? process.env.CLUSTER_NAME : undefined,
        ),
      },
    }
  }
}

const sdk = new NodeSDK({
  resourceDetectors: [envDetector, processDetector, new KubernetesDetector()],
})

sdk.start()

Manual attributes

Add custom attributes directly to resources:

js
const {
  resourceFromAttributes,
  envDetector,
  processDetector,
} = require('@opentelemetry/resources')

const customResource = resourceFromAttributes({
  'host.name': require('os').hostname(),
  'process.pid': process.pid,
  'deployment.environment.name': process.env.NODE_ENV || 'development',
  'service.namespace': 'user-services',
  'service.instance.id': `${require('os').hostname()}-${process.pid}`,
})

const sdk = new NodeSDK({
  resource: customResource,
  resourceDetectors: [envDetector, processDetector],
})

sdk.start()

Resource merging and precedence

Resources are merged in order, with later resources taking precedence:

js
const {
  resourceFromAttributes,
  envDetector,
  processDetector,
} = require('@opentelemetry/resources')

// Base resource (lowest precedence)
const baseResource = resourceFromAttributes({
  'service.name': 'default-service',
  'service.version': '0.0.0',
  'deployment.environment.name': 'development',
})

// Environment-specific overrides
const envResource = resourceFromAttributes({
  'service.name': process.env.SERVICE_NAME || 'default-service',
  'service.version': process.env.SERVICE_VERSION || '0.0.0',
  'deployment.environment.name': process.env.NODE_ENV || 'development',
})

// Final resource with precedence
const finalResource = baseResource.merge(envResource)

const sdk = new NodeSDK({
  resource: finalResource,
  resourceDetectors: [envDetector, processDetector],
})

sdk.start()

Querying resource data

Once your application is instrumented with resource detectors, you can use resource attributes in Uptrace for:

Identification and filtering

  • Service topology: Visualize services using service.name and service.namespace
  • Version tracking: Monitor deployments using service.version
  • Environment separation: Filter by deployment.environment.name

Infrastructure monitoring

  • Host analysis: Group metrics by host.name and os.type
  • Container insights: Track containers using container.name and container.id
  • Cloud resource tracking: Monitor cloud instances using cloud.provider and cloud.region

Deployment and debugging

  • Rollback identification: Track issues using git.commit.sha
  • Team ownership: Route alerts using application.team
  • Process debugging: Identify issues using process.pid and process.command_line

What's next?