Skip to content

feat: add DNS ServiceConfiguration for metering - #48

Merged
mattdjenkinson merged 2 commits into
mainfrom
feat/dns-service-configuration
Aug 31, 2026
Merged

feat: add DNS ServiceConfiguration for metering#48
mattdjenkinson merged 2 commits into
mainfrom
feat/dns-service-configuration

Conversation

@kevwilliams

Copy link
Copy Markdown
Contributor

Summary

Phase 2 of the catalog registration (#44) — adds the DNS ServiceConfiguration (services.miloapis.com/v1alpha1) declaring metering. The services-operator fans this single document out into billing.miloapis.com/MeterDefinition + MonitoredResourceType CRDs.

Tailored to DNS consumption (authoritative query traffic + managed inventory), not the edge proxy's request/byte counts.

Metrics

Metric Kind Unit Signal
dns.networking.miloapis.com/zone/queries Delta {query} Authoritative queries answered (primary consumption); dims rcode, record_type, location
dns.networking.miloapis.com/zone/hosted Gauge {zone} Active hosted-zone footprint
dns.networking.miloapis.com/recordset/active Gauge {recordset} Managed record-set inventory

Monitored resource types: DNSZone (queries + hosted) and DNSRecordSet (inventory), with billing routing wired to both.

Delivery

Ships phase: Published in the same config/components/service-catalog bundle as the Service, so infra's existing dns-operator-milo-service-catalog Flux Kustomization picks it up automatically on the next staging reconcile — no infra change needed.

Immutability

Once Published, metrics[].name/.kind/.unit and monitoredResourceTypes[].type/.gvk are immutable; renames/unit changes ship as a new metric name (.../v2).

Verification

  • kubectl kustomize config/components/service-catalog builds both Service + ServiceConfiguration
  • After merge + reconcile: services-operator fans out the expected MeterDefinition/MonitoredResourceType objects in staging

Follow-up

Declaring zone/queries is the metering contract; actually emitting query events from the PowerDNS data plane (collection source, per-tenant attribution, CloudEvents) is the remaining usage-pipeline work.

Declare DNS metering as a services.miloapis.com/ServiceConfiguration
(Phase 2 of the catalog registration). Meters three signals:

- zone/queries (Delta, {query}) -- authoritative query volume, the
  primary consumption signal, dimensioned by rcode/record_type/location
- zone/hosted (Gauge, {zone}) -- active hosted-zone footprint
- recordset/active (Gauge, {recordset}) -- managed record-set inventory

Monitored resource types DNSZone and DNSRecordSet, billing routing wired
to both. The services-operator fans this out into MeterDefinition and
MonitoredResourceType billing CRDs. Ships Published in the same
components/service-catalog bundle, so infra's existing Flux Kustomization
picks it up automatically.

Emitting zone/queries events from the PowerDNS data plane remains as
follow-up usage-pipeline work.
Comment on lines +61 to +68
- name: dns.networking.miloapis.com/recordset/active
displayName: Active DNS Record Sets
description: Record sets under management (gauge, 1 per active DNSRecordSet).
kind: Gauge
unit: "{recordset}"
dimensions:
- record_type
- location

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.

Is record set important? I think it would be more valuable to track active number of records.

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.

Switched this to dns.networking.miloapis.com/records/active but also moved it to DNSZone to use Status.RecordCount (sum of all len(spec.records) across its record sets), so the gauge value comes from there. Dropped DNSRecordSet as a monitored resource type entirely since we're not billing per-set.

Comment on lines +54 to +60
- name: dns.networking.miloapis.com/zone/hosted
displayName: Hosted DNS Zones
description: Active hosted-zone footprint (gauge, 1 per active DNSZone).
kind: Gauge
unit: "{zone}"
dimensions:
- location

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 could do dns.networking.miloapis.com/zones?

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.

✔️ renamed to dns.networking.miloapis.com/zones

- Rename zone/hosted → zones (simpler name)
- Replace recordset/active with records/active, attributed to DNSZone
- Drop DNSRecordSet monitored resource type; all metrics now route
  through DNSZone, sourcing record count from Status.RecordCount
  which the zone controller already maintains
@kevwilliams
kevwilliams requested a review from scotwells June 15, 2026 23:52
@mattdjenkinson
mattdjenkinson merged commit b0d193b into main Aug 31, 2026
10 checks passed
@mattdjenkinson
mattdjenkinson deleted the feat/dns-service-configuration branch August 31, 2026 00:44
mattdjenkinson added a commit that referenced this pull request Aug 31, 2026
PR #48 published the meter contract. This produces events against
those meters: query deltas from PowerDNS protobuf, and inventory
gauges from the replicator leader.

The writer stamps compact billing identity as PowerDNS DATUM-USAGE
metadata so LightningStream edge pods can attribute public queries
without DNSZone CRs. Usage is off by default.

The Go module moves to 1.26 for the billing SDK. golangci-lint is
compiled with that toolchain (install-mode goinstall), and Chainsaw
is pinned to v0.2.15 for testing.testDeps.ModulePath.

Closes #49
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.

3 participants