Skip to content

Add resource attribute support to ChipIngress client#2216

Draft
pkcll wants to merge 9 commits into
mainfrom
chip-ingress-resource-attributes
Draft

Add resource attribute support to ChipIngress client#2216
pkcll wants to merge 9 commits into
mainfrom
chip-ingress-resource-attributes

Conversation

@pkcll

@pkcll pkcll commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds resource-attribute propagation from beholder.Config.ResourceAttributes to the ChipIngress cre topic via two mechanisms: (1) gRPC metadata headers (chipingress.WithHeaderProvider/NewStaticHeaderProvider), raw key names, parity with beholder__platform__messages; (2) CloudEvent extensions (chipingress.WithResourceAttributeExtensions) with keys sanitized to ^[a-z0-9]+$ per the CloudEvents spec, surfacing as ce_<name> Kafka headers.
  • Wires both the non-batch ChipIngressEmitter and ChipIngressBatchEmitterService to stamp resource attributes on every emitted event.

Known gaps / follow-ups (called out for reviewers)

  • gRPC-metadata → Kafka-header forwarding is unconfirmed server-side. The chip-ingress server's baseKafkaHeaders logic does not appear to forward arbitrary incoming gRPC metadata onto Kafka headers today. The CE-extension mechanism guarantees headers immediately; the gRPC-metadata mechanism is shipped for observability now, with full parity once/if a chip-ingress server-side change forwards it. A follow-up ticket against chip-ingress should track that.
  • pkg/durableemitter is out of scope. It has its own NewEvent call site and config, and wiring it up would also require chainlink core changes (application.go, shell.go, plugins/loop_registry.go). This assumes production CRE-topic traffic goes through the beholder emitters, not DurableEmitter — unconfirmed, worth a sanity check before merge.
  • Cross-module version bump needed. pkg/chipingress is its own Go module; go.mod's pinned pkg/chipingress pseudo-version needs bumping to pick these changes up in pkg/beholder (standard two-step process per this repo's history).

Test plan

  • go test ./pkg/chipingress/... and go test ./pkg/beholder/... pass
  • New unit tests: SanitizeExtensionName, WithResourceAttributeExtensions (sanitization, reserved-name skip, deterministic dedup), NewStaticHeaderProvider, resourceAttributesToStringMap, and emitter-level tests asserting ce_<sanitized> extensions land on published/batched events
  • Manual verification against a live chip-ingress endpoint (not done in this session)

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

✅ API Diff Results - github.com/smartcontractkit/chainlink-common/pkg/chipingress

✅ Compatible Changes (7)

./ (7)
  • EventOpt — ➕ Added

  • NewEventWithOpts — ➕ Added

  • NewStaticHeaderProvider — ➕ Added

  • SanitizeExtensionName — ➕ Added

  • SanitizeMetadataHeaders — ➕ Added

  • SanitizeMetadataValue — ➕ Added

  • WithResourceAttributeExtensions — ➕ Added


📄 View full apidiff report

pkcll added 4 commits July 1, 2026 23:47
Propagate node resource attributes (from beholder.Config.ResourceAttributes) to the
cre topic via gRPC metadata headers and sanitized CloudEvent extensions, so ChipIngress
events carry the same node/environment identification already present on the legacy
beholder__platform__messages topic.
grpc.WithUnaryInterceptor is last-one-wins, so configuring both a header
provider and NOP lookup silently dropped one; switch to
WithChainUnaryInterceptor so they compose. Also reserve the CloudEvents
core context attribute names (id, source, type, specversion, data, etc.)
so a resource attribute can never collide with them.
grpc-go hard-fails the entire RPC when an outgoing metadata pair fails its
charset/printability validation, unlike the CE-extension path where an
invalid entry is just dropped. Add SanitizeMetadataHeaders (reusing
SanitizeExtensionName for keys, plus a printable-ASCII value sanitizer) and
apply it once when building the static header provider, so a malformed
resource-attribute key or value can no longer take down chip-ingress
emission for the node.
After [a-z0-9] key sanitization, "te" is the only grpc-reserved header
name reachable (every other reserved header contains a ':' or '-' that
sanitization strips). Handle it deterministically via an explicit skip
set rather than relying on grpc's own handling of a reserved header.
@pkcll pkcll force-pushed the chip-ingress-resource-attributes branch from e6eabcc to fdb6dee Compare July 2, 2026 03:48
Remove an unnecessary blank line in NewEvent and use net.ListenConfig in tests instead of deprecated net.Listen.

Co-authored-by: Cursor <cursoragent@cursor.com>
@pkcll pkcll requested a review from patrickhuie19 July 2, 2026 05:05
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

⚠️ API Diff Results - github.com/smartcontractkit/chainlink-common

⚠️ Breaking Changes (2)

pkg/beholder (2)
  • ChipIngressEmitter — Old is comparable, new is not

  • ChipIngressEmitterConfig — Old is comparable, new is not

✅ Compatible Changes (1)

pkg/beholder.ChipIngressEmitterConfig (1)
  • ResourceAttributes — ➕ Added

📄 View full apidiff report

Introduce NewEventWithOpts for variadic EventOpt without changing NewEvent's
exported signature, update beholder call sites, and bump the root module's
pkg/chipingress dependency to include the new API.

Co-authored-by: Cursor <cursoragent@cursor.com>
pkcll added 3 commits July 2, 2026 01:14
Point pkg/chipingress at the squashed commit and drop stale go.sum entries
so check-tidy passes make gomodtidy.
Keep the require pinned to the main-branch pseudo-version so go-mod validation
passes, and replace to ./pkg/chipingress so root-module builds pick up this PR's
chipingress API changes.
Adding a map field to a previously-comparable exported struct breaks
apidiff. ChipIngressEmitterConfig gets a new NewWithResourceAttributes
method instead of a ResourceAttributes field; New(client) is unchanged
and delegates with nil attrs. ChipIngressEmitter stores resource attrs
behind a pointer (resourceAttrs *resourceAttrExtensions) instead of a
bare map, keeping the struct comparable.
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