OpenTelemetry Collector distribution with JWT-based license validation for enterprise.
English | νκ΅μ΄ | ζ₯ζ¬θͺ | δΈζ
Based on OpenTelemetry Collector v0.109.0.
- π License Guard Extension β RS256 JWT-based license validation (public key only β no private key required)
- πͺ License Gate Processor β Drops telemetry (traces, logs, metrics) when the license has expired beyond the grace period
- β³ Grace Period β Configurable window (default 7 days) to warn operators without disrupting data flow immediately after expiration
- π Periodic Re-validation β License status re-checked on a configurable interval (default 1 hour)
- π Prometheus Metrics β 4 built-in metrics for license health and drop accounting
- π§ Pass-through Mode β Works transparently without a license for dev/test environments
- π’ Multi-tenant Aware β License claims (
tenant_id,contract_id) surfaced as metric attributes - π¦ Upstream compatible β Full OTel Collector features (ClickHouse exporter, span metrics processor, etc.) retained
The gateway sits at the edge of the Host cluster, in front of ClickHouse. Every OTLP payload from Agent clusters passes through a two-stage license check: the License Guard Extension holds and refreshes the current license state, and the License Gate Processor consults that state on each batch, either forwarding to ClickHouse or dropping with a counter increment.
flowchart LR
subgraph Agents["Agent Clusters"]
A1[OTel Collector<br/>DaemonSet]
A2[OTel Collector<br/>Deployment]
end
subgraph Gateway["K-O11y OTel Gateway"]
direction TB
R[OTLP Receiver<br/>:4317]
LG["π License Guard Extension<br/>(RS256 JWT verify,<br/>check_interval: 1h)"]
GP["πͺ License Gate Processor<br/>(consult guard state)"]
B[Batch Processor]
E[ClickHouse Exporter]
R --> GP
GP --> B
B --> E
LG -.state.-> GP
end
subgraph Decision["Gate Decision"]
direction TB
V{License<br/>valid?}
G{Within<br/>grace period?}
PASS[β
Forward to ClickHouse]
WARN[β οΈ Forward + log warning]
DROP["β Drop<br/>otel_data_dropped_total++"]
V -->|yes| PASS
V -->|no| G
G -->|yes| WARN
G -->|no| DROP
end
A1 -->|OTLP gRPC| R
A2 -->|OTLP gRPC| R
GP -.each batch.-> V
E --> CH[(ClickHouse)]
classDef agent fill:#e1f5ff,stroke:#0288d1,color:#000
classDef gw fill:#fff3e0,stroke:#f57c00,color:#000
classDef decide fill:#f3e5f5,stroke:#7b1fa2,color:#000
class A1,A2 agent
class R,LG,GP,B,E gw
class V,G,PASS,WARN,DROP decide
Validation flow:
- On startup, License Guard loads the JWT from env (
LICENSE_KEY) and verifies the RS256 signature with the configured public key - Guard extracts claims (
tenant_id,contract_id,exp) and records them on Prometheus metrics - Every
check_interval(default 1h), Guard re-validates and updates its in-memory status - For every telemetry batch, License Gate Processor consults Guard's status:
- Valid β forward to the next processor
- Expired but within grace period β forward + log a warning
- Expired beyond grace period β drop and increment
otel_data_dropped_total
A JWT-based license validation extension that exposes license status via Prometheus metrics and OpenTelemetry internal metrics.
- RS256 public-key verification β only the public key is deployed to the gateway; private keys stay with the license issuer
- Expiration tracking with configurable grace period
- Periodic re-validation (default:
1h) - Pass-through mode when no license is configured (dev/test)
fail_modeβclosedto block on verification failure,opento allow
A processor that drops telemetry data when the License Guard reports an expired license beyond the grace period.
- Works with traces, logs, and metrics pipelines
- Integrates with License Guard Extension by name (
extension_name) - In grace period: warns but lets data through
- After grace period: drops data and increments
otel_data_dropped_total
extensions:
license_guard:
# JWT license key (environment variable reference)
license_key_env: "LICENSE_KEY"
# RSA public key for JWT verification (PEM format)
public_key_pem: |
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
# Re-validation interval (default: 1h)
check_interval: 1h
# Grace period after expiration (default: 7 days)
grace_period_days: 7
# Behavior on validation failure: "closed" (block) or "open" (allow)
fail_mode: closedprocessors:
license_gate:
# Name of the License Guard extension to check (default: "license_guard")
extension_name: license_guardextensions:
license_guard:
license_key_env: "LICENSE_KEY"
public_key_pem: |
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
service:
extensions: [license_guard]
pipelines:
traces:
receivers: [otlp]
processors: [license_gate, batch]
exporters: [clickhouse]
logs:
receivers: [otlp]
processors: [license_gate, batch]
exporters: [clickhouse]
metrics:
receivers: [otlp]
processors: [license_gate, batch]
exporters: [clickhouse]- Go 1.22+
- Docker
go build -o signoz-otel-collector ./cmd/signozotelcollectordocker build -t ghcr.io/wondermove-inc/signoz-otel-collector:latest \
-f cmd/signozotelcollector/Dockerfile .go test ./extension/licenseguardextension/...
go test ./processor/licensegateprocessor/...| Metric | Type | Description | Attributes |
|---|---|---|---|
otel_license_valid |
Gauge | Whether the license is currently valid (1=valid, 0=invalid) |
tenant_id, contract_id |
otel_license_expires_in_days |
Gauge | Days until license expiration (negative = expired) | tenant_id, contract_id |
otel_grace_period_remaining_days |
Gauge | Days remaining in grace period (0 if not in grace period) |
tenant_id, contract_id |
otel_data_dropped_total |
Counter | Total data points dropped due to license expiration | reason=license_expired, signal=traces|logs|metrics |
Example alert rules:
# License expiring within 14 days
- alert: LicenseExpiringSoon
expr: otel_license_expires_in_days < 14
for: 10m
# Data being dropped due to expired license
- alert: DataDroppedLicenseExpired
expr: rate(otel_data_dropped_total[5m]) > 0
for: 1m| Symptom | Likely Cause | Fix |
|---|---|---|
license_guard: failed to verify JWT on startup |
Public key PEM mismatch or wrong LICENSE_KEY env |
Verify public_key_pem matches the issuer's key pair; re-check LICENSE_KEY value |
otel_license_valid = 0 but license is new |
Clock skew on the gateway host | Ensure NTP is configured on the gateway node |
otel_data_dropped_total increasing unexpectedly |
License expired and grace period ended | Rotate the license key (LICENSE_KEY env) and restart, or increase grace_period_days temporarily |
| Gateway starts but no data reaches ClickHouse | license_gate processor ordering |
Confirm license_gate is before batch in every pipeline |
| Dev environment blocked by license | Production config applied to dev | Omit the license_guard extension entirely for pass-through mode |
K-O11y OTel Gateway is part of the broader K-O11y project.
- Find an issue labeled
good first issueorhelp wanted - Comment on the issue to claim it (avoid duplicate work)
- Fork, branch, and send a PR β scope narrowly, describe clearly
- Address review feedback β maintainers will reply within a few days
See CONTRIBUTING.md for details.
This project follows passive maintenance β PRs and issues are reviewed as time allows. We aim to respond within 7 days but cannot guarantee faster turnaround.
Apache License 2.0 β see LICENSE.
Forked from SigNoz OTel Collector (Apache 2.0), based on the OpenTelemetry Collector (Apache 2.0). See NOTICE for attribution details.
- Umbrella: k-o11y β meta-repo with the full stack overview
- Server: k-o11y-server β Observability backend + Core API
- Install: k-o11y-install β Helm charts + Go CLI installers
- OTel Collector: k-o11y-otel-collector β Agent-side collector with CRD Processor
- π Bug reports & feature requests: GitHub Issues
- π Questions & discussions: Open an issue on the umbrella repo
- π Website: www.skuberplus.com
Built and maintained by Wondermove