SDKs
Go
Echo

Echo Integration

Capture errors, panics, and request context from Echo applications.

Installation

go get github.com/KodyDennon/statly-go

Setup

package main
 
import (
    "github.com/labstack/echo/v4"
    statly "github.com/KodyDennon/statly-go"
    statlyecho "github.com/KodyDennon/statly-go/integrations/echo"
)
 
func main() {
    // Initialize SDK first
    statly.Init(statly.Options{
        DSN:         "https://[email protected]/your-org",
        Environment: "production",
    })
    defer statly.Close()
 
    e := echo.New()
 
    // Add Statly middleware
    e.Use(statlyecho.Recovery(statlyecho.Options{}))
    e.Use(statlyecho.Logger())
 
    e.GET("/", func(c echo.Context) error {
        return c.JSON(200, map[string]string{"message": "Hello"})
    })
 
    e.Start(":8080")
}

Middleware

Recovery

Panic recovery middleware that captures panics as events.

func Recovery(options Options) echo.MiddlewareFunc
 
type Options struct {
    Repanic         bool          // Re-panic after capture (default: true)
    WaitForDelivery bool          // Wait for event to be sent
    Timeout         time.Duration // Delivery timeout
}

What's captured:

  • Panic value and stack trace
  • HTTP request context
  • Client IP (via c.RealIP(), respects X-Forwarded-For)
  • Request duration

Example:

e.Use(statlyecho.Recovery(statlyecho.Options{
    Repanic:         true,
    WaitForDelivery: true,
    Timeout:         2 * time.Second,
}))

Logger

Request logging middleware that adds breadcrumbs.

func Logger() echo.MiddlewareFunc

What's captured:

  • Request breadcrumb (method, URL)
  • Response breadcrumb (status code, duration)
  • 4xx/5xx responses marked with error level

ErrorHandler

Custom error handler that captures HTTP errors.

func ErrorHandler(defaultHandler echo.HTTPErrorHandler) echo.HTTPErrorHandler

Example:

e.HTTPErrorHandler = statlyecho.ErrorHandler(e.DefaultHTTPErrorHandler)

What's Captured

Request Context

For each error, the middleware captures:

  • HTTP method, URL, path
  • Query string
  • Headers (sensitive ones filtered)
  • Client IP via c.RealIP()
  • Host

Automatic Sanitization

Headers filtered:

  • Authorization
  • Cookie

Tags

Automatically set:

  • http.method: Request method
  • http.url: Request URL
  • transaction: Route path

With Authentication

Set user context from your auth middleware:

func AuthMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
    return func(c echo.Context) error {
        user := getCurrentUser(c)
        if user != nil {
            statly.SetUser(statly.User{
                ID:    user.ID,
                Email: user.Email,
            })
        }
        return next(c)
    }
}
 
e.Use(statlyecho.Recovery(statlyecho.Options{}))
e.Use(AuthMiddleware)

Manual Capture

Capture errors manually with context:

e.POST("/orders", func(c echo.Context) error {
    var order OrderRequest
    if err := c.Bind(&order); err != nil {
        return echo.NewHTTPError(400, "Invalid request")
    }
 
    result, err := processOrder(order)
    if err != nil {
        statly.CaptureExceptionWithContext(err, map[string]interface{}{
            "order_total": order.Total,
            "user_id":     c.Get("user_id"),
        })
        return echo.NewHTTPError(500, "Order processing failed")
    }
 
    return c.JSON(200, result)
})

Full Example

package main
 
import (
    "github.com/labstack/echo/v4"
    "github.com/labstack/echo/v4/middleware"
    statly "github.com/KodyDennon/statly-go"
    statlyecho "github.com/KodyDennon/statly-go/integrations/echo"
)
 
func main() {
    statly.Init(statly.Options{
        DSN:         "https://[email protected]/your-org",
        Environment: "production",
    })
    defer statly.Close()
 
    e := echo.New()
 
    // Statly middleware
    e.Use(statlyecho.Recovery(statlyecho.Options{
        Repanic:         true,
        WaitForDelivery: true,
    }))
    e.Use(statlyecho.Logger())
 
    // Set custom error handler
    e.HTTPErrorHandler = statlyecho.ErrorHandler(e.DefaultHTTPErrorHandler)
 
    // Auth middleware
    e.Use(func(next echo.HandlerFunc) echo.HandlerFunc {
        return func(c echo.Context) error {
            if user := authenticate(c); user != nil {
                statly.SetUser(statly.User{
                    ID:    user.ID,
                    Email: user.Email,
                })
            }
            return next(c)
        }
    })
 
    // Routes
    e.GET("/api/users", listUsers)
    e.POST("/api/orders", createOrder)
 
    e.Start(":8080")
}
 
func createOrder(c echo.Context) error {
    statly.AddBreadcrumb(statly.Breadcrumb{
        Message:  "Creating order",
        Category: "order",
    })
 
    var order Order
    if err := c.Bind(&order); err != nil {
        return echo.NewHTTPError(400, "Invalid order")
    }
 
    result, err := processOrder(order)
    if err != nil {
        statly.CaptureException(err)
        return echo.NewHTTPError(500, "Processing failed")
    }
 
    return c.JSON(200, result)
}