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 { Resource } = require('@opentelemetry/resources')
const {
  envDetector,
  processDetector,
  osDetector,
  hostDetector,
} = require('@opentelemetry/resources')

const sdk = new NodeSDK({
  resource: Resource.createDefault().merge(
    new Resource({
      '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=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 { Resource } = require('@opentelemetry/resources')
const {
  envDetector,
  processDetector,
  osDetector,
  hostDetector,
} = require('@opentelemetry/resources')

const sdk = new NodeSDK({
  resource: Resource.createDefault().merge(
    new Resource({
      'service.name': 'user-api',
      'service.version': '1.2.0',
      'deployment.environment': '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 { Resource } = from '@opentelemetry/resources'
import { WebTracerProvider } from '@opentelemetry/sdk-trace-web'

const resource = new Resource({
  '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 { detectResources } = require('@opentelemetry/resources')
const {
  awsEc2Detector,
  awsEcsDetector,
  awsEksDetector,
  awsLambdaDetector,
} = require('@opentelemetry/resource-detector-aws')

// Detect resources first
const resource = await detectResources({
  detectors: [
    awsEc2Detector,
    awsEcsDetector,
    awsEksDetector,
    awsLambdaDetector,
  ],
})

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

await 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 { detectResources } = require('@opentelemetry/resources')
const { gcpDetector } = require('@opentelemetry/resource-detector-gcp')

// Detect resources first
const resource = await detectResources({
  detectors: [gcpDetector],
})

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

await 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 customAzureResource = new Resource({
  '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: Resource.createDefault().merge(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 { detectResources } = require('@opentelemetry/resources')
const {
  containerDetector,
} = require('@opentelemetry/resource-detector-container')

// Detect resources first
const resource = await detectResources({
  detectors: [containerDetector],
})

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

await 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 Detector interface:

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

class CustomDetector {
  async detect() {
    return new Resource({
      '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'
  }
}

// Usage with detectResources
async function initializeSDK() {
  const customDetector = new CustomDetector()

  const resource = await detectResources({
    detectors: [envDetector, processDetector, customDetector],
  })

  const sdk = new NodeSDK({
    resource: resource,
  })

  await sdk.start()
}

initializeSDK()

Advanced custom detector

Create more sophisticated custom detectors with async detection:

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

class KubernetesDetector {
  async detect() {
    try {
      // Check if running in Kubernetes
      const namespaceFile =
        '/var/run/secrets/kubernetes.io/serviceaccount/namespace'
      const namespace = await fs.readFile(namespaceFile, 'utf8')

      return new Resource({
        'k8s.namespace.name': namespace.trim(),
        'k8s.pod.name': process.env.HOSTNAME || 'unknown',
        'k8s.cluster.name': process.env.CLUSTER_NAME || 'unknown',
      })
    } catch (error) {
      // Not running in Kubernetes
      return Resource.empty()
    }
  }
}

// Usage with async detection
async function initializeSDK() {
  const k8sDetector = new KubernetesDetector()

  const resource = await detectResources({
    detectors: [envDetector, processDetector, k8sDetector],
  })

  const sdk = new NodeSDK({
    resource: resource,
  })

  await sdk.start()
}

initializeSDK()

Manual attributes

Add custom attributes directly to resources:

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

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

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

sdk.start()

Resource merging and precedence

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

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

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

// Environment-specific overrides
const envResource = new Resource({
  'service.name': process.env.SERVICE_NAME || 'default-service',
  'service.version': process.env.SERVICE_VERSION || '0.0.0',
  'deployment.environment': 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

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?