simv

module
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Jan 26, 2026 License: MIT

README

simV

A Go library for simulating time-varying values in testing environments.

Overview

simV provides thread-safe entities representing different types of time-varying values, enabling developers to create realistic simulated metrics and time-series data for system validation.

Use cases:

  • Testing OTEL/Prometheus metric pipelines
  • Validating observability systems
  • Simulating realistic load patterns
  • Mocking external metric sources during development
  • Creating observable test fixtures with temporal behavior

Installation

go get github.com/neox5/simv@latest

Requirements: Go 1.25+

Quick Start

package main

import (
    "fmt"
    "time"

    "github.com/neox5/simv/clock"
    "github.com/neox5/simv/seed"
    "github.com/neox5/simv/source"
    "github.com/neox5/simv/transform"
    "github.com/neox5/simv/value"
)

func main() {
    // Initialize seed (required)
    // Use explicit seed for repeatable simulations:
    seed.Init(12345)
    // Or use time-based seed for non-repeatable behavior:
    // seed.Init(uint64(time.Now().UnixNano()))

    // Create clock that ticks every 100ms
    clk := clock.NewPeriodicClock(100 * time.Millisecond)

    // Create source that generates random integers [1, 10]
    src := source.NewRandomIntSource(clk, 1, 10)

    // Create value with accumulate transform and reset-on-read
    val := value.New(src).
        AddTransform(transform.NewAccumulate[int]()).
        EnableResetOnRead(0).
        SetUpdateHook(value.NewDefaultTraceHook[int]())

    // Start the value (locks configuration)
    val.Start()
    defer val.Stop()

    // Start the clock
    clk.Start()
    defer clk.Stop()

    // Read current value (resets to 0 after read)
    current := val.Value()
    fmt.Printf("Current value: %d\n", current)

    // Access metrics without side effects
    stats := val.Stats()
    fmt.Printf("Updates: %d, Current: %d\n",
        stats.UpdateCount,
        stats.CurrentValue,
    )
}

Architecture

simV uses a pipeline architecture:

ClockSourceTransformValue

  • Clock: Generates timing signals at fixed intervals
  • Source: Produces values on each clock tick
  • Transform: Modifies values (accumulate, average, etc.)
  • Value: Manages state and provides thread-safe access

Core Concepts

Seed

Control repeatability of random value generation.

### Seed

Control repeatability of random value generation. Must be called before creating any sources.
```go
// Repeatable simulations - same seed produces identical sequences
seed.Init(12345)

// Non-repeatable behavior - use time-based seed
seed.Init(uint64(time.Now().UnixNano()))
```

### Clock

Provides timing signals for value generation.

```go
clk := clock.NewPeriodicClock(100 * time.Millisecond)
clk.Start()
defer clk.Stop()

// Access metrics
stats := clk.Stats()
fmt.Printf("Ticks: %d, Running: %v\n", stats.TickCount, stats.IsRunning)
```

### Source

Generates values driven by clock ticks.

```go
// Constant value
constSrc := source.NewConstSource(clk, 42)

// Random integers
randomSrc := source.NewRandomIntSource(clk, 1, 100)

// Access metrics
stats := randomSrc.Stats()
fmt.Printf("Generated: %d, Subscribers: %d\n",
    stats.GenerationCount,
    stats.SubscriberCount,
)
```

### Transform

Applies operations to incoming values.

```go
// Running total
val.AddTransform(transform.NewAccumulate[int]())
```

### Value

Thread-safe value management with configurable behaviors.

```go
// Create value (configuration phase)
val := value.New(src).
    AddTransform(transform.NewAccumulate[int]()).
    EnableResetOnRead(0).
    SetUpdateHook(value.NewDefaultTraceHook[int]())

// Start value (locks configuration, begins updates)
val.Start()
defer val.Stop()

// Read value
current := val.Value()

// Access metrics without side effects
stats := val.Stats()
fmt.Printf("Updates: %d, Current: %d, Transforms: %d\n",
    stats.UpdateCount,
    stats.CurrentValue,
    stats.TransformCount,
)
```

**Important:** Configuration methods (AddTransform, EnableResetOnRead) panic if called after Start().

### Multiple Values from Same Source

Create independent values that receive the same source stream:

```go
src := source.NewRandomIntSource(clk, 1, 10)

// Value A: Running total (never resets)
valueA := value.New(src).
    AddTransform(transform.NewAccumulate[int]()).
    Start()

// Value B: Delta counter (resets on each read)
valueB := value.New(src).
    AddTransform(transform.NewAccumulate[int]()).
    EnableResetOnRead(0).
    Start()
```

Both values maintain independent state while receiving the same random integers.

## Observability

### Metrics

All components expose metrics via `Stats()` methods for integration with Prometheus/OTEL:

```go
// Clock metrics
clockStats := clk.Stats()
// - TickCount: total ticks generated
// - IsRunning: current operational state
// - Interval: tick rate

// Source metrics
sourceStats := src.Stats()
// - GenerationCount: total values produced
// - SubscriberCount: active subscriptions

// Value metrics
valueStats := val.Stats()
// - UpdateCount: total updates received
// - CurrentValue: current value without side effects
// - TransformCount: number of transforms in chain
```

**Prometheus example:**

```go
tickCounter := prometheus.NewCounter(...)
stats := clk.Stats()
tickCounter.Add(float64(stats.TickCount))
```

### Tracing

Enable trace output to observe value flow through the pipeline:

```go
val.SetUpdateHook(value.NewDefaultTraceHook[int]())
// Output: [15:04:05.000] 7 | Accumulate(s:42) | 49
```

## Features

- Generic type support
- Thread-safe concurrent access
- Explicit lifecycle management (construct → configure → start)
- Atomic reset-on-read (no data loss)
- Subscription-based value distribution
- Composable transform pipeline
- Observable update cycles via hooks
- Metrics exposure for monitoring systems
- Repeatable simulations via seed control
- Zero external dependencies

## Examples

See `cmd/example/main.go` for complete working example.

## License

MIT License - see LICENSE file for details.

Directories

Path Synopsis
cmd
example command

Jump to

Keyboard shortcuts

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