A fast, resilient, and scalable event-tracking SDK built in Go.
- Zero Dependencies – Built entirely with Go standard library
- Thread-Safe – Concurrent event tracking with mutex protection
- Automatic Batching – Efficient event grouping for network optimization
- Retry Logic – Exponential backoff with jitter for failed requests
- Event Persistence – Disk-backed storage for reliability
- Graceful Shutdown – Ensures all events are flushed and persisted
- Pluggable Adapters – Custom HTTP and storage implementations
go get github.com/Tap30/ripple-gopackage main
import (
"time"
ripple "github.com/Tap30/ripple-go"
)
func main() {
client := ripple.NewClient(ripple.ClientConfig{
APIKey: "your-api-key",
Endpoint: "https://api.example.com/events",
})
if err := client.Init(); err != nil {
panic(err)
}
defer client.Dispose()
// Set global context
client.SetContext("userId", "123")
client.SetContext("appVersion", "1.0.0")
// Track events
client.Track("page_view", map[string]interface{}{
"page": "/home",
}, nil)
// Track with metadata
client.Track("user_action", map[string]interface{}{
"button": "submit",
}, &ripple.EventMetadata{
SchemaVersion: "1.0.0",
})
// Manually flush
client.Flush()
}type ClientConfig struct {
APIKey string // Required: API authentication key
Endpoint string // Required: Event collection endpoint
FlushInterval time.Duration // Optional: Default 5s
MaxBatchSize int // Optional: Default 10
MaxRetries int // Optional: Default 3
}Initializes the client and starts the dispatcher. Must be called before tracking events.
Tracks an event with optional payload and metadata.
Sets a global context value that will be attached to all events.
Returns a copy of the current global context.
Manually triggers a flush of all queued events.
Gracefully shuts down the client, flushing and persisting all events.
Implement the HTTPAdapter interface to use custom HTTP clients:
import (
ripple "github.com/Tap30/ripple-go"
"github.com/Tap30/ripple-go/adapters"
)
type MyHTTPAdapter struct {
// custom fields
}
func (a *MyHTTPAdapter) Send(endpoint string, events []adapters.Event, headers map[string]string) (*adapters.HTTPResponse, error) {
// custom HTTP logic
return &adapters.HTTPResponse{OK: true, Status: 200}, nil
}
// Use custom adapter
client := ripple.NewClient(config)
client.SetHTTPAdapter(&MyHTTPAdapter{})
client.Init()Implement the StorageAdapter interface to use custom storage backends:
import (
ripple "github.com/Tap30/ripple-go"
"github.com/Tap30/ripple-go/adapters"
)
type RedisStorage struct {
// Redis client
}
func (r *RedisStorage) Save(events []adapters.Event) error {
// Save to Redis
return nil
}
func (r *RedisStorage) Load() ([]adapters.Event, error) {
// Load from Redis
return nil, nil
}
func (r *RedisStorage) Clear() error {
// Clear Redis storage
return nil
}
// Use custom adapter
client := ripple.NewClient(config)
client.SetStorageAdapter(&RedisStorage{})
client.Init()The SDK consists of several key components:
- Client – Public API and context management
- Dispatcher – Event batching, flushing, and retry logic
- Queue – Thread-safe FIFO event queue
- HTTP Adapter – Network communication layer
- Storage Adapter – Event persistence layer
See ONBOARDING.md for detailed architecture documentation.
See the
API Contract Documentation
for details on the shared, framework-independent interface all Ripple SDKs follow.
go test ./...go test -cover ./...cd examples/basic
go run main.goTest the SDK with a local server:
# Terminal 1: Start server
cd playground
make server
# Terminal 2: Run client
cd playground
make clientSee playground/README.md for more details.
Check the
contributing guide
for information on development workflow, proposing improvements, and running tests.
Distributed under the
MIT license.