errors

package
v1.0.64 Latest Latest
Warning

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

Go to latest
Published: Dec 25, 2025 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package errors provides rich error context for AI provider operations. It includes request/response snapshots, timing information, correlation IDs, and credential masking for secure debugging and tracing.

Package errors provides rich error context for AI provider operations.

This package implements comprehensive error handling with debugging context, including request/response snapshots, timing information, correlation IDs, and automatic credential masking for secure logging and tracing.

Overview

The errors package provides four main components:

  1. Error Context - Structured context information about errors
  2. Credential Masking - Security-focused masking of sensitive data
  3. Rich Errors - Error wrappers with full context
  4. Middleware - Automatic error context capture

Error Context

ErrorContext captures detailed information about when and where an error occurred:

ctx := errors.NewErrorContext().
    WithRequestID("req-123").
    WithCorrelationID("corr-456").
    WithProvider(types.ProviderTypeAnthropic).
    WithModel("claude-3-opus").
    WithOperation("chat_completion").
    WithDuration(150 * time.Millisecond)

Request and response snapshots can be captured automatically:

config := errors.DefaultSnapshotConfig()
reqSnapshot := errors.NewRequestSnapshot(httpRequest, config)
respSnapshot := errors.NewResponseSnapshot(httpResponse, config)

Credential Masking

The package provides automatic masking of sensitive information in logs:

masker := errors.DefaultCredentialMasker()
safe := masker.MaskString(`{"api_key": "secret123"}`)
// Result: {"api_key": "***MASKED***"}

Headers are automatically masked:

safeHeaders := masker.MaskHeaders(req.Header)

Custom patterns can be added:

masker.AddPattern(
    regexp.MustCompile(`session_id=([A-Za-z0-9]+)`),
    "session_id=***MASKED***",
)

Rich Errors

RichError wraps errors with comprehensive context:

err := doAPICall()
if err != nil {
    richErr := errors.Wrap(err).
        WithRequestID(requestID).
        WithProvider(types.ProviderTypeOpenAI).
        WithModel("gpt-4").
        WithRequestSnapshot(req).
        WithResponseSnapshot(resp).
        WithTimingStart(startTime)

    // Get formatted output for logging
    log.Error(richErr.Format())

    return richErr
}

Rich errors maintain the error chain and work with errors.Is/As:

if errors.Is(richErr, context.DeadlineExceeded) {
    // Handle timeout
}

Middleware Integration

The package provides middleware for automatic error context capture:

config := errors.DefaultErrorContextMiddlewareConfig(types.ProviderTypeAnthropic)
errorMw := errors.NewErrorContextMiddleware(config)

chain := middleware.NewMiddlewareChain()
chain.Add(errorMw)

// Use with HTTP requests
ctx, req, err := chain.ProcessRequest(ctx, req)
// ... perform request ...
ctx, resp, err := chain.ProcessResponse(ctx, req, resp)

// Retrieve error context
if err != nil {
    errCtx := errors.GetErrorContext(ctx)
    enrichedErr := errors.EnrichError(ctx, err)
    log.Error(enrichedErr)
}

Correlation Tracking

For simpler correlation tracking without full error context:

corrMw := errors.NewCorrelationMiddleware("X-Correlation-ID", true)
chain.Add(corrMw)

// Later, retrieve the correlation ID
correlationID := errors.GetCorrelationID(ctx)

Security Considerations

The package is designed with security in mind:

  • Sensitive headers (Authorization, API keys, etc.) are automatically masked
  • Request/response bodies are scanned for credentials and masked
  • Body size is limited to prevent memory issues
  • Custom masking patterns can be added for domain-specific secrets

Configuration

Snapshot capture can be configured:

config := &errors.SnapshotConfig{
    MaxBodySize:    8192,              // Capture up to 8KB
    IncludeHeaders: true,              // Include headers
    IncludeBody:    true,              // Include body
    Masker:         myCustomMasker,    // Custom masker
}

richErr := errors.NewRichErrorWithConfig(err, config)

Example: Complete Error Handling

func (p *MyProvider) ChatCompletion(ctx context.Context, req types.ChatCompletionRequest) (*types.ChatCompletionResponse, error) {
    startTime := time.Now()

    // Build HTTP request
    httpReq, err := p.buildRequest(req)
    if err != nil {
        return nil, errors.Wrap(err).
            WithProvider(types.ProviderType(p.Name())).
            WithOperation("chat_completion").
            WithModel(req.Model)
    }

    // Perform request
    httpResp, err := p.client.Do(httpReq)
    if err != nil {
        return nil, errors.Wrap(err).
            WithProvider(types.ProviderType(p.Name())).
            WithOperation("chat_completion").
            WithModel(req.Model).
            WithRequestSnapshot(httpReq).
            WithTimingStart(startTime)
    }
    defer httpResp.Body.Close()

    // Handle errors
    if httpResp.StatusCode != 200 {
        apiErr := parseAPIError(httpResp)
        return nil, errors.Wrap(apiErr).
            WithProvider(types.ProviderType(p.Name())).
            WithOperation("chat_completion").
            WithModel(req.Model).
            WithRequestSnapshot(httpReq).
            WithResponseSnapshot(httpResp).
            WithTimingStart(startTime)
    }

    // Parse response
    resp, err := parseResponse(httpResp)
    if err != nil {
        return nil, errors.Wrap(err).
            WithProvider(types.ProviderType(p.Name())).
            WithOperation("chat_completion").
            WithModel(req.Model).
            WithRequestSnapshot(httpReq).
            WithResponseSnapshot(httpResp).
            WithTimingStart(startTime)
    }

    return resp, nil
}

Package errors provides helper functions for integrating RichError into AI providers.

Example (BasicErrorWrapping)

Example_basicErrorWrapping demonstrates wrapping an error with rich context

package main

import (
	"fmt"
	"time"

	"github.com/cecil-the-coder/ai-provider-kit/internal/common/errors"
	"github.com/cecil-the-coder/ai-provider-kit/pkg/types"
)

func main() {
	// Simulate an API error
	baseErr := fmt.Errorf("API request failed: rate limit exceeded")

	// Wrap with rich context
	richErr := errors.Wrap(baseErr).
		WithRequestID("req-abc-123").
		WithProvider(types.ProviderTypeOpenAI).
		WithModel("gpt-4").
		WithOperation("chat_completion").
		WithTiming(250 * time.Millisecond)

	// Print the error
	fmt.Println(richErr.Error())
}
Output:
API request failed: rate limit exceeded
Example (CompleteWorkflow)

Example_completeWorkflow demonstrates a complete error handling workflow

package main

import (
	"bytes"
	"context"
	"fmt"
	"io"
	"net/http"

	"github.com/cecil-the-coder/ai-provider-kit/internal/common/errors"
	"github.com/cecil-the-coder/ai-provider-kit/internal/common/middleware"
	"github.com/cecil-the-coder/ai-provider-kit/pkg/types"
)

func main() {
	// 1. Create middleware
	config := errors.DefaultErrorContextMiddlewareConfig(types.ProviderTypeOpenAI)
	errorMw := errors.NewErrorContextMiddleware(config)

	chain := middleware.NewMiddlewareChain()
	chain.Add(errorMw)

	// 2. Make a request
	body := `{"model": "gpt-4", "messages": [{"role": "user", "content": "Hello"}]}`
	req, _ := http.NewRequest("POST", "https://api.openai.com/v1/chat/completions", bytes.NewBufferString(body))
	ctx := context.Background()

	// 3. Process request
	ctx, req, _ = chain.ProcessRequest(ctx, req)

	// 4. Simulate a response
	resp := &http.Response{
		StatusCode: 401,
		Header:     http.Header{"Content-Type": []string{"application/json"}},
		Body:       io.NopCloser(bytes.NewBufferString(`{"error": {"message": "Invalid API key"}}`)),
	}

	// 5. Process response
	ctx, _, _ = chain.ProcessResponse(ctx, req, resp)

	// 6. Handle error
	apiErr := fmt.Errorf("API authentication failed")
	enrichedErr := errors.EnrichError(ctx, apiErr)

	// 7. Check the enriched error
	if richErr, ok := enrichedErr.(*errors.RichError); ok {
		errCtx := richErr.Context()
		fmt.Println("Provider:", errCtx.Provider)
		fmt.Println("Has request:", errCtx.Request != nil)
		fmt.Println("Has response:", errCtx.Response != nil)
		fmt.Println("Response status:", errCtx.Response.StatusCode)
	}

}
Output:
Provider: openai
Has request: true
Has response: true
Response status: 401
Example (CorrelationMiddleware)

Example_correlationMiddleware demonstrates simple correlation tracking

package main

import (
	"context"
	"fmt"
	"net/http"

	"github.com/cecil-the-coder/ai-provider-kit/internal/common/errors"
)

func main() {
	// Create correlation middleware
	corrMw := errors.NewCorrelationMiddleware("X-Trace-ID", true)

	// Create request
	req, _ := http.NewRequest("GET", "https://api.example.com/test", nil)
	ctx := context.Background()

	// Process request
	ctx, req, _ = corrMw.ProcessRequest(ctx, req)

	// Retrieve correlation ID
	correlationID := errors.GetCorrelationID(ctx)
	headerID := req.Header.Get("X-Trace-ID")

	fmt.Println("Has correlation ID:", correlationID != "")
	fmt.Println("Header matches context:", correlationID == headerID)

}
Output:
Has correlation ID: true
Header matches context: true
Example (CredentialMasking)

Example_credentialMasking demonstrates automatic credential masking

package main

import (
	"fmt"
	"net/http"

	"github.com/cecil-the-coder/ai-provider-kit/internal/common/errors"
)

func main() {
	masker := errors.DefaultCredentialMasker()

	// Mask API keys in JSON
	jsonData := `{"model": "gpt-4", "api_key": "sk-1234567890abcdef"}`
	masked := masker.MaskString(jsonData)
	fmt.Println(masked)

	// Mask headers
	headers := http.Header{
		"Authorization": []string{"Bearer secret-token"},
		"Content-Type":  []string{"application/json"},
	}
	maskedHeaders := masker.MaskHeaders(headers)
	fmt.Println("Authorization:", maskedHeaders["Authorization"][0])
	fmt.Println("Content-Type:", maskedHeaders["Content-Type"][0])

}
Output:
{"model": "gpt-4", "api_key": "***MASKED***"}
Authorization: ***MASKED***
Content-Type: application/json
Example (CustomMaskingPattern)

Example_customMaskingPattern demonstrates adding custom masking patterns

package main

import (
	"fmt"
	"regexp"

	"github.com/cecil-the-coder/ai-provider-kit/internal/common/errors"
)

func main() {
	masker := errors.NewCredentialMasker()

	// Add custom pattern for session IDs
	masker.AddPattern(
		regexp.MustCompile(`session_id=([A-Za-z0-9]+)`),
		"session_id=***MASKED***",
	)

	data := "User request with session_id=abc123def456"
	masked := masker.MaskString(data)
	fmt.Println(masked)

}
Output:
User request with session_id=***MASKED***
Example (CustomSnapshotConfig)

Example_customSnapshotConfig demonstrates configuring snapshot capture

package main

import (
	"bytes"
	"fmt"
	"net/http"

	"github.com/cecil-the-coder/ai-provider-kit/internal/common/errors"
)

func main() {
	// Create custom config
	config := &errors.SnapshotConfig{
		MaxBodySize:    1024, // Only capture first 1KB
		IncludeHeaders: true,
		IncludeBody:    false, // Don't capture body
		Masker:         errors.DefaultCredentialMasker(),
	}

	// Create a request
	req, _ := http.NewRequest("POST", "https://api.example.com/v1/chat", bytes.NewBufferString(`{"test": "data"}`))
	req.Header.Set("Content-Type", "application/json")
	snapshot := errors.NewRequestSnapshot(req, config)

	fmt.Println("Method:", snapshot.Method)
	fmt.Println("Has headers:", len(snapshot.Headers) > 0)
	fmt.Println("Has body:", snapshot.Body != "")

}
Output:
Method: POST
Has headers: true
Has body: false
Example (EnrichError)

Example_enrichError demonstrates enriching errors from context

package main

import (
	"context"
	"fmt"
	"time"

	"github.com/cecil-the-coder/ai-provider-kit/internal/common/errors"
	"github.com/cecil-the-coder/ai-provider-kit/pkg/types"
)

func main() {
	// Simulate an error occurring during a request
	baseErr := fmt.Errorf("connection timeout")

	// Create error context
	errCtx := errors.NewErrorContext().
		WithRequestID("req-123").
		WithProvider(types.ProviderTypeOpenAI).
		WithModel("gpt-4").
		WithDuration(30 * time.Second)

	// Store in context
	ctx := context.WithValue(context.Background(), errors.ContextKeyErrorContext, errCtx)

	// Enrich the error
	enriched := errors.EnrichError(ctx, baseErr)

	// The enriched error has full context
	fmt.Println(enriched.Error())

}
Output:
connection timeout
Example (ErrorContextMiddleware)

Example_errorContextMiddleware demonstrates using middleware for automatic context capture

package main

import (
	"bytes"
	"context"
	"fmt"
	"net/http"

	"github.com/cecil-the-coder/ai-provider-kit/internal/common/errors"
	"github.com/cecil-the-coder/ai-provider-kit/internal/common/middleware"
	"github.com/cecil-the-coder/ai-provider-kit/pkg/types"
)

func main() {
	// Create middleware
	config := errors.DefaultErrorContextMiddlewareConfig(types.ProviderTypeAnthropic)
	errorMw := errors.NewErrorContextMiddleware(config)

	// Create middleware chain
	chain := middleware.NewMiddlewareChain()
	chain.Add(errorMw)

	// Create request
	req, _ := http.NewRequest("POST", "https://api.anthropic.com/v1/messages", bytes.NewBufferString(`{}`))
	ctx := context.Background()

	// Process request
	ctx, _, _ = chain.ProcessRequest(ctx, req)

	// Get error context
	errCtx := errors.GetErrorContext(ctx)
	if errCtx != nil {
		fmt.Println("Provider:", errCtx.Provider)
		fmt.Println("Has request ID:", errCtx.RequestID != "")
		fmt.Println("Has correlation ID:", errCtx.CorrelationID != "")
		fmt.Println("Has request snapshot:", errCtx.Request != nil)
	}

}
Output:
Provider: anthropic
Has request ID: true
Has correlation ID: true
Has request snapshot: true
Example (RequestSnapshot)

Example_requestSnapshot demonstrates capturing request snapshots

package main

import (
	"bytes"
	"fmt"
	"net/http"

	"github.com/cecil-the-coder/ai-provider-kit/internal/common/errors"
)

func main() {
	// Create a sample request
	body := `{"model": "claude-3-opus", "messages": [{"role": "user", "content": "Hello"}]}`
	req, _ := http.NewRequest("POST", "https://api.anthropic.com/v1/messages", bytes.NewBufferString(body))
	req.Header.Set("X-API-Key", "sk-ant-secret-key")
	req.Header.Set("Content-Type", "application/json")

	// Create snapshot with default config
	config := errors.DefaultSnapshotConfig()
	snapshot := errors.NewRequestSnapshot(req, config)

	fmt.Println("Method:", snapshot.Method)
	fmt.Println("URL:", snapshot.URL)
	fmt.Println("Has headers:", len(snapshot.Headers) > 0)
	fmt.Println("Has body:", snapshot.Body != "")
	fmt.Println("Body truncated:", snapshot.BodyTruncated)

}
Output:
Method: POST
URL: https://api.anthropic.com/v1/messages
Has headers: true
Has body: true
Body truncated: false

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrCancelled = errors.New("cancelled: request was cancelled")

ErrCancelled indicates that the request was cancelled by the client. This typically happens when the context is cancelled.

View Source
var ErrContentFiltered = errors.New("content filtered: request rejected by content policy")

ErrContentFiltered indicates that content was rejected by the provider's content filtering policy. This can happen when input or output violates safety guidelines.

View Source
var ErrContextLengthExceeded = errors.New("context length exceeded: input is too large for the model")

ErrContextLengthExceeded indicates that the input context exceeds the model's maximum context length. This is a specific type of invalid request error that can be handled differently.

View Source
var ErrInvalidRequest = errors.New("invalid request: malformed or invalid parameters")

ErrInvalidRequest indicates that the request was malformed or invalid. This can include missing required parameters, invalid parameter values, or other client-side validation errors.

View Source
var ErrModelNotFound = errors.New("model not found: the requested model is not available")

ErrModelNotFound indicates that the requested model is not available or does not exist. This can be used when a provider doesn't support a specific model or when a model name is misspelled.

View Source
var ErrNetworkError = errors.New("network error: unable to reach the provider")

ErrNetworkError indicates a general network connectivity issue. This can include DNS resolution failures, connection refused, etc.

View Source
var ErrNotAuthenticated = errors.New("not authenticated: missing or invalid credentials")

ErrNotAuthenticated indicates that the request lacks valid authentication credentials. This is returned when an API key, token, or other credential is missing, invalid, or expired.

View Source
var ErrRateLimited = errors.New("rate limited: too many requests")

ErrRateLimited indicates that the client has exceeded the rate limit for API requests. This error typically includes information about when the rate limit will reset, allowing clients to implement proper backoff.

View Source
var ErrServerError = errors.New("server error: an internal error occurred on the server")

ErrServerError indicates an internal server error from the provider. This is typically a 5xx error indicating an unexpected server condition.

View Source
var ErrServiceUnavailable = errors.New("service unavailable: the service is temporarily unavailable")

ErrServiceUnavailable indicates that the provider service is temporarily unavailable. This is typically a 503 error and may be retried after a delay.

View Source
var ErrTimeout = errors.New("timeout: request timed out")

ErrTimeout indicates that the request timed out. This can be due to network issues, slow provider responses, or context deadline exceeded.

View Source
var ErrUnauthorized = errors.New("unauthorized: insufficient permissions for the requested operation")

ErrUnauthorized indicates that the client is authenticated but lacks sufficient permissions for the requested operation. This is distinct from ErrNotAuthenticated - the credentials are valid, but don't grant access to the specific resource or operation.

Functions

func EnrichError

func EnrichError(ctx context.Context, err error) error

EnrichError adds error context to an error If the context contains error context, it will be attached to the error

func ExtractProviderError

func ExtractProviderError(richErr *RichError) *types.ProviderError

ExtractProviderError extracts a types.ProviderError from a RichError. This enables backward compatibility with existing error handling.

func GetCorrelationID

func GetCorrelationID(ctx context.Context) string

GetCorrelationID retrieves the correlation ID from a context

func IsAuthenticationError

func IsAuthenticationError(err error) bool

IsAuthenticationError returns true if the error is an authentication-related error.

func IsAuthenticationErrorRich

func IsAuthenticationErrorRich(err error) bool

IsAuthenticationErrorRich checks if an error is authentication-related.

func IsClientError

func IsClientError(err error) bool

IsClientError returns true if the error is a client-side error that won't be fixed by retrying without changes to the request.

func IsClientErrorRich

func IsClientErrorRich(err error) bool

IsClientErrorRich checks if an error is a client-side error.

func IsRetryableError

func IsRetryableError(err error) bool

IsRetryableError returns true if the error is potentially retryable. This includes rate limits, timeouts, network errors, and server errors.

func IsRetryableErrorRich

func IsRetryableErrorRich(err error) bool

IsRetryableErrorRich checks if an error is retryable. This works with both RichError and standard errors.

func MaskURL

func MaskURL(url string) string

MaskURL masks sensitive information in URLs (query parameters, etc.)

Types

type ContextKey

type ContextKey string

ContextKey type for error context keys

const (
	// ContextKeyErrorContext stores the error context in the request context
	ContextKeyErrorContext ContextKey = "errors:error_context"
	// ContextKeyCorrelationID stores the correlation ID in the request context
	ContextKeyCorrelationID ContextKey = "errors:correlation_id"
)

type CorrelationMiddleware

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

CorrelationMiddleware is a simple middleware that adds correlation IDs to requests This is a lighter-weight alternative to ErrorContextMiddleware when you only need correlation tracking

func NewCorrelationMiddleware

func NewCorrelationMiddleware(headerName string, generate bool) *CorrelationMiddleware

NewCorrelationMiddleware creates a new correlation middleware

func (*CorrelationMiddleware) ProcessRequest

func (m *CorrelationMiddleware) ProcessRequest(ctx context.Context, req *http.Request) (context.Context, *http.Request, error)

ProcessRequest implements RequestMiddleware

type CredentialMasker

type CredentialMasker interface {
	// MaskString masks sensitive information in a string
	MaskString(s string) string

	// MaskHeaders masks sensitive information in HTTP headers
	MaskHeaders(headers http.Header) map[string][]string

	// AddPattern adds a custom masking pattern
	AddPattern(pattern *regexp.Regexp, replacement string)
}

CredentialMasker provides methods to mask sensitive information in logs and errors

type DefaultMasker

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

DefaultMasker is the default implementation of CredentialMasker

func DefaultCredentialMasker

func DefaultCredentialMasker() *DefaultMasker

DefaultCredentialMasker creates a new credential masker with default patterns

func NewCredentialMasker

func NewCredentialMasker() *DefaultMasker

NewCredentialMasker creates a new credential masker with no default patterns Use this if you want complete control over what gets masked

func (*DefaultMasker) AddPattern

func (m *DefaultMasker) AddPattern(pattern *regexp.Regexp, replacement string)

AddPattern adds a custom masking pattern

func (*DefaultMasker) AddSensitiveHeader

func (m *DefaultMasker) AddSensitiveHeader(headerName string)

AddSensitiveHeader adds a header name to the list of sensitive headers

func (*DefaultMasker) MaskHeaders

func (m *DefaultMasker) MaskHeaders(headers http.Header) map[string][]string

MaskHeaders masks sensitive information in HTTP headers

func (*DefaultMasker) MaskString

func (m *DefaultMasker) MaskString(s string) string

MaskString masks sensitive information in a string

func (*DefaultMasker) RemoveSensitiveHeader

func (m *DefaultMasker) RemoveSensitiveHeader(headerName string)

RemoveSensitiveHeader removes a header name from the list of sensitive headers

type ErrorContext

type ErrorContext struct {
	// RequestID is a unique identifier for this request
	RequestID string

	// CorrelationID is a correlation identifier for tracing across services
	CorrelationID string

	// Timestamp is when the error occurred
	Timestamp time.Time

	// Duration is how long the request took before failing
	Duration time.Duration

	// Provider is the AI provider name
	Provider types.ProviderType

	// Model is the model being used
	Model string

	// Operation is the operation that failed (e.g., "chat_completion", "list_models")
	Operation string

	// Request is a snapshot of the HTTP request
	Request *RequestSnapshot

	// Response is a snapshot of the HTTP response (if available)
	Response *ResponseSnapshot
}

ErrorContext contains contextual information about an error

func GetErrorContext

func GetErrorContext(ctx context.Context) *ErrorContext

GetErrorContext retrieves the error context from a context

func NewErrorContext

func NewErrorContext() *ErrorContext

NewErrorContext creates a new error context

func (*ErrorContext) WithCorrelationID

func (ec *ErrorContext) WithCorrelationID(id string) *ErrorContext

WithCorrelationID sets the correlation ID

func (*ErrorContext) WithDuration

func (ec *ErrorContext) WithDuration(d time.Duration) *ErrorContext

WithDuration sets the request duration

func (*ErrorContext) WithModel

func (ec *ErrorContext) WithModel(model string) *ErrorContext

WithModel sets the model

func (*ErrorContext) WithOperation

func (ec *ErrorContext) WithOperation(operation string) *ErrorContext

WithOperation sets the operation

func (*ErrorContext) WithProvider

func (ec *ErrorContext) WithProvider(provider types.ProviderType) *ErrorContext

WithProvider sets the provider

func (*ErrorContext) WithRequest

func (ec *ErrorContext) WithRequest(snapshot *RequestSnapshot) *ErrorContext

WithRequest sets the request snapshot

func (*ErrorContext) WithRequestID

func (ec *ErrorContext) WithRequestID(id string) *ErrorContext

WithRequestID sets the request ID

func (*ErrorContext) WithResponse

func (ec *ErrorContext) WithResponse(snapshot *ResponseSnapshot) *ErrorContext

WithResponse sets the response snapshot

type ErrorContextMiddleware

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

ErrorContextMiddleware captures error context automatically for requests

func NewErrorContextMiddleware

func NewErrorContextMiddleware(config *ErrorContextMiddlewareConfig) *ErrorContextMiddleware

NewErrorContextMiddleware creates a new error context middleware

func (*ErrorContextMiddleware) ProcessRequest

func (m *ErrorContextMiddleware) ProcessRequest(ctx context.Context, req *http.Request) (context.Context, *http.Request, error)

ProcessRequest implements RequestMiddleware

func (*ErrorContextMiddleware) ProcessResponse

func (m *ErrorContextMiddleware) ProcessResponse(ctx context.Context, req *http.Request, resp *http.Response) (context.Context, *http.Response, error)

ProcessResponse implements ResponseMiddleware

type ErrorContextMiddlewareConfig

type ErrorContextMiddlewareConfig struct {
	// Provider is the provider name
	Provider types.ProviderType

	// SnapshotConfig controls how snapshots are created
	SnapshotConfig *SnapshotConfig

	// GenerateRequestID determines if request IDs should be generated
	GenerateRequestID bool

	// GenerateCorrelationID determines if correlation IDs should be generated
	GenerateCorrelationID bool

	// CorrelationIDHeader is the header name for correlation IDs
	// Defaults to "X-Correlation-ID"
	CorrelationIDHeader string
}

ErrorContextMiddlewareConfig configures the error context middleware

func DefaultErrorContextMiddlewareConfig

func DefaultErrorContextMiddlewareConfig(provider types.ProviderType) *ErrorContextMiddlewareConfig

DefaultErrorContextMiddlewareConfig returns the default configuration

type ProviderErrorHelper

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

ProviderErrorHelper provides helper methods for creating rich errors from provider operations. This simplifies error handling in provider implementations.

func NewProviderErrorHelper

func NewProviderErrorHelper(provider types.ProviderType) *ProviderErrorHelper

NewProviderErrorHelper creates a new helper for the given provider.

func NewProviderErrorHelperWithConfig

func NewProviderErrorHelperWithConfig(provider types.ProviderType, config *SnapshotConfig) *ProviderErrorHelper

NewProviderErrorHelperWithConfig creates a new helper with custom snapshot config.

func (*ProviderErrorHelper) NewAuthError

func (h *ProviderErrorHelper) NewAuthError(message string) *RichError

NewAuthError creates a new authentication error.

func (*ProviderErrorHelper) NewInvalidRequestError

func (h *ProviderErrorHelper) NewInvalidRequestError(message string) *RichError

NewInvalidRequestError creates a new invalid request error.

func (*ProviderErrorHelper) NewNetworkError

func (h *ProviderErrorHelper) NewNetworkError(message string) *RichError

NewNetworkError creates a new network error.

func (*ProviderErrorHelper) NewRateLimitError

func (h *ProviderErrorHelper) NewRateLimitError(message string) *RichError

NewRateLimitError creates a new rate limit error.

func (*ProviderErrorHelper) NewServerError

func (h *ProviderErrorHelper) NewServerError(statusCode int, message string) *RichError

NewServerError creates a new server error.

func (*ProviderErrorHelper) NewTimeoutError

func (h *ProviderErrorHelper) NewTimeoutError(message string) *RichError

NewTimeoutError creates a new timeout error.

func (*ProviderErrorHelper) WrapAuthError

func (h *ProviderErrorHelper) WrapAuthError(operation string, err error) *RichError

WrapAuthError wraps an authentication error with context.

func (*ProviderErrorHelper) WrapHTTPError

func (h *ProviderErrorHelper) WrapHTTPError(req *http.Request, resp *http.Response, err error) *RichError

WrapHTTPError wraps an HTTP error with rich context. It automatically detects the error type based on status code.

func (*ProviderErrorHelper) WrapInvalidRequestError

func (h *ProviderErrorHelper) WrapInvalidRequestError(operation string, err error) *RichError

WrapInvalidRequestError wraps an invalid request error.

func (*ProviderErrorHelper) WrapNetworkError

func (h *ProviderErrorHelper) WrapNetworkError(operation string, err error) *RichError

WrapNetworkError wraps a network error with context.

func (*ProviderErrorHelper) WrapRateLimitError

func (h *ProviderErrorHelper) WrapRateLimitError(req *http.Request, resp *http.Response) *RichError

WrapRateLimitError wraps a rate limit error with context.

func (*ProviderErrorHelper) WrapRequestError

func (h *ProviderErrorHelper) WrapRequestError(operation string, req *http.Request, err error) *RichError

WrapRequestError wraps an error that occurred while building or sending a request.

func (*ProviderErrorHelper) WrapResponseError

func (h *ProviderErrorHelper) WrapResponseError(operation string, req *http.Request, resp *http.Response, err error) *RichError

WrapResponseError wraps an error that occurred while reading or parsing a response.

func (*ProviderErrorHelper) WrapServerError

func (h *ProviderErrorHelper) WrapServerError(req *http.Request, resp *http.Response) *RichError

WrapServerError wraps a server error with context.

func (*ProviderErrorHelper) WrapTimeoutError

func (h *ProviderErrorHelper) WrapTimeoutError(operation string, err error) *RichError

WrapTimeoutError wraps a timeout error with context.

type RequestSnapshot

type RequestSnapshot struct {
	// Method is the HTTP method (GET, POST, etc.)
	Method string

	// URL is the request URL
	URL string

	// Headers are the HTTP headers (with sensitive values masked)
	Headers map[string][]string

	// Body is the request body (truncated if too large)
	Body string

	// BodyTruncated indicates if the body was truncated
	BodyTruncated bool
}

RequestSnapshot captures key information from an HTTP request for debugging

func NewRequestSnapshot

func NewRequestSnapshot(req *http.Request, config *SnapshotConfig) *RequestSnapshot

NewRequestSnapshot creates a snapshot of an HTTP request The request body will be read and restored so the request can still be used

type ResponseSnapshot

type ResponseSnapshot struct {
	// StatusCode is the HTTP status code
	StatusCode int

	// Headers are the HTTP headers (with sensitive values masked)
	Headers map[string][]string

	// Body is the response body (truncated if too large)
	Body string

	// BodyTruncated indicates if the body was truncated
	BodyTruncated bool
}

ResponseSnapshot captures key information from an HTTP response for debugging

func NewResponseSnapshot

func NewResponseSnapshot(resp *http.Response, config *SnapshotConfig) *ResponseSnapshot

NewResponseSnapshot creates a snapshot of an HTTP response The response body will be read and restored so the response can still be used

type RichError

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

RichError wraps an error with contextual information for debugging and tracing

func ConvertProviderError

func ConvertProviderError(providerErr *types.ProviderError) *RichError

ConvertProviderError converts a types.ProviderError to a RichError. This enables backward compatibility with existing error handling.

func NewRichError

func NewRichError(err error) *RichError

NewRichError creates a new RichError wrapping the given error

func NewRichErrorWithConfig

func NewRichErrorWithConfig(err error, config *SnapshotConfig) *RichError

NewRichErrorWithConfig creates a new RichError with a custom snapshot configuration

func Wrap

func Wrap(err error) *RichError

Wrap wraps an error with rich context This is a convenience function for NewRichError(err)

func WrapWithContext

func WrapWithContext(err error, ctx *ErrorContext) *RichError

WrapWithContext wraps an error with an existing error context

func (*RichError) Context

func (e *RichError) Context() *ErrorContext

Context returns the error context

func (*RichError) Error

func (e *RichError) Error() string

Error implements the error interface

func (*RichError) Format

func (e *RichError) Format() string

Format returns a detailed formatted error message including all context

func (*RichError) String

func (e *RichError) String() string

String returns a string representation of the error

func (*RichError) Unwrap

func (e *RichError) Unwrap() error

Unwrap returns the underlying error for error chain support

func (*RichError) WithContext

func (e *RichError) WithContext(ctx *ErrorContext) *RichError

WithContext sets the entire error context

func (*RichError) WithCorrelationID

func (e *RichError) WithCorrelationID(id string) *RichError

WithCorrelationID sets the correlation ID and returns the error for chaining

func (*RichError) WithModel

func (e *RichError) WithModel(model string) *RichError

WithModel sets the model and returns the error for chaining

func (*RichError) WithOperation

func (e *RichError) WithOperation(operation string) *RichError

WithOperation sets the operation and returns the error for chaining

func (*RichError) WithProvider

func (e *RichError) WithProvider(provider types.ProviderType) *RichError

WithProvider sets the provider and returns the error for chaining

func (*RichError) WithRequestID

func (e *RichError) WithRequestID(id string) *RichError

WithRequestID sets the request ID and returns the error for chaining

func (*RichError) WithRequestSnapshot

func (e *RichError) WithRequestSnapshot(req *http.Request) *RichError

WithRequestSnapshot creates and attaches a request snapshot

func (*RichError) WithResponseSnapshot

func (e *RichError) WithResponseSnapshot(resp *http.Response) *RichError

WithResponseSnapshot creates and attaches a response snapshot

func (*RichError) WithTiming

func (e *RichError) WithTiming(duration time.Duration) *RichError

WithTiming sets the duration and returns the error for chaining

func (*RichError) WithTimingStart

func (e *RichError) WithTimingStart(startTime time.Time) *RichError

WithTimingStart sets the duration based on a start time and returns the error for chaining

type SnapshotConfig

type SnapshotConfig struct {
	// MaxBodySize is the maximum body size to capture (default: 4KB)
	MaxBodySize int

	// IncludeHeaders determines if headers should be included
	IncludeHeaders bool

	// IncludeBody determines if request/response bodies should be included
	IncludeBody bool

	// Masker is the credential masker to use
	Masker CredentialMasker
}

SnapshotConfig controls how snapshots are created

func DefaultSnapshotConfig

func DefaultSnapshotConfig() *SnapshotConfig

DefaultSnapshotConfig returns the default snapshot configuration

Jump to

Keyboard shortcuts

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