Skip to main content
This guide walks you through creating and using a counter metric to track events in your Gleam application. You’ll learn the fundamental workflow that applies to all PromGleam metrics.

What you’ll build

By the end of this guide, you’ll have:
  • A counter metric that tracks the total number of HTTP requests
  • Code that increments the counter with labels for method, route, and status
  • An understanding of how to export metrics for Prometheus to scrape

Prerequisites

Make sure you’ve installed PromGleam in your project before continuing.

Create your first counter

1

Import the counter module

Start by importing the counter functions you’ll need:
import promgleam/metrics/counter.{create_counter, increment_counter}
2

Create a counter metric

A counter is a cumulative metric that represents a single monotonically increasing value. It can only increase or be reset to zero on restart.Create a counter to track HTTP requests:
pub fn setup_metrics() {
  let result = create_counter(
    registry: "default",
    name: "http_requests_total",
    help: "Total number of HTTP requests",
    labels: ["method", "route", "status"],
  )

  case result {
    Ok(_) -> Nil
    Error(msg) -> panic as msg
  }
}
Call this setup function once when your application starts, before handling any requests.
Let’s break down the parameters:
  • registry - The metric registry name (use "default" for most cases)
  • name - A unique identifier for your metric (use snake_case)
  • help - A description of what this metric measures
  • labels - Label names for categorizing your metrics (empty list [] if not needed)
3

Increment the counter

Now that your counter exists, you can increment it whenever an HTTP request is handled:
pub fn track_request(method: String, route: String, status: Int) {
  let result = increment_counter(
    registry: "default",
    name: "http_requests_total",
    labels: [method, route, int.to_string(status)],
    value: 1,
  )

  case result {
    Ok(_) -> Nil
    Error(msg) -> {
      // Log the error but don't crash the application
      io.println("Failed to increment counter: " <> msg)
      Nil
    }
  }
}
The number of label values must match the number of label names you specified when creating the counter. PromGleam will return an error if they don’t match.
Example usage in a request handler:
pub fn handle_request(req: Request) -> Response {
  // ... handle the request ...
  let response = wisp.ok() |> wisp.string_body("Hello, world!")

  // Track the request
  track_request("GET", "/", 200)

  response
}
4

Export metrics for Prometheus

Prometheus scrapes metrics by making HTTP requests to your application. You need to expose an endpoint that returns your metrics in a format Prometheus understands.Import the registry module:
import promgleam/registry.{print_as_text}
Create a metrics endpoint:
pub fn metrics_handler(_req: Request) -> Response {
  let body = print_as_text(registry_name: "default")

  wisp.ok()
  |> wisp.string_body(body)
}
When Prometheus scrapes /metrics, it will receive output like:
# HELP http_requests_total Total number of HTTP requests
# TYPE http_requests_total counter
http_requests_total{method="GET",route="/",status="200"} 42
http_requests_total{method="POST",route="/comments",status="201"} 15

Complete example

Here’s everything together:
import gleam/int
import gleam/io
import promgleam/metrics/counter.{create_counter, increment_counter}
import promgleam/registry.{print_as_text}

pub fn setup_metrics() {
  let assert Ok(_) = create_counter(
    registry: "default",
    name: "http_requests_total",
    help: "Total number of HTTP requests",
    labels: ["method", "route", "status"],
  )
  Nil
}

pub fn track_request(method: String, route: String, status: Int) {
  let assert Ok(_) = increment_counter(
    registry: "default",
    name: "http_requests_total",
    labels: [method, route, int.to_string(status)],
    value: 1,
  )
  Nil
}

pub fn metrics_handler(_req: Request) -> Response {
  let body = print_as_text(registry_name: "default")
  wisp.ok() |> wisp.string_body(body)
}

Understanding counters

Counters are perfect for tracking:
  • Total number of requests served
  • Number of tasks completed
  • Number of errors encountered
  • Any value that only increases over time
Don’t use counters for values that can decrease. For example, don’t use a counter for the number of active connections. Use a gauge instead.

What’s next?

You’ve successfully created your first metric! Here’s what to explore next:

Gauge metrics

Learn about metrics that can go up and down

Histogram metrics

Measure distributions and percentiles

Wisp integration

See a complete example with the Wisp web framework

Metrics overview

Learn about all metric types and best practices

Build docs developers (and LLMs) love