debug

package
v1.1.0 Latest Latest
Warning

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

Go to latest
Published: Sep 2, 2025 License: MIT Imports: 17 Imported by: 0

README

Debug Package

Package debug provides debugging, error handling, and validation capabilities for weft. It offers configurable debug modes, enhanced error reporting with stack traces, template validation, and a rich set of debugging helper functions.

Architecture

The debug package is organized into four main components:

  • Error Handling (errors.go): Enhanced error types with stack traces and analysis
  • Debug Mode Management (mode.go): Configurable debug levels and logging
  • Template Helpers (helpers.go): Debug functions available in templates
  • Template Validation (validation.go): Syntax and semantic validation

Basic Usage

Enable Debug Mode and Configure Logging
debugMode := debug.NewDebugMode()
debugMode.SetLevel(debug.LevelInfo)
Create Enhanced Errors with Stack Traces
err := debug.NewEnhancedError(originalErr, "template_execution")
fmt.Println(err.FormatDetailed())

Template Integration

The package provides debug functions that can be used within templates:

<!-- In your template -->
{{ debug .Data }}
{{ debugType .Value }}
{{ debugJSON .Config }}
{{ debugLog "Processing item" .Item }}
Register Debug Functions
funcMap := debug.CreateDebugFuncMap(debugMode)
tmpl := template.New("example").Funcs(funcMap)

Configuration

The package supports various configuration options:

config := debug.Config{
    MaxStackFrames:       15,  // Stack trace depth
    ErrorBufferSize:      200, // Error history buffer
    ExecutionBufferSize:  150, // Execution tracking buffer
    MaxStackTraceDisplay: 8,   // Stack frames shown in output
}
debug.SetConfig(config)

Template Validation

Validate templates for syntax and semantic issues:

validator := debug.NewTemplateValidator(templateFS, funcMap, debugMode)
result := validator.ValidateTemplate("path/to/template.tmpl")
if !result.Valid {
    for _, err := range result.Errors {
        fmt.Printf("Error: %s\n", err.Message)
    }
}
Validation Features
  • Syntax Validation: Checks for proper template syntax
  • Security Validation: Prevents path traversal attacks
  • Function Validation: Verifies function availability
  • Performance Warnings: Identifies potential performance issues

Debug Levels

The package supports multiple debug levels:

Level Description
LevelOff Disable all debug output
LevelError Show only errors
LevelWarn Show warnings and errors
LevelInfo Show informational messages, warnings, and errors
LevelDebug Show debug messages and above
LevelTrace Show all messages including detailed traces
Setting Debug Levels
debugMode := debug.NewDebugMode()
debugMode.SetLevel(debug.LevelDebug)

// Check if level is enabled
if debugMode.IsEnabled(debug.LevelDebug) {
    // Perform debug operations
}

Template Helper Functions

Available Functions
Function Description Example
debug Display detailed value information {{ debug .User }}
debugType Show type information {{ debugType .Value }}
debugKeys List map keys or struct fields {{ debugKeys .Config }}
debugSize Get size of collections {{ debugSize .Items }}
debugJSON Output JSON representation {{ debugJSON .Data }}
debugPretty Pretty-printed JSON {{ debugPretty .Config }}
debugLog Log message with context {{ debugLog "Processing" .Item }}
debugTime Current timestamp {{ debugTime }}
debugStack Stack trace (trace level) {{ debugStack }}
debugContext Debug context information {{ debugContext }}
Usage Examples
<!-- Display user information -->
{{ debug .User }}

<!-- Show data types -->
Type: {{ debugType .Value }}

<!-- List configuration keys -->
Config keys: {{ debugKeys .Config }}

<!-- Pretty JSON output -->
<pre>{{ debugPretty .Settings }}</pre>

<!-- Conditional debugging -->
{{ if debugContext.debug_level }}
    Debug enabled at level: {{ debugContext.debug_level }}
{{ end }}

Error Handling

Enhanced Error Creation
// Basic enhanced error
err := debug.NewEnhancedError(originalErr, "template_parse")

// With additional context
err = debug.NewEnhancedError(originalErr, "template_parse").
    WithTemplate("user.tmpl").
    WithLine(42).
    WithContext("variable", "user.name").
    WithSuggestion("Check if user.name exists in the data")
Error Analysis
analyzer := debug.NewErrorAnalyzer()
analyzer.AddError(enhancedErr)

// Get error statistics
stats := analyzer.GetStatistics()
fmt.Printf("Total errors: %d\n", stats.TotalErrors)

// Get errors by operation
templateErrors := analyzer.GetErrorsByTemplate("user.tmpl")
Error Context
ctx := debugMode.NewContext("template_execution")
ctx.SetAttribute("template", "user.tmpl")
ctx.SetAttribute("user_id", userID)

// Log with context
ctx.Info("Starting template execution")
ctx.Debug("Processing user data", "count", len(users))

// Complete operation
ctx.Complete()

// Or complete with error
if err != nil {
    ctx.CompleteWithError(err)
}

Performance Considerations

Optimization Tips
  1. Disable in Production: Use LevelOff or LevelError in production
  2. Lazy Evaluation: Debug operations are only performed when the level is enabled
  3. Efficient Helpers: Template helpers check debug level before processing
  4. Caching: Type information and function maps are cached for performance
Performance Settings
// Production-optimized configuration
config := debug.Config{
    MaxStackFrames:       5,  // Reduced for performance
    ErrorBufferSize:      50, // Smaller buffer
    ExecutionBufferSize:  25, // Minimal tracking
    MaxStackTraceDisplay: 3,  // Limited display
}
Memory Management
// Clear error history periodically
analyzer.Clear()

// Clear execution history
debugger := debug.NewTemplateDebugger(debugMode)
debugger.ClearExecutions()

Security Notes

Sensitive Data Protection
  • Debug output may contain sensitive information
  • File paths in stack traces are filtered for security
  • Sensitive field names are automatically redacted
  • Template validation prevents path traversal attacks
Security Best Practices
  1. Never expose debug output in production environments
  2. Filter sensitive data before logging
  3. Use secure logging destinations when debug is enabled
  4. Regular security reviews of debug output
Sensitive Field Detection
// Automatically filtered fields:
// - password, passwd, pwd
// - secret, api_key, apikey, private_key
// - access_token, refresh_token, bearer_token
// - certificate, cert, ssl
// - session, cookie, csrf
// - credential, cred, token, auth

Thread Safety

All public functions and types in this package are thread-safe and can be used concurrently from multiple goroutines.

Concurrent Usage Examples
// Safe concurrent debug mode usage
debugMode := debug.NewDebugMode()

go func() {
    debugMode.SetLevel(debug.LevelDebug)
    debugMode.Info("Goroutine 1", "id", 1)
}()

go func() {
    debugMode.SetLevel(debug.LevelTrace)
    debugMode.Debug("Goroutine 2", "id", 2)
}()

Advanced Features

Template Debugging
debugger := debug.NewTemplateDebugger(debugMode)
debugger.RegisterTemplate("user", userTemplate)

// Execute with debugging
output, err := debugger.ExecuteWithDebug("user", userTemplate, userData)

// Get execution statistics
stats := debugger.GetExecutionStats()
fmt.Printf("Success rate: %.2f%%\n", stats["success_rate"].(float64)*100)
Custom Validation Rules
validator := debug.NewTemplateValidator(fs, funcMap, debugMode)
validator.SetStrict(true) // Enable strict validation

// Validate entire directory
results := validator.ValidateDirectory("templates/")
for path, result := range results {
    if result.HasErrors() {
        fmt.Printf("Template %s has errors: %s\n", path, result.Summary())
    }
}
Error Recovery
// Implement error recovery patterns
func processTemplate() {
    defer func() {
        if r := recover(); r != nil {
            if err, ok := r.(error); ok {
                enhanced := debug.NewEnhancedError(err, "template_panic")
                log.Printf("Template panic recovered: %s", enhanced.FormatDetailed())
            }
        }
    }()
    
    // Template processing code
}

Integration Examples

With HTTP Handlers
func templateHandler(w http.ResponseWriter, r *http.Request) {
    ctx := debugMode.NewContext("http_template")
    ctx.SetAttribute("method", r.Method)
    ctx.SetAttribute("path", r.URL.Path)
    
    defer ctx.Complete()
    
    // Template execution with debugging
    output, err := debugger.ExecuteWithDebug("page", tmpl, data)
    if err != nil {
        ctx.CompleteWithError(err)
        http.Error(w, "Template error", http.StatusInternalServerError)
        return
    }
    
    w.Write([]byte(output))
}
With CLI Applications
func main() {
    debugMode := debug.NewDebugMode()
    
    if verbose {
        debugMode.SetLevel(debug.LevelDebug)
    }
    
    // Process templates with debugging
    for _, templateFile := range templateFiles {
        ctx := debugMode.NewContext("cli_process")
        ctx.SetAttribute("file", templateFile)
        
        if err := processTemplate(templateFile); err != nil {
            enhanced := debug.NewEnhancedError(err, "cli_template").
                WithTemplate(templateFile).
                WithSuggestion("Check template syntax and data structure")
            
            fmt.Fprintf(os.Stderr, "Error: %s\n", enhanced.FormatDetailed())
            ctx.CompleteWithError(err)
        } else {
            ctx.Complete()
        }
    }
}

Documentation

Overview

Package debug provides helpers for debugging template rendering.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CreateDebugFuncMap

func CreateDebugFuncMap(debugMode *DebugMode) template.FuncMap

func SetConfig

func SetConfig(config Config) error

func SuggestTemplateErrors

func SuggestTemplateErrors(err error, templatePath string) []string

Types

type Config

type Config struct {
	MaxStackFrames       int `json:"max_stack_frames"`
	ErrorBufferSize      int `json:"error_buffer_size"`
	ExecutionBufferSize  int `json:"execution_buffer_size"`
	MaxStackTraceDisplay int `json:"max_stack_trace_display"`
}

func DefaultConfig

func DefaultConfig() Config

func GetConfig

func GetConfig() Config

type DebugContext

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

func (*DebugContext) Complete

func (dc *DebugContext) Complete()

func (*DebugContext) CompleteWithError

func (dc *DebugContext) CompleteWithError(err error)

func (*DebugContext) Debug

func (dc *DebugContext) Debug(msg string, args ...any)

func (*DebugContext) Error

func (dc *DebugContext) Error(msg string, err error)

func (*DebugContext) GetAttribute

func (dc *DebugContext) GetAttribute(key string) (any, bool)

func (*DebugContext) Info

func (dc *DebugContext) Info(msg string, args ...any)

func (*DebugContext) SetAttribute

func (dc *DebugContext) SetAttribute(key string, value any)

type DebugLevel

type DebugLevel int
const (
	LevelOff DebugLevel = iota
	LevelError
	LevelWarn
	LevelInfo
	LevelDebug
	LevelTrace
)

func (DebugLevel) String

func (dl DebugLevel) String() string

type DebugMode

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

func NewDebugMode

func NewDebugMode(opts ...DebugOption) *DebugMode

func (*DebugMode) Debug

func (dm *DebugMode) Debug(msg string, args ...any)

func (*DebugMode) Error

func (dm *DebugMode) Error(msg string, args ...any)

func (*DebugMode) GetStats

func (dm *DebugMode) GetStats() DebugStats

func (*DebugMode) Info

func (dm *DebugMode) Info(msg string, args ...any)

func (*DebugMode) IsEnabled

func (dm *DebugMode) IsEnabled(level DebugLevel) bool

func (*DebugMode) LogError

func (dm *DebugMode) LogError(operation string, err error, context map[string]any)

func (*DebugMode) LogFileWrite

func (dm *DebugMode) LogFileWrite(path string, size int, duration time.Duration)

func (*DebugMode) LogTemplateData

func (dm *DebugMode) LogTemplateData(templatePath string, data any)

func (*DebugMode) LogTemplateExecution

func (dm *DebugMode) LogTemplateExecution(templatePath string, data any, duration time.Duration)

func (*DebugMode) NewContext

func (dm *DebugMode) NewContext(operation string) *DebugContext

func (*DebugMode) SetLevel

func (dm *DebugMode) SetLevel(level DebugLevel) error

func (*DebugMode) Trace

func (dm *DebugMode) Trace(msg string, args ...any)

func (*DebugMode) Warn

func (dm *DebugMode) Warn(msg string, args ...any)

type DebugOption

type DebugOption func(*DebugMode)

func WithLevel

func WithLevel(level DebugLevel) DebugOption

func WithMetrics

func WithMetrics(enable bool) DebugOption

func WithOutput

func WithOutput(output io.Writer) DebugOption

func WithProfiling

func WithProfiling(enable bool) DebugOption

func WithTracing

func WithTracing(enable bool) DebugOption

type DebugStats

type DebugStats struct {
	Level            DebugLevel    `json:"level"`
	StartTime        time.Time     `json:"start_time"`
	Uptime           time.Duration `json:"uptime"`
	ProfilingEnabled bool          `json:"profiling_enabled"`
	TracingEnabled   bool          `json:"tracing_enabled"`
	MetricsEnabled   bool          `json:"metrics_enabled"`
}

func (DebugStats) String

func (ds DebugStats) String() string

type EnhancedError

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

func NewEnhancedError

func NewEnhancedError(err error, operation string) *EnhancedError

func (*EnhancedError) Error

func (ee *EnhancedError) Error() string

func (*EnhancedError) FormatDetailed

func (ee *EnhancedError) FormatDetailed() string

func (*EnhancedError) GetContext

func (ee *EnhancedError) GetContext() *ErrorContext

func (*EnhancedError) Unwrap

func (ee *EnhancedError) Unwrap() error

func (*EnhancedError) WithContext

func (ee *EnhancedError) WithContext(key string, value any) *EnhancedError

func (*EnhancedError) WithLine

func (ee *EnhancedError) WithLine(line int) *EnhancedError

func (*EnhancedError) WithOutput

func (ee *EnhancedError) WithOutput(path string) *EnhancedError

func (*EnhancedError) WithSuggestion

func (ee *EnhancedError) WithSuggestion(suggestion string) *EnhancedError

func (*EnhancedError) WithTemplate

func (ee *EnhancedError) WithTemplate(path string) *EnhancedError

type ErrorAnalyzer

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

func NewErrorAnalyzer

func NewErrorAnalyzer() *ErrorAnalyzer

func (*ErrorAnalyzer) AddError

func (ea *ErrorAnalyzer) AddError(err *EnhancedError)

func (*ErrorAnalyzer) Clear

func (ea *ErrorAnalyzer) Clear()

func (*ErrorAnalyzer) GetErrors

func (ea *ErrorAnalyzer) GetErrors() []EnhancedError

func (*ErrorAnalyzer) GetErrorsByOperation

func (ea *ErrorAnalyzer) GetErrorsByOperation(operation string) []EnhancedError

func (*ErrorAnalyzer) GetErrorsByTemplate

func (ea *ErrorAnalyzer) GetErrorsByTemplate(templatePath string) []EnhancedError

func (*ErrorAnalyzer) GetStatistics

func (ea *ErrorAnalyzer) GetStatistics() ErrorStatistics

type ErrorContext

type ErrorContext struct {
	Operation    string         `json:"operation"`
	TemplatePath string         `json:"template_path,omitempty"`
	OutputPath   string         `json:"output_path,omitempty"`
	LineNumber   int            `json:"line_number,omitempty"`
	Context      map[string]any `json:"context,omitempty"`
	Suggestions  []string       `json:"suggestions,omitempty"`
	Timestamp    time.Time      `json:"timestamp"`
	Stack        []StackFrame   `json:"stack,omitempty"`
}

type ErrorStatistics

type ErrorStatistics struct {
	TotalErrors    int            `json:"total_errors"`
	OperationStats map[string]int `json:"operation_stats"`
	TemplateStats  map[string]int `json:"template_stats"`
	TimeRange      TimeRange      `json:"time_range"`
}

func (ErrorStatistics) String

func (es ErrorStatistics) String() string

type StackFrame

type StackFrame struct {
	Function string `json:"function"`
	File     string `json:"file"`
	Line     int    `json:"line"`
}

type TemplateDebugger

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

func NewTemplateDebugger

func NewTemplateDebugger(debugMode *DebugMode) *TemplateDebugger

func (*TemplateDebugger) ClearExecutions

func (td *TemplateDebugger) ClearExecutions()

func (*TemplateDebugger) ExecuteWithDebug

func (td *TemplateDebugger) ExecuteWithDebug(name string, tmpl *template.Template, data any) (string, error)

func (*TemplateDebugger) GetExecutionStats

func (td *TemplateDebugger) GetExecutionStats() map[string]any

func (*TemplateDebugger) GetExecutions

func (td *TemplateDebugger) GetExecutions() []TemplateExecution

func (*TemplateDebugger) RegisterTemplate

func (td *TemplateDebugger) RegisterTemplate(name string, tmpl *template.Template)

type TemplateExecution

type TemplateExecution struct {
	Name      string         `json:"name"`
	StartTime time.Time      `json:"start_time"`
	Duration  time.Duration  `json:"duration"`
	Data      map[string]any `json:"data"`
	Error     string         `json:"error,omitempty"`
	Output    string         `json:"output,omitempty"`
}

type TemplateValidator

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

func NewTemplateValidator

func NewTemplateValidator(templateFS fs.FS, funcMap template.FuncMap, debugMode *DebugMode) *TemplateValidator

func (*TemplateValidator) SetStrict

func (tv *TemplateValidator) SetStrict(strict bool)

func (*TemplateValidator) ValidateDirectory

func (tv *TemplateValidator) ValidateDirectory(templateDir string) map[string]ValidationResult

func (*TemplateValidator) ValidateTemplate

func (tv *TemplateValidator) ValidateTemplate(templatePath string) ValidationResult

type TimeRange

type TimeRange struct {
	Start time.Time `json:"start"`
	End   time.Time `json:"end"`
}

type ValidationError

type ValidationError struct {
	Type       string `json:"type"`
	Message    string `json:"message"`
	File       string `json:"file,omitempty"`
	Line       int    `json:"line,omitempty"`
	Column     int    `json:"column,omitempty"`
	Suggestion string `json:"suggestion,omitempty"`
}

type ValidationResult

type ValidationResult struct {
	Valid    bool              `json:"valid"`
	Errors   []ValidationError `json:"errors"`
	Warnings []ValidationError `json:"warnings"`
	Info     []string          `json:"info"`
}

func (ValidationResult) HasErrors

func (vr ValidationResult) HasErrors() bool

func (ValidationResult) Summary

func (vr ValidationResult) Summary() string

Jump to

Keyboard shortcuts

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