name: otel-weaver
description: OpenTelemetry Weaver registry authoring, codegen, and CI enforcement. Use when adopting Weaver, authoring or reviewing a registry (manifest, attributes, metrics, spans, events), writing Jinja2 templates against the resolved schema, migrating hand-maintained telemetry constants, or wiring weaver registry check/generate/diff into CI.
OpenTelemetry Weaver
Use this skill when an organization wants to define its own semantic conventions on top of upstream OTel and generate language bindings from them.
Usage:
- pair with
otel-semantic-conventionsto decide which attributes already exist upstream and should not be redeclared in the local registry - use
otel-sdk-versionsonly for SDK package selection; Weaver versions are tracked separately at https://github.com/open-telemetry/weaver/releases
If a companion skill is unavailable:
- do not stop
- do not rely on memory alone when the guidance can be checked from official sources
- consult the Weaver repo,
schemas/semconv-syntax.v2.md, anddocs/usage.md/docs/validate.md - state which fallback you used and leave any unverified item unresolved
Mental Model
Three moving parts:
- Registry — directory of YAML files.
manifest.yamlis required and names the registry, declaressemconv_versionandschema_url. The rest declareattributes,metrics,spans,events,entities. The local registry'ssemconv_versionis yours to manage; bump it on changes. - Templates — directory of Jinja2 files plus a
weaver.yamlper target language describing which templates to run, with what filter, in whatapplication_mode, and with what output filename. - Policies — Rego rules. Built-in OTel policies are the floor; custom policies layer on org rules.
These three replace a hand-rolled const.go (or equivalent): const blocks become the registry, the act of writing them becomes codegen, and tribal knowledge becomes policies.
Non-Negotiable Rules
- Install Weaver via one of the methods documented at https://github.com/open-telemetry/weaver#install (release binary,
otel/weaver:vX.Y.ZDocker image, or thesetup-weaverGitHub Action). Neverbrew install weaver— that resolves to an unrelated Scribd tool. - Reference upstream semconv attributes by
refrather than redeclaring them. Boundary domains (http,db,messaging,rpc,network,gen-ai, ...) belong in upstream OTel semconv, not in a local registry. Use the language SDK's semconv package for those at runtime. - Every entry needs
stability. Weaver refuses to generate without it. - Use a domain prefix (e.g.
ecommerce.,acme.) for org-local attributes, metrics, and spans. - Run the language formatter (
gofmt -w,prettier,ruff format, ...) on generated output. Jinja whitespace produces multiple blank lines; without formatting, the diff check in CI will fail spuriously. - Confirm the resolved schema shape before writing a template. Run
weaver registry resolve -r <reg> -f json -o /tmp/r.jsonand inspect — inputkey/name/typefields are renamed at resolve time (seereferences/template-authoring.md).
Workflow
- Install or locate Weaver. Follow the upstream install instructions at https://github.com/open-telemetry/weaver#install — pick a pinned release binary, the
otel/weaver:vX.Y.ZDocker image, or thesetup-weaverGitHub Action. Use Docker for CI and reproducible local runs. - Author the registry. Required:
manifest.yamlplus at least one ofattributes.yaml/metrics.yaml/spans.yaml/events.yaml. Seereferences/registry-authoring.md. - Author templates. One target dir per language under
templates/registry/<lang>/withweaver.yamlplus*.j2. Seereferences/template-authoring.md. - Validate and generate.
weaver registry check -r ./telemetry/registry/for fast feedback.weaver registry generate --registry ./telemetry/registry/ --templates ./telemetry/templates/ <lang> <output-dir>for codegen. Run the language formatter on the output. - Wire into CI. Three gates:
check(schema),generate+git diff --exit-code(checked-in code is current),diffagainst the base branch (surfaces breaking changes). Seereferences/ci-integration.md.
Gotchas
These cost time and are not obvious from the upstream docs:
brew install weaverinstalls the wrong tool. Use GitHub releases or Docker.- Generated output is not formatter-clean. Always run the language formatter after
weaver registry generate. - Resolved field names differ from input. Attribute input
key→ resolvedname. Metric inputname→ resolvedmetric_name. Span inputtype→ resolvedidof the formspan.<type>, with a flatnamestring equal to the inputname.note. Always resolve and inspect before writing a template. - The
commentJinja filter takes a keyword argument:attr.brief | comment(format="go"). It already emits the//prefix; do not add another. - There is no prebuilt jq filter for spans. Use:
It must be single-quoted insemconv_signal("span"; {}) | group_by(.root_namespace) | map({root_namespace: .[0].root_namespace, spans: . | sort_by(.id)})weaver.yaml; the colons in jq syntax collide with YAML mapping rules otherwise. weaver registry checkemits "File formatdefinition/2is not yet stable" on every run as of 0.22.1. This is normal; do not treat it as a failure.--futureis opt-in but breaks today ondefinition/2. Note this in CI guidance and re-enable once the format goes stable.- CLI argument ordering for
generate: target directory name is positional after--registryand--templates; the output directory follows.--templatespoints at the parent that contains target dirs, not at the language-specific subdir. - Span name in registry vs. runtime: required schema fields are
type,kind(client/server/producer/consumer/internal),brief,stability, and a structuredname: { note: "..." }. For internal business spans, putting the dotted type identifier inname.noteand using the resolvedspan.namestring at runtime is clean. - What does NOT belong in your local registry. DB, HTTP, messaging, RPC, network, GenAI, and similar boundary spans/attributes follow upstream OTel semconv. Until upstream is pulled in as a manifest dependency, instrumentation for those should reference the language SDK's semconv package directly. This is the most common modeling mistake.
- Drop the
.totalsuffix from counter names — OTel naming has moved away from it. - Use seconds (
s) for duration histograms, not milliseconds. Migrating frommsis a natural step when authoring the schema; flag it.
References To Load On Demand
- registry YAML field reference:
references/registry-authoring.md - Jinja2 patterns, jq filters, resolved-shape cheat sheet:
references/template-authoring.md - ready-to-lift GitHub Actions example:
references/ci-integration.md - hand-maintained-constants → registry walkthrough:
references/migration-playbook.md - semantic conventions skill:
otel-semantic-conventions - manual instrumentation skill:
manual-instrumentation
Out Of Scope
These are natural follow-ups but not part of this skill:
- publishing the registry as a versioned artifact for downstream consumers
- declaring upstream semantic-conventions as a manifest dependency
weaver registry live-checkagainst a local collector- custom Rego policies beyond the built-ins
- helper-function codegen (
MyMetricName(meter)wrappers)
Verification Contract
If you authored or modified a Weaver registry, templates, or CI integration:
- re-open the changed files before finishing
- run
weaver registry checkagainst the registry and capture the result - run
weaver registry generateand the language formatter, then verifygit diff --exit-codeis clean - confirm each applicable item with codebase evidence
Report the final check with:
[x]completed[~]not applicable, with a reason[ ]unresolved
Use these items:
- registry has
manifest.yamlwithname,semconv_version,schema_url - every entry has
stability - org-local attributes/metrics/spans use a domain prefix
- no boundary-domain (http/db/messaging/rpc/network/gen-ai) entries duplicated locally
- counter names have no
.totalsuffix - duration histograms use
s(seconds) - templates use jq filters that match the resolved schema, with the spans filter single-quoted
- generated output is formatter-clean
- CI runs
check,generate+git diff --exit-code, anddiffagainst the base branch - changed files were re-read
- remaining risks or gaps are stated