Skip to content

feat(otel_exporter): expose ubi.* identification fields on OTel Resource#81

Draft
amogiska wants to merge 4 commits intomainfrom
amogiska/arrow-ubi-resource-attrs
Draft

feat(otel_exporter): expose ubi.* identification fields on OTel Resource#81
amogiska wants to merge 4 commits intomainfrom
amogiska/arrow-ubi-resource-attrs

Conversation

@amogiska
Copy link
Copy Markdown
Contributor

Summary

Parse `pg_stat_ch.extra_attributes` in `PopulateResource()` and set matching identification keys on the OTel Resource so downstream collectors can route/filter arrow records against JWT claims without running a resource-enrichment processor on the VM.

Mapping from `extra_attributes` keys to OTel Resource attributes:

extra_attributes key OTel Resource attribute
`instance_ubid` `ubi.postgres_resource_ubid`
`server_ubid` `ubi.postgres_server_ubid`
`server_role` `ubi.postgres_server_role`
`region` `cloud.region`
`cell` `cell`

Why

The cell `datagres-otelcol` runs `filter/validate_claims` which compares `resource.attributes["ubi.postgres_resource_ubid"]` to the JWT claim `auth_token_clickgres_postgres_resource_id`. When arrow records skip resource enrichment on the VM (to save CPU), these attributes are missing and the filter silently no-ops via `error_mode: ignore` — auth is effectively bypassed.

With this change, pg_stat_ch emits arrow records with the ubi.* attributes already on the Resource, so:

  • The VM OTel collector can route arrow records straight to export (no resource/ubiMetadata needed)
  • `filter/validate_claims` finds the attributes and validates them against JWT claims properly

The same GUC already feeds `ArrowBatchBuilder` for the Arrow payload columns, so one config source populates both.

Test plan

  • Build and start with `pg_stat_ch.extra_attributes = 'instance_ubid:abc;server_ubid:xyz;server_role:primary;region:us-east-1;cell:cell0'` and `pg_stat_ch.otel_arrow_passthrough = on`
  • Capture an OTLP export and verify Resource attributes include `ubi.postgres_resource_ubid=abc`, `ubi.postgres_server_ubid=xyz`, etc.
  • Verify no regression when `extra_attributes` is unset (only service.name/version/host.name on Resource)

Parse pg_stat_ch.extra_attributes in PopulateResource() and set
matching ubi.* keys on the OTel Resource:
- instance_ubid    → ubi.postgres_resource_ubid
- server_ubid      → ubi.postgres_server_ubid
- server_role      → ubi.postgres_server_role
- region           → cloud.region
- cell             → cell

This lets downstream OTel collectors (e.g. datagres-otelcol) route
and validate arrow records against JWT claims without running a
resource-enrichment processor on the VM. The same GUC is already
consumed by ArrowBatchBuilder for the Arrow payload columns, so
one config source populates both.
Add include/export/extra_attr_keys.h defining each recognized key as
a Key{guc_key, resource_attr} struct in a single kAll array.

Both the Arrow batch builder and the OTel exporter now reference these
constants instead of duplicating string literals across files. Adding
a new identification field is now a one-line addition to kAll plus
the Arrow column wiring (which still needs a typed builder per column).

Drive-by: ExtraAttr() now takes string_view instead of const char*.
Parse pg_stat_ch.extra_attributes once at exporter init (in
ConfigureLogExport) and cache the resulting OTel Resource attribute
pairs. PopulateResource now iterates the cached vector instead of
re-parsing the GUC string on every batch.

Mirrors arrow_batch.cc's parse-once-at-Init pattern. GUC changes
require a connection restart.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant