Skip to content

[OpAMP] parse comma separated tags list from non-identifying attributes#6769

Open
juliaElastic wants to merge 3 commits intoelastic:mainfrom
juliaElastic:opamp-metadata-fields
Open

[OpAMP] parse comma separated tags list from non-identifying attributes#6769
juliaElastic wants to merge 3 commits intoelastic:mainfrom
juliaElastic:opamp-metadata-fields

Conversation

@juliaElastic
Copy link
Copy Markdown
Contributor

@juliaElastic juliaElastic commented Apr 8, 2026

What is the problem this PR solves?

Save tags list in the top level tags field in Agent, taking from the comma separated list from non-identifying attributes

How does this PR solve the problem?

Non-identifying attributes are already added to Agent, tags need special handling because they are mapped to the top level tags field, and the comma separated string has to be parsed.

How to test this PR locally

Follow instructions in https://github.com/elastic/fleet-server/blob/main/docs/opamp.md

Download and extract otel collector, e.g.:

curl -L -O https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v0.144.0/otelcol-contrib_0.144.0_darwin_arm64.tar.gz 

Create otel config to include the new metadata fields, e.g. otel-opamp.yaml:

receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317

processors:
  resourcedetection:
    detectors: ["system","env"]
    system:
      hostname_sources: ["os"]
      resource_attributes:
        host.name:
          enabled: true
        host.arch:
          enabled: true
        os.description:
          enabled: true
        os.type:
          enabled: true

exporters:
  debug:
    verbosity: detailed
  elasticsearch/otel:
    endpoints: [ "http://localhost:9200" ]
    api_key: ${env:ES_API_KEY} 
    mapping:
      mode: otel
  otlp:
    endpoint: "http://localhost:4317"
    tls:
      insecure: true

extensions:
  opamp:
    server:
      http:
        endpoint: http://localhost:8220/v1/opamp
        tls:
          insecure: true
        headers:
          Authorization: ApiKey ${env:FLEET_ENROLLMENT_TOKEN}
    instance_uid: ${env:INSTANCE_UID}
    capabilities:
      reports_effective_config: true
    agent_description:
      # Pipelines Lab reads these fields to populate the fleet and configs views.
      non_identifying_attributes:
        # Shown as the collector's name in the fleet list. Defaults to hostname if unset.
        elastic.display.name: ${env:HOSTNAME}
        # Machine-friendly key used to group collectors on the Configs page.
        # Collectors sharing the same slug collapse into one group with a
        # shared health summary and config-hash distribution view.
        elastic.collector.group: "mysql-dev"
        # Human-readable label for the group shown in the UI.
        elastic.collector.group_name: "MySQL Dev"
        # Labels this config on the Configs page and as a header in the effective config view.
        config.description: "The MySQL Stuff"
        # Tags appear in the fleet view and as resource attributes
        # on all self-emitted metrics/logs in Elasticsearch (queryable via ES|QL).
        tags: "dev,west,us-west-1a"
        # OTel semconv deployment tier — e.g. production, staging, dev.
        deployment.environment.name: "dev"

service:
  pipelines:
    logs:
      receivers: [otlp]
      exporters: [debug]
    metrics:
      receivers: [otlp]
      processors: [resourcedetection]
      exporters: [elasticsearch/otel]
  extensions: [opamp]

  # publish collector internal telemetry
  telemetry:
    metrics:
      level: detailed
      readers:
        - periodic:
            interval: 30000
            exporter:
              otlp:
                protocol: grpc
                endpoint: http://localhost:4317
    resource:
      # semconv: identifies this collector instance in Elasticsearch.
      service.name: mysql-dev
      service.instance.id: ${env:HOSTNAME}
      # Required for Logs and Error Patterns tabs — the backend queries ES by this field.
      service.node.name: ${env:HOSTNAME}
      # Mirrors elastic.display.name above — queryable in ES|QL.
      elastic.display.name: ${env:HOSTNAME}
      # Stamps self-emitted metrics/logs with the host — queryable as host.name in ES|QL.
      host.name: ${env:HOSTNAME}
      # semconv: groups collectors by workload (mirrors elastic.collector.group).
      service.namespace: "mysql-dev"
      # Machine-friendly group key — matches elastic.collector.group in the fleet UI.
      elastic.collector.group: "mysql-dev"
      # Human-readable group label — matches elastic.collector.group_name in the fleet UI.
      elastic.collector.group_name: "MySQL Dev"
      # Mirrors tags above — queryable in ES|QL.
      tags: "dev,west,us-west-1a"
      deployment.environment.name: "dev"

Create API keys and start otel collector:

 cd ~/Downloads/otelcol-contrib_0.144.0_darwin_arm64
 
 export INSTANCE_UID=<uuid> # e.g. "519b8d7a-2da8-7657-b52d-492a9de33313"
 export ES_API_KEY=<api_key> # ES API key from observability onboarding UI
 export FLEET_ENROLLMENT_TOKEN=<enrollment_token> 
 export HOSTNAME=MacBook-Pro.local
 ./otelcol-contrib --config ./otel-opamp.yaml

Check the Agent JSON in Fleet, check that tags are showing up as an array, and non_identifying_attributes show the new metadata fields.

image

Check the telemetry data in Discover, and find the matching fields in resource.attributes:

image

Tested ESQL queries on the new fields in telemetry:

image

Open question:

  • The tags field in collector telemetry data is not parsed to a list of strings, I'm not sure how can we fix that. The collector config doesn't accept a list, only string.
    "tags": "dev,west,us-west-1a"

Design Checklist

  • I have ensured my design is stateless and will work when multiple fleet-server instances are behind a load balancer.
  • I have or intend to scale test my changes, ensuring it will work reliably with 100K+ agents connected.
  • I have included fail safe mechanisms to limit the load on fleet-server: rate limiting, circuit breakers, caching, load shedding, etc.

Checklist

  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • I have made corresponding change to the default configuration files
  • I have added tests that prove my fix is effective or that my feature works
  • I have added an entry in ./changelog/fragments using the changelog tool

Related issues

@mergify
Copy link
Copy Markdown
Contributor

mergify bot commented Apr 8, 2026

This pull request does not have a backport label. Could you fix it @juliaElastic? 🙏
To fixup this pull request, you need to add the backport labels for the needed
branches, such as:

  • backport-./d./d is the label to automatically backport to the 8./d branch. /d is the digit
  • backport-active-all is the label that automatically backports to all active branches.
  • backport-active-8 is the label that automatically backports to all active minor branches for the 8 major.
  • backport-active-9 is the label that automatically backports to all active minor branches for the 9 major.

@juliaElastic juliaElastic added enhancement New feature or request backport-skip Skip notification from the automated backport with mergify skip-changelog labels Apr 8, 2026
},
{
name: "multiple tags",
tagsValue: "dev,west,us-west-1a",
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using a comma separated list, when tested with an array in the otel config yaml, I was getting an error in the otel collector
tags: ["prod", "west", "us-west-1a"]

'extensions' error reading configuration for "opamp": decoding failed due to the following error(s):

'agent_description.non_identifying_attributes[tags]' expected type 'string', got unconvertible type '[]interface {}'
'service.telemetry.resource[tags]' expected type 'string', got unconvertible type '[]interface {}'

@juliaElastic juliaElastic marked this pull request as ready for review April 8, 2026 08:11
@juliaElastic juliaElastic requested a review from a team as a code owner April 8, 2026 08:11
juliaElastic added a commit to elastic/kibana that referenced this pull request Apr 9, 2026
## Summary

Relates elastic/ingest-dev#7062

Added new mappings in
elastic/elasticsearch#145824 to kibana so the UI
search works on them.

To verify:

Start ES from source with so the new mappings apply (switch to the
branch of the ES PR):
```
yarn es source --license trial -E xpack.security.authc.api_key.enabled=true -E xpack.security.authc.token.enabled=true  --source-path=/Users/juliabardi/elasticsearch  -E path.data=/tmp/es-data -E xpack.ml.enabled=false -E http.host=0.0.0.0
``` 

Add a collector (follow steps in
elastic/fleet-server#6769) and test that the UI
search works on the new fields:

<img width="952" height="505" alt="image"
src="https://github.com/user-attachments/assets/d776f8cd-3367-4f35-a3fa-deee5b211292"
/>
<img width="949" height="498" alt="image"
src="https://github.com/user-attachments/assets/7045e502-0484-4cc6-937b-c878bbbead29"
/>
<img width="888" height="492" alt="image"
src="https://github.com/user-attachments/assets/9971b2b6-acdb-474e-a3c2-a68e54779cd6"
/>
<img width="840" height="515" alt="image"
src="https://github.com/user-attachments/assets/dd8da6c6-e546-4eef-ad43-b85cd6dae7c6"
/>


### Checklist

Check the PR satisfies following conditions. 

Reviewers should verify this PR satisfies this list as well.

- [ ] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)
- [ ]
[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)
was added for features that require explanation or tutorials
- [ ] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [ ] If a plugin configuration key changed, check if it needs to be
allowlisted in the cloud and added to the [docker
list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)
- [ ] This was checked for breaking HTTP API changes, and any breaking
changes have been approved by the breaking-change committee. The
`release_note:breaking` label should be applied in these situations.
- [ ] [Flaky Test
Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was
used on any tests changed
- [ ] The PR description includes the appropriate Release Notes section,
and the correct `release_note:*` label is applied per the
[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)
- [ ] Review the [backport
guidelines](https://docs.google.com/document/d/1VyN5k91e5OVumlc0Gb9RPa3h1ewuPE705nRtioPiTvY/edit?usp=sharing)
and apply applicable `backport:*` labels.

### Identify risks

Does this PR introduce any risks? For example, consider risks like hard
to test bugs, performance regression, potential of data loss.

Describe the risk, its severity, and mitigation for each identified
risk. Invite stakeholders and evaluate how to proceed before merging.

- [ ] [See some risk
examples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx)
- [ ] ...
@ycombinator ycombinator added the Team:Elastic-Agent-Control-Plane Label for the Agent Control Plane team label Apr 10, 2026
tagsValue: " dev , west , us-west-1a ",
wantTags: []string{"otel-collector", "dev", "west", "us-west-1a"},
otherNIAKeys: []string{string(semconv.HostNameKey)},
},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should add a test case for duplicate tags, e.g. "west,dev,west". These should probably be deduplicated so the wantTags is []string{"west","dev"}. I can't imagine a use case for storing duplicates?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport-skip Skip notification from the automated backport with mergify enhancement New feature or request skip-changelog Team:Elastic-Agent-Control-Plane Label for the Agent Control Plane team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants