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:
- Error Context - Structured context information about errors
- Credential Masking - Security-focused masking of sensitive data
- Rich Errors - Error wrappers with full context
- 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 ¶
- Variables
- func EnrichError(ctx context.Context, err error) error
- func ExtractProviderError(richErr *RichError) *types.ProviderError
- func GetCorrelationID(ctx context.Context) string
- func IsAuthenticationError(err error) bool
- func IsAuthenticationErrorRich(err error) bool
- func IsClientError(err error) bool
- func IsClientErrorRich(err error) bool
- func IsRetryableError(err error) bool
- func IsRetryableErrorRich(err error) bool
- func MaskURL(url string) string
- type ContextKey
- type CorrelationMiddleware
- type CredentialMasker
- type DefaultMasker
- func (m *DefaultMasker) AddPattern(pattern *regexp.Regexp, replacement string)
- func (m *DefaultMasker) AddSensitiveHeader(headerName string)
- func (m *DefaultMasker) MaskHeaders(headers http.Header) map[string][]string
- func (m *DefaultMasker) MaskString(s string) string
- func (m *DefaultMasker) RemoveSensitiveHeader(headerName string)
- type ErrorContext
- func (ec *ErrorContext) WithCorrelationID(id string) *ErrorContext
- func (ec *ErrorContext) WithDuration(d time.Duration) *ErrorContext
- func (ec *ErrorContext) WithModel(model string) *ErrorContext
- func (ec *ErrorContext) WithOperation(operation string) *ErrorContext
- func (ec *ErrorContext) WithProvider(provider types.ProviderType) *ErrorContext
- func (ec *ErrorContext) WithRequest(snapshot *RequestSnapshot) *ErrorContext
- func (ec *ErrorContext) WithRequestID(id string) *ErrorContext
- func (ec *ErrorContext) WithResponse(snapshot *ResponseSnapshot) *ErrorContext
- type ErrorContextMiddleware
- type ErrorContextMiddlewareConfig
- type ProviderErrorHelper
- func (h *ProviderErrorHelper) NewAuthError(message string) *RichError
- func (h *ProviderErrorHelper) NewInvalidRequestError(message string) *RichError
- func (h *ProviderErrorHelper) NewNetworkError(message string) *RichError
- func (h *ProviderErrorHelper) NewRateLimitError(message string) *RichError
- func (h *ProviderErrorHelper) NewServerError(statusCode int, message string) *RichError
- func (h *ProviderErrorHelper) NewTimeoutError(message string) *RichError
- func (h *ProviderErrorHelper) WrapAuthError(operation string, err error) *RichError
- func (h *ProviderErrorHelper) WrapHTTPError(req *http.Request, resp *http.Response, err error) *RichError
- func (h *ProviderErrorHelper) WrapInvalidRequestError(operation string, err error) *RichError
- func (h *ProviderErrorHelper) WrapNetworkError(operation string, err error) *RichError
- func (h *ProviderErrorHelper) WrapRateLimitError(req *http.Request, resp *http.Response) *RichError
- func (h *ProviderErrorHelper) WrapRequestError(operation string, req *http.Request, err error) *RichError
- func (h *ProviderErrorHelper) WrapResponseError(operation string, req *http.Request, resp *http.Response, err error) *RichError
- func (h *ProviderErrorHelper) WrapServerError(req *http.Request, resp *http.Response) *RichError
- func (h *ProviderErrorHelper) WrapTimeoutError(operation string, err error) *RichError
- type RequestSnapshot
- type ResponseSnapshot
- type RichError
- func (e *RichError) Context() *ErrorContext
- func (e *RichError) Error() string
- func (e *RichError) Format() string
- func (e *RichError) String() string
- func (e *RichError) Unwrap() error
- func (e *RichError) WithContext(ctx *ErrorContext) *RichError
- func (e *RichError) WithCorrelationID(id string) *RichError
- func (e *RichError) WithModel(model string) *RichError
- func (e *RichError) WithOperation(operation string) *RichError
- func (e *RichError) WithProvider(provider types.ProviderType) *RichError
- func (e *RichError) WithRequestID(id string) *RichError
- func (e *RichError) WithRequestSnapshot(req *http.Request) *RichError
- func (e *RichError) WithResponseSnapshot(resp *http.Response) *RichError
- func (e *RichError) WithTiming(duration time.Duration) *RichError
- func (e *RichError) WithTimingStart(startTime time.Time) *RichError
- type SnapshotConfig
Examples ¶
Constants ¶
This section is empty.
Variables ¶
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.
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.
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.
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.
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.
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.
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.
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.
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.
ErrServiceUnavailable indicates that the provider service is temporarily unavailable. This is typically a 503 error and may be retried after a delay.
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.
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 ¶
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 ¶
GetCorrelationID retrieves the correlation ID from a context
func IsAuthenticationError ¶
IsAuthenticationError returns true if the error is an authentication-related error.
func IsAuthenticationErrorRich ¶
IsAuthenticationErrorRich checks if an error is authentication-related.
func IsClientError ¶
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 ¶
IsClientErrorRich checks if an error is a client-side error.
func IsRetryableError ¶
IsRetryableError returns true if the error is potentially retryable. This includes rate limits, timeouts, network errors, and server errors.
func IsRetryableErrorRich ¶
IsRetryableErrorRich checks if an error is retryable. This works with both RichError and standard errors.
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
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
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 ¶
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 ¶
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 ¶
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 ¶
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) WithContext ¶
func (e *RichError) WithContext(ctx *ErrorContext) *RichError
WithContext sets the entire error context
func (*RichError) WithCorrelationID ¶
WithCorrelationID sets the correlation ID and returns the error for chaining
func (*RichError) WithOperation ¶
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 ¶
WithRequestID sets the request ID and returns the error for chaining
func (*RichError) WithRequestSnapshot ¶
WithRequestSnapshot creates and attaches a request snapshot
func (*RichError) WithResponseSnapshot ¶
WithResponseSnapshot creates and attaches a response snapshot
func (*RichError) WithTiming ¶
WithTiming sets the duration 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