productgraph

package
v0.7.0 Latest Latest
Warning

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

Go to latest
Published: May 10, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package productgraph provides a client for sending events to ProductGraph and middleware for frontend-backend correlation.

Package productgraph provides a client for sending telemetry events to ProductGraph and middleware for frontend-backend correlation.

Overview

ProductGraph is a product analytics platform that collects and analyzes user behavior events from both frontend and backend systems. This package enables Go services to:

  • Send events to ProductGraph with batching and async dispatch
  • Correlate backend requests with frontend sessions
  • Track API calls, errors, and journey steps

Quick Start

// Create client
client, err := productgraph.New(productgraph.Config{
    ProjectID: "my-project",
    Endpoint:  "https://api.productgraph.io/v1/events",
    APIKey:    os.Getenv("PRODUCTGRAPH_API_KEY"),
})
if err != nil {
    log.Fatal(err)
}
defer client.Close()

// Use middleware for automatic tracking
r := chi.NewRouter()
r.Use(productgraph.ChainMiddleware(client))

// Or track events manually
client.TrackAPICall(ctx, "POST", "/checkout", 200, 150*time.Millisecond)
client.TrackJourneyStep(ctx, "checkout_flow", "payment", "Enter Payment")
client.TrackError(ctx, "ValidationError", "invalid card number")

Correlation

The CorrelationMiddleware extracts frontend correlation headers and injects them into the request context:

  • X-Session-ID: Frontend session identifier
  • X-Request-ID: Per-request identifier (generated if not provided)
  • X-User-ID: Authenticated user identifier

Use SessionIDFromContext, RequestIDFromContext, and UserIDFromContext to retrieve these values in your handlers.

Event Types

ProductGraph supports various event types following OTel semantic conventions:

  • page.view, page.leave: Page navigation
  • ui.click, ui.input, ui.scroll, ui.submit: User interactions
  • state.change: Application state changes
  • api.request, api.response: API calls
  • journey.step: User journey progression
  • error: Application errors
  • performance: Performance metrics

Configuration

Use ConfigFromEnv to load configuration from environment variables:

  • PRODUCTGRAPH_PROJECT_ID: Project identifier
  • PRODUCTGRAPH_ENDPOINT: API endpoint
  • PRODUCTGRAPH_API_KEY: Authentication key
  • PRODUCTGRAPH_BATCH_SIZE: Events per batch (default: 50)
  • PRODUCTGRAPH_BATCH_INTERVAL: Flush interval in seconds (default: 5)
  • PRODUCTGRAPH_DEBUG: Enable debug logging

Index

Constants

View Source
const (
	// HeaderSessionID is the HTTP header for session ID from frontend.
	HeaderSessionID = "X-Session-ID"
	// HeaderRequestID is the HTTP header for request ID.
	HeaderRequestID = "X-Request-ID"
	// HeaderUserID is the HTTP header for user ID.
	HeaderUserID = "X-User-ID"
)

Variables

View Source
var (
	ErrMissingProjectID = errors.New("productgraph: missing project_id")
	ErrMissingEndpoint  = errors.New("productgraph: missing endpoint")
	ErrClientClosed     = errors.New("productgraph: client is closed")
)

Common errors.

Functions

func ChainMiddleware

func ChainMiddleware(client *Client) func(http.Handler) http.Handler

ChainMiddleware chains correlation and request tracking middleware. This is a convenience function that applies both middlewares in the correct order: 1. CorrelationMiddleware - extracts session/request IDs 2. RequestTrackerMiddleware - tracks API calls with correlation

func CorrelationMiddleware

func CorrelationMiddleware(next http.Handler) http.Handler

CorrelationMiddleware extracts correlation headers from incoming requests and injects them into the request context. It also generates a request ID if not provided and echoes it back in the response.

func RequestIDFromContext

func RequestIDFromContext(ctx context.Context) string

RequestIDFromContext extracts the request ID from context. Returns empty string if not present.

func RequestTrackerMiddleware

func RequestTrackerMiddleware(client *Client) func(http.Handler) http.Handler

RequestTrackerMiddleware creates middleware that tracks HTTP requests to ProductGraph. It records api.response events with method, path, status code, and duration.

func SessionIDFromContext

func SessionIDFromContext(ctx context.Context) string

SessionIDFromContext extracts the session ID from context. Returns empty string if not present.

func UserIDFromContext

func UserIDFromContext(ctx context.Context) string

UserIDFromContext extracts the user ID from context. Returns empty string if not present.

func WithRequestID

func WithRequestID(ctx context.Context, requestID string) context.Context

WithRequestID returns a new context with the request ID set.

func WithSessionID

func WithSessionID(ctx context.Context, sessionID string) context.Context

WithSessionID returns a new context with the session ID set.

func WithUserID

func WithUserID(ctx context.Context, userID string) context.Context

WithUserID returns a new context with the user ID set.

Types

type Client

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

Client sends events to ProductGraph with batching and async dispatch.

func MustNew

func MustNew(cfg Config) *Client

MustNew creates a new ProductGraph client and panics on error.

func New

func New(cfg Config) (*Client, error)

New creates a new ProductGraph client. Returns an error if the configuration is invalid.

func (*Client) Close

func (c *Client) Close() error

Close gracefully shuts down the client, flushing any remaining events.

func (*Client) Config

func (c *Client) Config() Config

Config returns the client configuration.

func (*Client) Flush

func (c *Client) Flush(ctx context.Context) error

Flush forces all buffered events to be sent immediately.

func (*Client) IsEnabled

func (c *Client) IsEnabled() bool

IsEnabled returns true if the client is configured and ready.

func (*Client) SetLogger

func (c *Client) SetLogger(logger *slog.Logger)

SetLogger sets the logger for the client.

func (*Client) Track

func (c *Client) Track(ctx context.Context, event Event) error

Track queues an event for dispatch to ProductGraph. The event is buffered and sent asynchronously in batches.

func (*Client) TrackAPICall

func (c *Client) TrackAPICall(ctx context.Context, method, path string, statusCode int, duration time.Duration) error

TrackAPICall is a convenience method for tracking API calls.

func (*Client) TrackError

func (c *Client) TrackError(ctx context.Context, errType, message string) error

TrackError is a convenience method for tracking errors.

func (*Client) TrackJourneyStep

func (c *Client) TrackJourneyStep(ctx context.Context, journeyID, stepID, stepName string) error

TrackJourneyStep is a convenience method for tracking journey steps.

type Config

type Config struct {
	// ProjectID is the ProductGraph project identifier (required).
	ProjectID string

	// Endpoint is the ProductGraph API endpoint (required).
	// Example: "https://api.productgraph.io/v1/events"
	Endpoint string

	// APIKey is the API key for authentication (optional).
	// Sent as X-PG-API-Key header.
	APIKey string

	// BatchSize is the number of events to buffer before flushing.
	// Default: 50
	BatchSize int

	// BatchInterval is the maximum time to wait before flushing buffered events.
	// Default: 5 seconds
	BatchInterval time.Duration

	// HTTPClient is the HTTP client to use for requests.
	// Default: http.DefaultClient with 10s timeout
	HTTPClient *http.Client

	// Debug enables debug logging.
	Debug bool
}

Config holds ProductGraph client configuration.

func ConfigFromEnv

func ConfigFromEnv() Config

ConfigFromEnv creates a Config from environment variables.

Environment variables:

  • PRODUCTGRAPH_PROJECT_ID: Project identifier (required)
  • PRODUCTGRAPH_ENDPOINT: API endpoint (required)
  • PRODUCTGRAPH_API_KEY: API key for authentication
  • PRODUCTGRAPH_BATCH_SIZE: Events per batch (default: 50)
  • PRODUCTGRAPH_BATCH_INTERVAL: Flush interval in seconds (default: 5)
  • PRODUCTGRAPH_DEBUG: Enable debug logging (true/false)

func (Config) IsEnabled

func (c Config) IsEnabled() bool

IsEnabled returns true if ProductGraph integration is configured.

func (Config) Validate

func (c Config) Validate() error

Validate returns an error if the configuration is invalid.

func (Config) WithDefaults

func (c Config) WithDefaults() Config

WithDefaults returns a copy of the config with default values applied.

type ContextKey

type ContextKey string

ContextKey is used for storing correlation values in context.

const (
	// SessionIDKey is the context key for session ID.
	SessionIDKey ContextKey = "productgraph.session_id"
	// RequestIDKey is the context key for request ID.
	RequestIDKey ContextKey = "productgraph.request_id"
	// UserIDKey is the context key for user ID.
	UserIDKey ContextKey = "productgraph.user_id"
)

type Event

type Event struct {
	// Identity
	EventID   string `json:"event_id"`
	ProjectID string `json:"project_id"`
	SessionID string `json:"session.id"`
	UserID    string `json:"user.id,omitempty"`

	// Event classification
	EventType EventType `json:"event.type"`
	EventName string    `json:"event.name,omitempty"`
	Timestamp string    `json:"event.timestamp"`
	Sequence  int       `json:"event.sequence,omitempty"`

	// Page context
	PagePath     string `json:"page.path,omitempty"`
	PageTitle    string `json:"page.title,omitempty"`
	PageURL      string `json:"page.url,omitempty"`
	PageReferrer string `json:"page.referrer,omitempty"`

	// UI context
	UIComponentName string `json:"ui.component.name,omitempty"`
	UIComponentPath string `json:"ui.component.path,omitempty"`
	UIComponentType string `json:"ui.component.type,omitempty"`
	UIAction        string `json:"ui.action,omitempty"`
	UIElement       string `json:"ui.element,omitempty"`
	UIElementText   string `json:"ui.element.text,omitempty"`

	// State changes
	UIStateKey    string `json:"ui.state.key,omitempty"`
	UIStateBefore string `json:"ui.state.before,omitempty"`
	UIStateAfter  string `json:"ui.state.after,omitempty"`

	// Journey tracking
	JourneyID   string `json:"gen_ai.journey.id,omitempty"`
	JourneyStep string `json:"gen_ai.journey.step.id,omitempty"`
	JourneyName string `json:"gen_ai.journey.step.name,omitempty"`

	// API tracking
	APIMethod     string `json:"api.method,omitempty"`
	APIPath       string `json:"api.path,omitempty"`
	APIStatusCode int    `json:"api.status_code,omitempty"`
	APIDurationMs int    `json:"api.duration_ms,omitempty"`

	// Error tracking
	ErrorType    string `json:"error.type,omitempty"`
	ErrorMessage string `json:"error.message,omitempty"`
	ErrorStack   string `json:"error.stack,omitempty"`

	// Performance
	DurationMs int `json:"duration_ms,omitempty"`

	// Organization
	OrgID   string `json:"org.id,omitempty"`
	OrgName string `json:"org.name,omitempty"`

	// Custom metadata
	Metadata map[string]any `json:"metadata,omitempty"`
}

Event represents a ProductGraph event following OTel semantic conventions.

func APIResponseEvent

func APIResponseEvent(method, path string, statusCode int, durationMs int) Event

APIResponseEvent creates an event for tracking an API response.

func ErrorEvent

func ErrorEvent(errType, message string) Event

ErrorEvent creates an event for tracking an error.

func JourneyStepEvent

func JourneyStepEvent(journeyID, stepID, stepName string) Event

JourneyStepEvent creates an event for tracking a journey step.

func NewEvent

func NewEvent(eventType EventType) Event

NewEvent creates a new Event with required fields populated.

type EventType

type EventType string

EventType represents the type of ProductGraph event.

const (
	// Page events
	EventTypePageView  EventType = "page.view"
	EventTypePageLeave EventType = "page.leave"

	// UI events
	EventTypeUIClick  EventType = "ui.click"
	EventTypeUIInput  EventType = "ui.input"
	EventTypeUIScroll EventType = "ui.scroll"
	EventTypeUIFocus  EventType = "ui.focus"
	EventTypeUIBlur   EventType = "ui.blur"
	EventTypeUISubmit EventType = "ui.submit"

	// State events
	EventTypeStateChange EventType = "state.change"

	// API events
	EventTypeAPIRequest  EventType = "api.request"
	EventTypeAPIResponse EventType = "api.response"

	// Journey events
	EventTypeJourneyStep EventType = "journey.step"

	// Error events
	EventTypeError EventType = "error"

	// Performance events
	EventTypePerformance EventType = "performance"

	// Custom events
	EventTypeCustom EventType = "custom"
)

type Payload

type Payload struct {
	Events []Event `json:"events"`
}

Payload represents the request body for POST /v1/events.

type PayloadError

type PayloadError struct {
	Index int    `json:"index"`
	Error string `json:"error"`
}

PayloadError represents an error for a specific event in a batch.

type Response

type Response struct {
	Accepted int            `json:"accepted"`
	Rejected int            `json:"rejected"`
	Errors   []PayloadError `json:"errors,omitempty"`
}

Response represents the response from POST /v1/events.

Jump to

Keyboard shortcuts

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