Documentation
¶
Overview ¶
Package reporter turns ordinary Go errors into structured reports that are suitable for local logs, production JSON logs, and external alerting.
A report includes the caller file path, line number, function name, service, environment, timestamp, raw error, error type, and human-readable description. Reports can be published to Kafka or a custom publisher so a separate worker can forward the alert to Telegram or another notification channel.
Initialize the package once during application startup:
reporter.Init(reporter.Config{
AppName: "payment-service",
AppEnv: "development",
})
defer reporter.Close()
Use AutoWrap when reporter should classify the error from its text:
if err := run(); err != nil {
return reporter.AutoWrap(err)
}
Use Wrap when the application can provide better business context:
if err := repository.SaveOrder(order); err != nil {
return reporter.Wrap(err, "Failed to save checkout order after payment was confirmed")
}
Index ¶
- Constants
- func AutoWrap(err error) error
- func Close()
- func Flush()
- func Info(tag string, format string, args ...any)
- func Init(cfg Config)
- func SetPublisher(p Publisher)
- func Wrap(err error, customDesc string) error
- func WrapHTTPStatus(err error, statusCode int, customDesc string) error
- func WrapReport(err error, opts ReportOptions) error
- func WrapWithSeverity(err error, severity, customDesc string) error
- type ClosePublisher
- type Config
- type CustomError
- type KafkaPublisher
- type Publisher
- type RedisPublisher
- type ReportOptions
Constants ¶
const ( SeverityInfo = "info" SeverityWarning = "warning" SeverityDanger = "danger" SeverityCritical = "critical" )
Severity values describe how urgent a report is.
Variables ¶
This section is empty.
Functions ¶
func AutoWrap ¶
AutoWrap converts an ordinary error into a structured report with automatic classification.
AutoWrap returns nil when err is nil. Otherwise it inspects err.Error() and assigns an error type and description for known patterns such as connection failures, duplicate keys, deadline timeouts, and missing data. The returned error captures the caller file path, line number, and function name. In production, the report is also published when Init configured a publisher.
Example:
if err := repository.FindUser(id); err != nil {
return reporter.AutoWrap(err)
}
func Close ¶
func Close()
Close releases the Kafka writer used by reporter.
Call Close during graceful shutdown after Init has been called. It is safe to call even when Kafka publishing is not enabled.
Example:
defer reporter.Close()
func Flush ¶ added in v2.0.4
func Flush()
Flush blocks the calling goroutine until all pending background publishing operations have safely finished executing.
This function should be called during a graceful shutdown sequence or immediately before forcing an application exit (e.g., inside log.Fatalf or after a critical startup failure) to guarantee zero log data loss.
Example:
func main() {
rdb, err := ConnectRedis()
if err != nil {
reporter.AutoWrap(err)
reporter.Flush() // Ensures the error above is sent to Redis before exiting
log.Fatalf("Fatal startup error: %v", err)
}
}
func Info ¶
Info logs a general informational message or a success indicator.
Unlike AutoWrap or Wrap, Info is designed strictly for operational tracking (e.g., "Database connected successfully", "Kafka consumer started"). It only outputs to standard synchronization streams (stdout) and will NEVER publish payloads to Kafka or external alert destinations, preventing log pollution.
In non-production environments, it formats the output with terminal-friendly colors synchronized with the CustomError aesthetic. In production, it outputs a structured, single-line JSON log ideal for indexing tools like Elasticsearch.
Example:
func ConnectDB() {
db, err := sql.Open("postgres", dsn)
if err != nil {
reporter.AutoWrap(err) // Sent to Kafka as CRITICAL
return
}
// Log success locally/json without triggering alerting pipelines
reporter.Info("DATABASE", "Successfully connected to PostgreSQL at %s:%d", "127.0.0.1", 5432)
}
func Init ¶
func Init(cfg Config)
Init applies reporter configuration for the current service.
Call Init once during application startup before using AutoWrap or Wrap. It stores the service name, environment, and optional publishing settings. When EnablePublishing is true and a publisher or complete Kafka settings are provided, every reported error can be published asynchronously.
Example:
reporter.Init(reporter.Config{
AppName: "payment-service",
AppEnv: "development",
})
defer reporter.Close()
func SetPublisher ¶ added in v2.0.2
func SetPublisher(p Publisher)
SetPublisher enables external publishing after Init has already configured service metadata. This is useful when the publisher depends on a connection that must be created after reporter is available for bootstrap errors.
func Wrap ¶
Wrap converts an ordinary error into a structured report with a custom description.
Wrap returns nil when err is nil. Use Wrap when the application can provide better business context than automatic classification. The original error is preserved in RawError, while customDesc is stored in Description. The returned error captures the caller file path, line number, and function name. In production, the report is also published when Init configured a publisher.
Example:
if err := repository.SaveOrder(order); err != nil {
return reporter.Wrap(err, "Failed to save checkout order after payment was confirmed")
}
func WrapHTTPStatus ¶
WrapHTTPStatus converts an ordinary error into a structured report using the HTTP status code as the primary classification signal.
func WrapReport ¶
func WrapReport(err error, opts ReportOptions) error
WrapReport converts an ordinary error into a structured report using explicit options supplied by the application.
func WrapWithSeverity ¶
WrapWithSeverity converts an ordinary error into a structured report with a custom description and explicit severity.
Types ¶
type ClosePublisher ¶
type ClosePublisher interface {
Close() error
}
ClosePublisher can be implemented by publishers that hold resources.
type Config ¶
type Config struct {
AppName string
AppEnv string
KafkaBrokers []string
KafkaTopic string
EnablePublishing bool
Publisher Publisher
PublishMinSeverity string
AutoWrapFallbackSeverity string
}
Config holds all the configuration parameters required to initialize the reporter. Passing this struct explicitly via function parameters provides better flexibility and decouples the package from direct environment variable access.
type CustomError ¶
type CustomError struct {
Timestamp string `json:"timestamp"`
Environment string `json:"environment"`
Service string `json:"service"`
Severity string `json:"severity"`
ErrorType string `json:"error_type"`
Description string `json:"description"`
RawError string `json:"raw_error"`
StatusCode int `json:"status_code,omitempty"`
File string `json:"file"`
Line int `json:"line"`
FunctionName string `json:"function"`
}
CustomError is the structured error payload produced by this package.
It contains the information needed for logs and alerts: timestamp, environment, service name, error type, human-readable description, raw error text, caller file path, caller line number, and caller function name. This structure is passed to publishers and can be serialized to JSON for downstream alert delivery, such as Telegram notifications.
func (*CustomError) Error ¶
func (e *CustomError) Error() string
Error returns a formatted representation of the structured error.
In non-production environments it returns a colored terminal-friendly string containing the timestamp, file, line, error type, description, and raw error. In production it returns the JSON representation of CustomError, which is suitable for logs, Kafka messages, and alert consumers.
type KafkaPublisher ¶
type KafkaPublisher struct {
// contains filtered or unexported fields
}
KafkaPublisher publishes error reports to Kafka as JSON.
func NewKafkaPublisher ¶
func NewKafkaPublisher(brokers []string, topic string) *KafkaPublisher
NewKafkaPublisher creates a Kafka-backed reporter publisher.
func (*KafkaPublisher) Close ¶
func (p *KafkaPublisher) Close() error
Close releases the Kafka writer.
func (*KafkaPublisher) Publish ¶
func (p *KafkaPublisher) Publish(ctx context.Context, report *CustomError) error
Publish serializes the report to JSON and writes it to Kafka.
type Publisher ¶
type Publisher interface {
Publish(ctx context.Context, report *CustomError) error
}
Publisher sends a structured error report to an external destination.
Implement this interface when you want to publish reports to something other than the built-in Kafka publisher, such as Redis, a file spool, or a webhook.
type RedisPublisher ¶ added in v2.0.1
type RedisPublisher struct {
// contains filtered or unexported fields
}
RedisPublisher implements the reporter.Publisher interface by appending structured error reports to a Redis list.
Reports are stored with RPUSH, so consumers can process them in FIFO order using LPOP or BLPOP from the same list.
func NewRedisListPublisher ¶ added in v2.0.3
func NewRedisListPublisher(client *redis.Client, listName string) *RedisPublisher
NewRedisListPublisher creates a Redis-backed publisher that appends reports to a Redis list.
It is equivalent to NewRedisPublisher and exists as the clearer constructor for new code.
func NewRedisPublisher ¶ added in v2.0.1
func NewRedisPublisher(client *redis.Client, listName string) *RedisPublisher
NewRedisPublisher creates and initializes a new Redis-backed reporter publisher. It keeps the historical constructor name for compatibility; the destination is now a Redis list, not channel broadcasting.
Parameters:
- client: An active *redis.Client connection instance.
- listName: The target Redis list name where reports will be appended.
Example:
pub := reporter.NewRedisPublisher(rdbClient, "app_error_logs")
func (*RedisPublisher) Publish ¶ added in v2.0.1
func (p *RedisPublisher) Publish(ctx context.Context, report *CustomError) error
Publish serializes the structured CustomError report into a JSON payload and appends it to the configured Redis list using the RPUSH command.
It satisfies the reporter.Publisher interface requirements. Returns an error if JSON marshalling fails or if the Redis server is unreachable.