Skip to content

Quickstart

This guide gets Unimeter running on your machine, then walks through defining a metric, sending a handful of events, and reading the usage total back. By the end you will have a working integration you can adapt to your real application.

You need Docker installed to run the Unimeter server, and either Go or Python to run the client code.

Clone the server repository, build the image, and start a single-node instance.

Terminal window
git clone https://github.com/unimeter/unimeter.git
cd server
docker build -t unimeter .
docker run -d --name unimeter -p 7001:7001 -p 9090:9090 unimeter

The build takes a minute or two on the first run. After that, Unimeter listens on port 7001 for application traffic and port 9090 for health checks. Verify it is alive by asking for its health status.

Terminal window
curl http://localhost:9090/health

A successful response looks like {"status":"ok","uptime_seconds":3}. If you see that, Unimeter is running and ready to accept events.

Create a new project and install the Unimeter client library.

Terminal window
mkdir billing-demo && cd billing-demo
go mod init billing-demo
go get github.com/unimeter/go-unimeter@latest

A metric describes something you want to count, like API calls or bytes transferred. Before sending events, you tell Unimeter what the metric is called and how it should count. In this quickstart we define a metric called api_calls that simply counts one unit per event.

Create a file called main.go with the following content.

package main
import (
"context"
"fmt"
"log"
billing "github.com/unimeter/go-unimeter"
)
func main() {
client, err := billing.New([]string{"localhost:7001"})
if err != nil {
log.Fatal(err)
}
defer client.Close()
ctx := context.Background()
err = client.Metrics.Create(ctx, billing.MetricSchema{
Code: "api_calls",
AggType: billing.AggCount,
})
if err != nil {
log.Fatal(err)
}
fmt.Println("metric created")
}

Run it with go run .. You should see metric created.

If the metric already exists from a previous run, you can ignore the error; the call is safe to repeat.

Now that the metric exists, send a few events. Three for account 1 and one for account 2.

Replace the body of main with the following, keeping the imports and the client setup at the top.

events := []billing.Event{
{AccountID: 1, MetricCode: "api_calls", Value: 1},
{AccountID: 1, MetricCode: "api_calls", Value: 1},
{AccountID: 1, MetricCode: "api_calls", Value: 1},
{AccountID: 2, MetricCode: "api_calls", Value: 1},
}
result, err := client.Ingest(ctx, events)
if err != nil {
log.Fatal(err)
}
fmt.Printf("stored %d events\n", result.NStored)

Run it with go run .. You should see stored 4 events.

Unimeter persisted the events to disk, replicated them within the cluster (a cluster of one in this case), and updated its in-memory totals.

Querying is the reverse of recording. You tell Unimeter which account and metric you care about, and for what period, and it returns the total.

Add this at the end of main.

usage, err := client.Query(ctx, billing.QueryRequest{
AccountID: 1,
MetricCode: "api_calls",
Period: billing.CurrentMonth(),
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("account 1 used api_calls %d times this month\n", usage.Value.Count)

Run it again with go run ..

The first three events from account 1 produced a total of three, matching what you sent. Account 2 sent one event, so querying for account 2 would return one.

This is the full loop. You defined a metric, sent events, and got a total back. Everything else you might want to do with Unimeter builds on this pattern.

To understand the different counting modes (counting, summing, taking the maximum, tracking unique values), read Metric types.

To see how to tag events with dimensions like region or feature name and query them separately, read Filters and dimensions.

When you are ready to run Unimeter in production with multiple nodes and failover, see Running a cluster.

When you are done experimenting, stop Unimeter and remove its data.

Terminal window
docker stop unimeter && docker rm unimeter

This removes the container that held your events.