Skip to content

OTTL profile context exposes profile.sample_type but provides no way to read its data #43723

@henrikrexed

Description

@henrikrexed

Component(s)

pkg/ottl

What happened?

Description

Version: v0.137.0 with service.profilesSupport feature gate

The OTTL profile context exposes profile.sample_type but the object is completely opaque - no form of access works.
All attempts fail:

# Returns Empty()
set(resource.attributes["type"], profile.sample_type)

# Error: "path section 'typ' was not used by the context"
set(resource.attributes["type"], profile.sample_type.typ)

# Error: "path section 'type' was not used by the context"  
set(resource.attributes["type"], profile.sample_type.type)

# Error: "keys indexing 'sample_type' were not used by the context"
set(resource.attributes["type"], profile.sample_type["typ"])

Steps to Reproduce

Deploy the profiler collector.

Architecture

Two-tier OpenTelemetry Collector setup:

  • DaemonSet collectors - receive profiles from eBPF profiler, forward to gateway
  • Gateway collector - receives profiles from DaemonSets, attempts to process with OTTL
    Minimal ConfigurationGateway Collector (otelcol-gateway.yaml):
receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317

processors:
  transform/test:
    error_mode: ignore
    profile_statements:
      - context: profile
        statements:
          # All of these fail to access sample_type data
          - set(resource.attributes["test1"], profile.sample_type)
          - set(resource.attributes["test2"], profile.sample_type.typ)
          - set(resource.attributes["test3"], profile.sample_type["typ"])

exporters:
  debug:
    verbosity: detailed

service:
  pipelines:
    profiles:
      receivers: [otlp]
      processors: [transform/test]
      exporters: [debug]

Expected Result

sample_type is a struct with fields Typ, Unit, and AggregationTemporality.
OTTL should expose these fields so users can differentiate CPU vs memory profiles.

For now Cannot use signaltometrics or transform processor to create separate metrics for CPU and memory profiles. The connector is unusable for profiling use cases that need type-based filtering.

Please expose sample_type.typ and sample_type.unit as readable fields in the OTTL profile context.

Collector version

v0.137.0

Environment information

Environment

Kubernetes v1.33.4

OpenTelemetry Collector configuration

receivers:

      otlp:
        protocols:
          grpc: {}
          http: {}

    processors:
      batch:
        send_batch_max_size: 1000
        timeout: 30s
        send_batch_size : 800

      memory_limiter:
        check_interval: 1s
        limit_percentage: 70
        spike_limit_percentage: 30


      k8sattributes/profile:
        auth_type: "serviceAccount"
        passthrough: false
        wait_for_metadata: true
        wait_for_metadata_timeout: 60s
        extract:
          metadata:
            - k8s.pod.name
            - k8s.pod.uid
            - k8s.deployment.name
            - k8s.namespace.name
            - k8s.statefulset.name
            - k8s.daemonset.name
            - k8s.cronjob.name
            - k8s.node.name
            - k8s.cluster.uid
          labels:
            - tag_name: app.label.component
              key: app.kubernetes.io/component
              from: pod
          otel_annotations: true
        pod_association:
          - sources:
              - from: resource_attribute
                name: container.id
              - from: resource_attribute
                name: k8s.node.name





      transform/fix_container_id:
        error_mode: ignore
        profile_statements:
          - context: resource
            statements:
              # Add containerd:// prefix if container.id exists and doesn't have it
              - set(attributes["container.id"], Concat(["containerd://", attributes["container.id"]], "")) where attributes["container.id"] != nil and not IsMatch(attributes["container.id"], "^(containerd|docker|cri-o)://")
              - set(attributes["k8s.node.name"], attributes["host.name"]) where attributes["host.name"] != nil
          - context: profile
            statements:
              # Extract the sample type (cpu, alloc_space, etc.)
              # Try accessing the TypeStrindex method
              - set(resource.attributes["profile.type_strindex"], profile.sample_type["typ"]) where profile.sample_type["typ"] != nil

              # Or try with camelCase
#              - set(resource.attributes["profile.type_strindex"], Int(profile.sample_type.TypeStrindex)) where profile.sample_type.TypeStrindex != nil




      
    connectors:
      signaltometrics:

        profiles:
          - name: profile.cpu.count
            description: "Number of CPU profile records per container"
            sum:
              value: "1"  # Just count each profile
            attributes:
              - key: container.short_id
              - key: k8s.node.name
            conditions:
              - 'resource.attributes["profile.type_strindex"] == 1'
          - name: profile.memory.inuse.count
            description: "Number of CPU profile records per container"
            sum:
              value: "1"  # Just count each profile
            attributes:
              - key: container.short_id
              - key: k8s.node.name
            conditions:
              - 'resource.attributes["profile.type_strindex"] == 3'
          - name: profile.memory.alloc.count
            description: "Number of CPU profile records per container"
            sum:
              value: "1"  # Just count each profile
            attributes:
              - key: container.short_id
              - key: k8s.node.name
            conditions:
              - 'resource.attributes["profile.type_strindex"] == 5'
    exporters:


      otlphttp:
        endpoint: ${DT_ENDPOINT}/api/v2/otlp
        headers:
          Authorization: "Api-Token ${DT_API_TOKEN}"
      debug:
        verbosity: detailed

    service:
      pipelines:

       
        profiles:
          receivers: [ otlp ]
          processors: [ memory_limiter, transform/fix_container_id, k8sattributes/profile ]
          exporters: [ signaltometrics,debug ]
        metrics/profile:
          receivers: [ signaltometrics ]
          processors: [ memory_limiter,filter,cumulativetodelta,batch ]
          exporters: [otlphttp,debug]
      telemetry:
        logs:
          level: info
          initial_fields:
            service: otelcol

Log output

Error: invalid configuration: processors::transform/fix_container_id: unable to parse OTTL statement "set(resource.attributes[\"profile.type_strindex\"], profile.sample_type[\"typ\"]) where profile.sample_type[\"typ\"] != nil": error while parsing arguments for call to "set": invalid argument at position 1: the keys indexing "sample_type" were not used by the context - this likely means you are trying to index a path that does not support indexing

Additional context

No response

Tip

React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding +1 or me too, to help us triage it. Learn more here.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions