<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/implementing-metrics-in-go-u0orxjqqt" -->

---
title: Implementing metrics in Go | daily.dev
description: A hands-on walkthrough of building a lightweight metrics library in Go from scratch, covering the three common metric types (counters, gauges, histograms) and...
canonical: https://daily.dev/posts/implementing-metrics-in-go-u0orxjqqt
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Implementing metrics in Go | daily.dev
og:description: A hands-on walkthrough of building a lightweight metrics library in Go from scratch, covering the three common metric types (counters, gauges, histograms) and...
og:url: https://daily.dev/posts/implementing-metrics-in-go-u0orxjqqt
og:image: https://api.daily.dev/og/posts/u0OrXjQqT.png
og:image:alt: Implementing metrics in Go
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Implementing metrics in Go

**[zserge's blog](https://daily.dev/sources/zserge)** · 7 min read · 0 upvotes · 0 comments

## Summary

A hands-on walkthrough of building a lightweight metrics library in Go from scratch, covering the three common metric types (counters, gauges, histograms) and how to implement each with simplified code. Explains rolling mean/min/max for gauges and an approximate histogram algorithm using bin merging. Also shows how to build timelines with multiple precisions and integrate with Go's built-in expvar package plus a small dependency-free web UI. Links to the author's own open-source implementation on GitHub and suggests using Prometheus, InfluxDB, or StatsD for larger-scale needs.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://zserge.com/posts/metrics>

## Questions this post answers

### How do you implement an approximate histogram metric in Go without storing every data point?

Use a fixed number of bins where each incoming value is inserted into a sorted slice of bins by value, and when the number of bins exceeds a maximum, the two adjacent bins with the closest values are merged into one weighted by their counts. This trades precision for constant memory usage while still showing the overall distribution shape, useful for tracking things like response time percentiles.

_daily.dev surfaces practical Go implementation patterns like this for developers building their own observability tooling._

### How can I integrate custom application metrics with Go's expvar package?

Implement a String() method on the metric type that outputs JSON, then register it with expvar.Publish(name, metric) and retrieve it later with expvar.Get(name).(metric.Metric).Add(value). This exposes the data through the standard /debug/metrics HTTP endpoint without needing external dependencies like Prometheus.

_Developers wiring up lightweight observability in Go services can find similar hands-on guides on daily.dev._

### What's the difference between a counter, a gauge, and a histogram metric?

A counter is a number that only increases, useful for counting served requests or errors. A gauge is a number that can go up or down, such as memory usage or CPU load, and typically tracks mean, min, and max per time interval. A histogram tracks percentiles, like the 95th percentile response time, which is often more meaningful than an average.

_daily.dev helps developers comparing metric types decide which fits their monitoring needs._

## Similar posts on daily.dev

- [Observability in Go: What Goes in a Metric, a Log, and a Trace](https://daily.dev/posts/observability-in-go-what-goes-in-a-metric-a-log-and-a-trace-9fz1jzl1o) · Awesome Go · 6 upvotes · 0 comments
- [OpenTelemetry Metrics .NET: Counters, Histograms, and IMeterFactory](https://daily.dev/posts/opentelemetry-metrics-net-counters-histograms-and-imeterfactory-kira4yrde) · We Are .NET · 1 upvotes · 0 comments
- [Creating and consuming metrics with System.Diagnostics.Metrics APIs](https://daily.dev/posts/creating-and-consuming-metrics-with-system-diagnostics-metrics-apis-bqo3wwbym) · .NET Escapades · 0 upvotes · 0 comments
- [Go proposal: Goroutine metrics](https://daily.dev/posts/go-proposal-goroutine-metrics-ofxbznglj) · Anton Zhiyanov · 23 upvotes · 0 comments
- [Observability in Go: Where to start and what matters most](https://daily.dev/posts/observability-in-go-where-to-start-and-what-matters-most-yxb08zvul) · Grafana Labs · 32 upvotes · 0 comments

---

Tags: [#golang](https://daily.dev/tags/golang), [#observability](https://daily.dev/tags/observability)

[View this post on daily.dev](https://daily.dev/posts/implementing-metrics-in-go-u0orxjqqt)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"Implementing metrics in Go","url":"https://daily.dev/posts/implementing-metrics-in-go-u0orxjqqt","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/implementing-metrics-in-go-u0orxjqqt"},"datePublished":"2026-08-23T10:20:17.629Z","dateModified":"2026-08-23T10:20:46.864Z","description":"A hands-on walkthrough of building a lightweight metrics library in Go from scratch, covering the three common metric types (counters, gauges, histograms) and...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/3872d1c144d1d20966d056877804d5c8?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/3872d1c144d1d20966d056877804d5c8?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"zserge's blog","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"zserge's blog","logo":"https://media.daily.dev/image/upload/s--KQnFBOIT--/f_auto,q_auto/v1787480407/logos/zserge","url":"https://daily.dev/sources/zserge"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/implementing-metrics-in-go-u0orxjqqt","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"golang,observability","timeRequired":"PT7M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"zserge's blog","item":"https://daily.dev/sources/zserge"},{"@type":"ListItem","position":3,"name":"Implementing metrics in Go"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/implementing-metrics-in-go-u0orxjqqt#faq","mainEntity":[{"@type":"Question","name":"How do you implement an approximate histogram metric in Go without storing every data point?","acceptedAnswer":{"@type":"Answer","text":"Use a fixed number of bins where each incoming value is inserted into a sorted slice of bins by value, and when the number of bins exceeds a maximum, the two adjacent bins with the closest values are merged into one weighted by their counts. This trades precision for constant memory usage while still showing the overall distribution shape, useful for tracking things like response time percentiles. daily.dev surfaces practical Go implementation patterns like this for developers building their own observability tooling."}},{"@type":"Question","name":"How can I integrate custom application metrics with Go's expvar package?","acceptedAnswer":{"@type":"Answer","text":"Implement a String() method on the metric type that outputs JSON, then register it with expvar.Publish(name, metric) and retrieve it later with expvar.Get(name).(metric.Metric).Add(value). This exposes the data through the standard /debug/metrics HTTP endpoint without needing external dependencies like Prometheus. Developers wiring up lightweight observability in Go services can find similar hands-on guides on daily.dev."}},{"@type":"Question","name":"What's the difference between a counter, a gauge, and a histogram metric?","acceptedAnswer":{"@type":"Answer","text":"A counter is a number that only increases, useful for counting served requests or errors. A gauge is a number that can go up or down, such as memory usage or CPU load, and typically tracks mean, min, and max per time interval. A histogram tracks percentiles, like the 95th percentile response time, which is often more meaningful than an average. daily.dev helps developers comparing metric types decide which fits their monitoring needs."}}]}
```

