Documentation
¶
Overview ¶
Package peekapi provides an API analytics SDK that captures HTTP request events, buffers them in memory, and flushes them in batches to an ingestion endpoint. It includes exponential backoff on failures, disk persistence for undelivered events, and SSRF protection.
Index ¶
- Constants
- Variables
- func DefaultIdentifyConsumer(r *http.Request) string
- func HashConsumerID(raw string) string
- func IsPrivateIP(host string) bool
- func Middleware(client *Client) func(http.Handler) http.Handler
- func ResolveHost(host string) (string, error)
- type Client
- func (c *Client) BufferLen() int
- func (c *Client) Flush() error
- func (c *Client) FlushContext(ctx context.Context) error
- func (c *Client) Shutdown(ctx context.Context) error
- func (c *Client) Track(event RequestEvent)
- func (c *Client) TrackRequest(r *http.Request, statusCode, responseSize int, start time.Time)
- type Options
- type RequestEvent
Constants ¶
const DefaultEndpoint = "https://ingest.peekapi.dev/v1/events"
const Version = "0.1.0"
Version is the SDK version sent via the x-peekapi-sdk header.
Variables ¶
var ErrEventsPersisted = fmt.Errorf("peekapi: events persisted to disk, not delivered to endpoint")
ErrEventsPersisted indicates that Shutdown could not deliver events to the ingestion endpoint and they were persisted to the local disk file instead. Callers can check for this with errors.Is(err, ErrEventsPersisted).
Functions ¶
func DefaultIdentifyConsumer ¶
DefaultIdentifyConsumer extracts a consumer ID from the request using the default strategy: X-API-Key header as-is, or hashed Authorization header.
func HashConsumerID ¶
HashConsumerID hashes a raw consumer identifier (e.g. Authorization header) to a short, stable, non-reversible identifier using SHA-256.
func IsPrivateIP ¶
IsPrivateIP reports whether the given host string matches a private, loopback, or link-local IP address pattern. It checks both the string representation (regex) and the numeric value (net.IP parsing).
func Middleware ¶
Middleware returns a standard net/http middleware that captures request metrics and tracks them via the provided Client. It works with any Go HTTP router that supports the func(http.Handler) http.Handler pattern (stdlib mux, chi, gorilla, etc.).
Safety: if client is nil, the middleware is a no-op passthrough. Any panic during tracking (e.g. from a user-provided IdentifyConsumer callback) is recovered — analytics must never break the customer's API.
func ResolveHost ¶
ResolveHost resolves a hostname to its first IP address. Exported for testing.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client buffers request events and sends them to an ingestion endpoint.
func New ¶
New creates a new Client with the given options. It validates the configuration, loads any previously persisted events from disk, and starts a background goroutine for periodic flushing.
func (*Client) BufferLen ¶
BufferLen returns the current number of events in the buffer (for testing).
func (*Client) Flush ¶
Flush sends all buffered events to the ingestion endpoint. It respects in-flight and backoff guards. Flush is safe for concurrent use. Equivalent to FlushContext(context.Background()).
func (*Client) FlushContext ¶
FlushContext sends all buffered events to the ingestion endpoint with context support for cancellation and timeouts. It respects in-flight and backoff guards. FlushContext is safe for concurrent use.
Locking strategy: mu protects flush state (flushInFlight, backoff), bufMu protects buffer/spare. Track() only acquires bufMu, so it never blocks on flush state or network I/O. Lock ordering: mu -> bufMu.
func (*Client) Shutdown ¶
Shutdown gracefully stops the client: stops the background flush goroutine, flushes remaining events, and persists any undelivered events to disk. The provided context controls the shutdown timeout.
Returns ErrEventsPersisted if events could not be delivered to the ingestion endpoint and were persisted to the local disk file instead.
func (*Client) Track ¶
func (c *Client) Track(event RequestEvent)
Track adds an event to the buffer. If the buffer reaches BatchSize, a non-blocking flush is triggered. Track is safe for concurrent use.
func (*Client) TrackRequest ¶
TrackRequest builds a RequestEvent from the given request/response metadata and tracks it via the Client. It encapsulates duration calculation, consumer identification, request size extraction, and timestamp generation.
This method is used by the stdlib Middleware and the framework-specific middleware adapters (Gin, Echo) that wrap net/http under the hood.
Any panic from IdentifyConsumer or Track is recovered — analytics must never break the customer's API.
type Options ¶
type Options struct {
// APIKey is the API key used to authenticate with the ingestion endpoint (required).
APIKey string
// Endpoint is the URL of the ingestion endpoint. Default: PeekAPI cloud.
Endpoint string
// FlushInterval is the time between automatic flushes. Default: 15s.
FlushInterval time.Duration
// BatchSize is the number of events that triggers an automatic flush. Default: 250.
BatchSize int
// MaxBufferSize is the maximum number of events held in memory. Default: 10,000.
MaxBufferSize int
// Debug enables debug logging to stderr.
Debug bool
// IdentifyConsumer is an optional function to extract a consumer identifier
// from an HTTP request. If nil, the default logic uses X-API-Key or hashes
// the Authorization header.
IdentifyConsumer func(r *http.Request) string
// StoragePath is the file path for persisting undelivered events.
// Default: os.TempDir()/peekapi-events-<hash>.jsonl
StoragePath string
// MaxStorageBytes is the maximum size of the storage file. Default: 5MB.
MaxStorageBytes int64
// TLSConfig is an optional TLS configuration for the HTTP client.
TLSConfig *tls.Config
// CollectQueryString includes sorted query parameters in the tracked path.
// NOTE: increases DB usage — each unique path+query creates a separate endpoint row.
CollectQueryString bool
// OnError is an optional callback invoked when the background flush loop
// encounters an error (network failure, non-retryable status, etc.).
// Called from the background goroutine — implementations must be safe for
// concurrent use and should not block.
OnError func(err error)
}
Options configures the API dashboard client.
type RequestEvent ¶
type RequestEvent struct {
Method string `json:"method"`
Path string `json:"path"`
StatusCode int `json:"status_code"`
ResponseTimeMs float64 `json:"response_time_ms"`
RequestSize int `json:"request_size"`
ResponseSize int `json:"response_size"`
ConsumerID string `json:"consumer_id,omitempty"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
Timestamp string `json:"timestamp"`
}
RequestEvent represents a single captured API request.