trend

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 13, 2026 License: MIT Imports: 16 Imported by: 0

README

kelindar/trend
Go Version PkgGoDev Go Report Card License Coverage

Trend: Small Time-Series Store for Go

Trend stores float64 samples, unsigned counters, and sketches behind a small byte-store interface. It is meant for embedded or service-local time-series data where simple writes, mergeable state, iterator reads, and compact storage are enough.

It keeps recent raw points, can compact older points into buckets, and serializes state with a compact binary format compressed with S2.

  • Samples: Last-write-wins float64 values.
  • Counters: Grow-only unsigned counter deltas.
  • Sketches: Exact recent observations with compact approximate quantiles.
  • Reads: Values and Range return Go iterators.
  • Storage: Pluggable stores registered by URI scheme.

Use When

  • You need simple local time-series storage inside a Go service.
  • You want separate APIs for samples, counters, and sketches.
  • You want compact serialized state without running a metrics database.

Not For

  • High-cardinality metrics ingestion at Prometheus/TSDB scale.
  • Distributed query engines, retention policies, or alerting.
  • Interoperable on-disk formats.

Quick Start

package main

import (
	"context"
	"fmt"
	"time"

	"github.com/kelindar/trend"
	_ "github.com/kelindar/trend/storage/buntdb"
)

func main() {
	ctx := context.Background()

	db, err := trend.Open("buntdb:///:memory:")
	if err != nil {
		panic(err)
	}
	defer db.Close()

	now := time.Now()
	_ = db.Samples("cpu").Set(ctx, now, 0.42)
	_ = db.Counters("requests").Add(ctx, now, 1)
	_ = db.Sketches("latency").Add(ctx, now, 12.5)

	values, _ := db.Samples("cpu").Values(ctx, now.Add(-time.Minute), now)
	for at, value := range values {
		fmt.Println(at, value)
	}
}

API Highlights

  • Open(uri string, opts ...Option): Open a registered storage adapter.
  • New(store Store, opts ...Option): Use an existing store implementation.
  • Samples(key).Set(ctx, at, value): Store a float64 sample.
  • Samples(key).Values(ctx, from, to): Iterate raw sample values.
  • Samples(key).Range(ctx, from, to, span, agg): Iterate bucketed sample aggregates.
  • Counters(key).Add(ctx, at, delta): Store an unsigned counter delta.
  • Counters(key).Values(ctx, from, to): Iterate counter values.
  • Counters(key).Range(ctx, from, to, span, agg): Iterate bucketed counter aggregates.
  • Sketches(key).Add(ctx, at, value): Store one finite float64 observation.
  • Sketches(key).Values(ctx, from, to): Iterate sketches at retained resolution.
  • Sketches(key).Range(ctx, from, to, span): Iterate merged sketch buckets.
  • Compact(ctx): Compact old points using the configured window.

Storage

Stores implement a byte-oriented update interface:

type Store interface {
	Load(context.Context, string) ([]byte, error)
	Update(context.Context, string, func([]byte) ([]byte, error)) error
	Delete(context.Context, string) error
	Close() error
}

Adapters register by URI scheme. Import the adapter package for registration:

import (
	_ "github.com/kelindar/trend/storage/buntdb"
	_ "github.com/kelindar/trend/storage/redis"
	_ "github.com/kelindar/trend/storage/sqlite"
)

Benchmarks

name             time/op   ops/s    allocs/op
samples/append   327.9 us  3.0K     10
samples/range    177.9 us  5.6K     4
samples/values   95.0 us   10.5K    4
counters/append  286.4 us  3.5K     9
counters/range   100.7 us  9.9K     4
counters/values  78.6 us   12.7K    4

Numbers are from local 10K element DB-backed benchmarks on an Intel i7-13700K.

About

Trend is MIT licensed and maintained by @kelindar.

PRs and issues welcome.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Register

func Register(scheme string, open func(*url.URL) (Store, error))

Register registers a storage adapter.

Types

type Agg

type Agg uint8

Agg identifies a fixed aggregation.

const (
	Sum Agg = iota
	Count
	Min
	Max
	Mean
	First
	Last
)

type Counters

type Counters struct {
	// contains filtered or unexported fields
}

Counters writes and reads grow-only counters.

func (Counters) Add

func (c Counters) Add(ctx context.Context, at time.Time, delta uint64) error

Add stores a positive counter delta.

func (Counters) Compact

func (c Counters) Compact(ctx context.Context) error

Compact compacts this series.

func (Counters) Range

func (c Counters) Range(ctx context.Context, from, to time.Time, span time.Duration, agg Agg) (iter.Seq2[time.Time, float64], error)

Range returns bucketed aggregate values.

func (Counters) Values

func (c Counters) Values(ctx context.Context, from, to time.Time) (iter.Seq2[time.Time, float64], error)

Values returns exact counter values where raw data is still retained.

type DB

type DB struct {
	// contains filtered or unexported fields
}

DB stores time-series samples, counters, and sketches.

func New

func New(store Store, opts ...Option) (*DB, error)

New creates a DB over an existing store.

func Open

func Open(uri string, opts ...Option) (*DB, error)

Open opens a registered store URI.

func (*DB) Close

func (db *DB) Close() error

Close flushes pending writes and closes resources.

func (*DB) Counters

func (db *DB) Counters(key string) Counters

Counters returns a counter series handle.

func (*DB) Flush

func (db *DB) Flush(ctx context.Context) error

Flush writes buffered deltas.

func (*DB) Samples

func (db *DB) Samples(key string) Samples

Samples returns a sample series handle.

func (*DB) Sketches added in v0.2.0

func (db *DB) Sketches(key string) Sketches

Sketches returns a sketch series handle.

type Option

type Option func(*DB) error

Option configures a DB.

func WithCompaction

func WithCompaction(after, span time.Duration) Option

WithCompaction enables lossy compaction of raw values older than after.

func WithCompactor

func WithCompactor(every, jitter time.Duration) Option

WithCompactor starts a jittered background compactor for keys seen locally.

func WithFlushEvery

func WithFlushEvery(every time.Duration) Option

WithFlushEvery buffers writes in memory and flushes them periodically.

func WithReplica

func WithReplica(id string) Option

WithReplica sets a stable replica identifier.

type Samples

type Samples struct {
	// contains filtered or unexported fields
}

Samples writes and reads float64 samples.

func (Samples) Compact

func (s Samples) Compact(ctx context.Context) error

Compact compacts this series.

func (Samples) Range

func (s Samples) Range(ctx context.Context, from, to time.Time, span time.Duration, agg Agg) (iter.Seq2[time.Time, float64], error)

Range returns bucketed aggregate values.

func (Samples) Set

func (s Samples) Set(ctx context.Context, at time.Time, value float64) error

Set stores a sample using LWW CRDT semantics.

func (Samples) Values

func (s Samples) Values(ctx context.Context, from, to time.Time) (iter.Seq2[time.Time, float64], error)

Values returns exact values where raw data is still retained.

type Sketch added in v0.2.0

type Sketch struct {
	// contains filtered or unexported fields
}

Sketch is an immutable encoded distribution.

func (Sketch) Count added in v0.2.0

func (h Sketch) Count() uint64

Count returns the number of observations.

func (Sketch) Max added in v0.2.0

func (h Sketch) Max() float64

Max returns the largest observation, or NaN when empty.

func (Sketch) Mean added in v0.2.0

func (h Sketch) Mean() float64

Mean returns the arithmetic mean, or NaN when empty.

func (Sketch) Min added in v0.2.0

func (h Sketch) Min() float64

Min returns the smallest observation, or NaN when empty.

func (Sketch) Quantile added in v0.2.0

func (h Sketch) Quantile(q float64) float64

Quantile returns the nearest-rank quantile, or NaN for an invalid quantile.

func (Sketch) Sum added in v0.2.0

func (h Sketch) Sum() float64

Sum returns the sum of observations.

type Sketches added in v0.2.0

type Sketches struct {
	// contains filtered or unexported fields
}

Sketches writes and reads distributions of float64 observations.

func (Sketches) Add added in v0.2.0

func (h Sketches) Add(ctx context.Context, at time.Time, value float64) error

Add stores one observation.

func (Sketches) Compact added in v0.2.0

func (h Sketches) Compact(ctx context.Context) error

Compact compacts this series.

func (Sketches) Range added in v0.2.0

func (h Sketches) Range(ctx context.Context, from, to time.Time, span time.Duration) (iter.Seq2[time.Time, Sketch], error)

Range returns sketches merged into time buckets.

func (Sketches) Values added in v0.2.0

func (h Sketches) Values(ctx context.Context, from, to time.Time) (iter.Seq2[time.Time, Sketch], error)

Values returns sketches at the finest retained resolution.

type Store

type Store interface {
	Load(context.Context, string) ([]byte, error)
	Update(context.Context, string, func([]byte) ([]byte, error)) error
	Delete(context.Context, string) error
	Close() error
}

Store is the atomic byte store used by trend.

Directories

Path Synopsis
Package machine identifies the current process for replica tags.
Package machine identifies the current process for replica tags.
storage
cached
Package cached adds a read-through cache to a store.
Package cached adds a read-through cache to a store.
memory module
sqlite module

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL