Skip to content

Build1 publisher3 min readPublished

A checked-in snapshot attributes 59 of a Go service's 67 metric records to the platform

Anton Brilliantov regenerates his service's metric list into a checked-in file so the split between platform and service can be reviewed as a diff. His published breakdown of 67 records adds up to 66.

The Engineer · Build desk

Illustration accompanying A checked-in snapshot attributes 59 of a Go service's 67 metric records to the platform

What happened

  • A Go service being carved out of a PHP monolith keeps a generated snapshot of every metric it exposes as a checked-in file, regenerated by a tool, and the current snapshot holds 67 records.
  • Of those records, 59 are attributed to the platform library and 6 to the service, with one further record standing for the dynamic-metric factory instead of a fixed name.
  • One platform gauge exists because the Go linker ignores -X aimed at a missing symbol, leaving a green build whose version reads dev in the audit trail and trace attributes.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • capability Keeping the metric list in a file turns adding a metric into a reviewable change, so a name someone slipped in shows up in a pull request instead of on a scrape endpoint during an incident.
  • constraint Metric names and label sets belong to the platform library, so a team that wants a different outcome label on amqp_delivery_total is asking the platform owners for a release, not editing its own code.
  • contradiction The ratio is only as auditable as the file: the post's own categories account for 66 of the 67 records, and a reader cannot tell which side the last one falls on.
  • cost The 59 free records are paid for upstream, by whoever maintains the shared library, the manifest format and the snapshot generator; a service that imports a third-party framework instead gets none of them.

Add a queue to the manifest and three metric records appear with no instrumentation code in the service repository: amqp_delivery_total{queue,handler,status}, a delivery duration histogram, and an in-flight gauge [11]. A declared Postgres pool brings connection pool state from the driver, and a registered gRPC handler gets request counts, durations and statuses per method from the platform's interceptors [13][10]. All of it comes from the shared platform library the service imports, wired because the manifest declared the corresponding resource [15].

The counts run 59 records with source platform and 6 with source service [2][3]. On the stated total of 67 that is 88 percent platform and 9 percent service [21]. Brilliantov wrote that nine out of ten records exist "because the service was started, not because anyone decided to measure something" [5].

The published breakdown does not close. Fifty-nine platform records plus six service records plus the single <dynamic> record is 66, one short of the stated 67 [22][4]. The post does not place the remaining record.

A record is a metric name, not a time series. amqp_delivery_total carries three labels [11], so one line in that file becomes as many series at runtime as there are queue, handler and status combinations. The 59-to-6 split describes who owns the names. Storage and scrape cost track label cardinality, and a platform that ships a duration histogram per gRPC method is the bigger contributor there too [10].

The file is the part I would copy first. "You can't diff a scrape endpoint. You can diff a snapshot," Brilliantov wrote [17]. A metric that exists only in a running process cannot be reviewed in a pull request [23], so a new name becomes a line someone approves instead of something found later during an incident. He also wrote, "I'd rather start with a count, because the count is the argument" [16].

app_version is the entry that justifies itself on failure modes. It is one gauge carrying the version string linked into the binary [8]. The Go linker silently ignores -X pointed at a symbol that does not exist, so the build stays green, the version stays dev, and dev is what lands in the audit trail and the trace attributes [9]. Publishing it as a metric puts that on a dashboard. In the same spirit, the platform serves /health and /ready on the system port and the service implements neither handler, and there is no wait-for-health step in the deploy pipeline [6][7]. One fewer step to time out.

For the ratio to transfer, your services have to be shaped like this one: gRPC in, broker deliveries consumed, an outbound relay drained, Postgres behind it [10][11][12][13]. Six service metrics is what is left over when the platform owns transport, broker, pool and Go runtime [14]. A service with real domain counters would add more on its own side, and the split would move. You also need the library and the manifest first, and Brilliantov is describing a live PHP monolith being carved into Go services [18]. "This is what I do on one codebase, with the reasons and the price," he wrote [20].

What to watch

  • Whether CI fails the build when the checked-in snapshot and the live scrape endpoint disagree; the post describes the file as tool-regenerated, not as a gate.
  • A second service's snapshot from the same platform, which would show whether the 59 platform records travel or are specific to this codebase.
  • Accounting for the <dynamic> record, since one line in the file can stand for an open-ended set of metric names.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories