synthdata

package
v0.0.0-...-acbe8ed Latest Latest
Warning

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

Go to latest
Published: Sep 8, 2026 License: AGPL-3.0 Imports: 6 Imported by: 0

Documentation

Overview

Package synthdata generates synthetic historical check results.

It exists so two very different callers can share one generator: the test-only `POST /api/v1/test/generate-data` endpoint (which is how this code started life, in internal/handlers/testapi), and the public live demo's one-shot 30-day backfill at seed time (spec 2026-09-06-02), which needs the same shapes but has no HTTP request, no handler and no test-mode gate.

Deliberately free of HTTP, of the job system and of anything testapi-shaped: it takes a period, a window and a failure model, and writes rows.

Index

Constants

View Source
const DefaultMaxResults = 200_000

DefaultMaxResults bounds a single Generate call. 200k rows is roughly 30 days at a 15-second period — comfortably more than any legitimate caller needs, and far short of "wedge the database".

Variables

This section is empty.

Functions

func Generate

func Generate(ctx context.Context, writer ResultWriter, opts *Options) (int, error)

Generate writes synthetic raw results for one check and returns how many rows it created. It stops early — without an error — at the MaxResults ceiling.

func Simulate

func Simulate(
	rng *rand.Rand, opts *Options, avgDurationMs float64, timestamp time.Time,
) (models.ResultStatus, float32)

Simulate produces one sample's status and duration.

Exported so a caller can unit-test the failure model without a database. With FailureBurstSec set the outage pattern is DETERMINISTIC in the sample's wall-clock time — the same second always produces the same verdict — which is what makes multi-region synthetic history agree with itself instead of showing three unrelated random walks.

Types

type Options

type Options struct {
	// OrganizationUID and CheckUID identify the rows written.
	OrganizationUID string
	CheckUID        string
	// Region is stamped on every generated row. Empty means "default".
	Region string
	// Start is the beginning of the synthesized window; End its exclusive end
	// (zero means "now").
	Start time.Time
	End   time.Time
	// Period is the interval between generated results. Must be > 0.
	Period time.Duration
	// AvgDurationMs is the mean response time; each sample is drawn around it
	// with a 20% standard deviation.
	AvgDurationMs float64
	// FailureRate is the fraction of time spent down, in [0, 1]. Zero means a
	// perfectly healthy history.
	FailureRate float64
	// FailureBurstSec, when > 0, turns FailureRate into CLUSTERED outages of
	// this length rather than independent per-sample coin flips — which is
	// what makes a chart look like a real incident instead of static.
	FailureBurstSec int
	// Seed makes a run reproducible. Zero uses the wall clock.
	Seed int64
	// MaxResults bounds one run. Zero means the default ceiling. It is a
	// guardrail, not a tuning knob: a caller that asks for a year of 10-second
	// samples is asking for three million inserts, and the honest answer is to
	// stop rather than to spend an hour writing them.
	MaxResults int
}

Options describes the history to synthesize for ONE check.

type ResultWriter

type ResultWriter interface {
	CreateResults(ctx context.Context, results []*models.Result) error
}

ResultWriter is the slice of the database service this package needs. Narrow on purpose: a generator that could reach the whole db.Service would invite it to start creating checks and orgs too, which is the caller's job.

Batched rather than row-at-a-time: 30 days of history across a dozen checks is tens of thousands of rows, and one INSERT each turned the demo's seed into a forty-second startup pause.

Jump to

Keyboard shortcuts

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