SyLog brings the battle-tested Facility and Severity methodology of Unix Syslog to modern Go applications. It provides a structured, JSON-first logging interface designed to give distributed systems the same level of granular categorisation that system administrators have relied on for decades.
In the world of microservices, a simple string message is rarely enough. By implementing the facility concept, this package allows you to categorise logs not just by what happened, but by where it originated within your architecture (e.g., auth-service, payment-gateway, kernel).
- Contextual Tracing: Automatically captures file locations and line numbers to pinpoint failures.
- RFC-Inspired Severities: Moves beyond simple "Info/Error" levels to include Alert, Critical, and Emergency states.
- Structured Output: Native JSON formatting out of the box, ready for ingestion by ELK, Splunk, or Grafana Loki.
- Developer-Centric API: A clean, variadic interface that feels natural to Go developers.
First you need to add and download SyLog dependency in your Go project.
go get github.com/syniol/go-loggerExample code:
package main
import "github.com/syniol/go-logger"
func main() {
sylog.LogAlert("pay microservice", "mock message for alert log")
}Resulting Output:
{
"level": "alert",
"facility": "pay microservice",
"message": "mock message for alert log",
"trace": [
"location: '/Users/hadi/dev/golang/logger/logger.go' on line: 100"
],
"timestamp": "2023-11-04T21:36:33Z"
}Every log entry is emitted as a structured JSON object. This consistent schema ensures that your logs are machine-readable and ready for high-performance indexing in modern observability stacks.
| Field | Type | Description |
|---|---|---|
level |
string |
The severity level mapped from the invoked method (e.g., alert, warn, info ). Derived from RFC 5424 standards. |
facility |
string |
The logical component or service name. Used as the primary partition for log filtering in distributed environments. |
message |
string |
The primary log descriptor. This is captured from the first argument provided to the logging method. |
trace |
array |
A collection of contextual metadata. The first element is automatically injected with the file path and line number of the caller. Subsequent elements contain any additional variadic arguments passed to the method. |
timestamp |
string |
The UTC time of event generation, formatted according to the ISO 8601 / RFC 3339 standard for universal compatibility. |
The trace field is designed for maximum forensic utility. By capturing the exact line number where the log was triggered, it eliminates the guesswork during incident response. Because it is an array, it keeps your top-level JSON namespace clean while allowing you to pass as much supplemental context as needed.
This package implements the full spectrum of Unix Syslog severity levels. Rather than passing a level as a variable, SyLog provides dedicated methods for each. This ensures type safety and clear intent at the call site.
Choosing the right level is critical for effective alerting and noise reduction in your monitoring dashboards.
| Method | Level | Syslog Code | Use Case |
|---|---|---|---|
LogEmergency() |
Emergency | 0 | System is unusable. Total failure. Everyone gets paged. |
LogAlert() |
Alert | 1 | Immediate action required. e.g., Primary database down. |
LogCritical() |
Critical | 2 | Critical conditions. e.g., Hard device errors or loss of primary functions. |
LogError() |
Error | 3 | Error conditions. Something failed, but the app is still running. |
LogWarning() |
Warning | 4 | Warning conditions. Potential issues that should be investigated. |
LogNotice() |
Notice | 5 | Normal but significant. Non-error events that deserve tracking. |
LogInfo() |
Informational | 6 | Standard operational logs. General ""heartbeat"" of the app. |
LogDebug() |
Debug | 7 | Developer verbosity. Detailed info for troubleshooting. |
In your JSON output, these methods automatically map to the level key. This allows your log aggregator
(Datadog, Grafana, etc.) to apply color-coding and trigger automated alerts based on the numerical priority.
// Severity 1: Trigger SRE page
sylog.LogAlert("vault-service", "Credential rotation failed - Unauthorised access detected")
// Severity 6: Standard audit trail
sylog.LogInfo("user-service", "User ID 505 logged in successfully")Architect's Tip: In a production environment, you should typically set your log sink to ignore
LogDebugandLogInfoto save on storage costs, while ensuringLogWarningand above are always captured.
SyLog is designed to be a transparent sidecar to your application logic. Unlike other logging libraries that may
force a panic() or os.Exit() when a high-severity log is triggered, this package is entirely non-intrusive.
Whether you call LogInfo() or LogEmergency(), the package will:
- Capture the trace and timestamp.
- Format the JSON payload.
- Emit the log to the configured output.
- Return control to your application.
- Testing: Your unit tests won't unexpectedly terminate when testing error-handling paths.
- Graceful Shutdowns: You can log a Critical failure and still allow your application to close database connections or finish inflight requests before exiting.
- Separation of Concerns: We believe a logger’s job is to report, not to decide the lifecycle of your software.
if err != nil {
// The logger records the disaster...
sylog.LogEmergency("kernel", "Memory limit reached, unable to continue")
// ...but YOU decide how to crash.
panic("System Unstable")
}Our LogFatal implementation uses Type Assertion to detect if the underlying io.Writer supports
synchronisation (like *os.File). This ensures that during a catastrophic failure, your logs are
flushed to the disk before the process terminates, preventing "ghost crashes" where the cause of
death is lost in a buffered stream.
In systems architecture, clarity is the antidote to complexity. When adapting the Syslog Facility concept for modern microservices, we are essentially moving from "What happened?" to "Who is responsible?"
In traditional Unix, facilities were predefined (like auth, cron, or kern).
In SyLog package, the Facility becomes a dynamic tag representing the Service Identity.
Unlike traditional loggers that only categorise by severity (Level), SyLog introduces
the Facility parameter as a first-class citizen.
In this package, a Facility represents the Identity of the Component. While the level
tells you the urgency of the message, the facility tells you exactly which microservice
or sub-system generated it.
By explicitly tagging logs with a facility, you provide high-cardinality metadata that modern observability tools (CloudWatch, Prometheus, Datadog) use for indexing and filtering.
| Advantage | Benefit |
|---|---|
| Granular Filtering | Instantly isolate all logs from the billing-engine without parsing complex message strings. |
| Routing Logic | Route logs from the auth facility to a high-security storage bucket while sending frontend logs to standard storage. |
| Alerting Accuracy | Set up monitors that trigger only when alert level logs appear specifically within the database-proxy facility. |
For the best results in distributed environments, we recommend following a consistent naming convention for your facilities:
- Service Name: e.g., payment-microservice
- Sub-system: e.g., worker-pool or cache-layer
- Environment (Optional): e.g., prod-api-gateway
Instead of generic logging:
// Vague: Where did this happen?
sylog.LogError("Database connection timed out")Use the Facility-first approach:
// Precise: The 'order-processor' is the culprit.
sylog.LogError("order-processor", "Database connection timed out")When this reaches CloudWatch or Datadog, you can simply run a query like facility: "order-processor" to see the entire lifecycle of that specific service's behavior.
The document that tracks the performance of the logger package is published in details
at the root of repository BENCHMARKS.md.
| Benchmark Case | Iterations | Memory Allocations | Bytes Allocations | Operation Allocations |
|---|---|---|---|---|
| BenchmarkSyniolLogger | 2792167 | 407.3 ns/op | 336 B/op | 6 allocs/op |
| BenchmarkSyniolLogger | 2944899 | 408.6 ns/op | 336 B/op | 6 allocs/op |
| BenchmarkSyniolLogger | 2927808 | 409.0 ns/op | 336 B/op | 6 allocs/op |
| BenchmarkSlogJSON | 2355129 | 508.6 ns/op | 0 B/op | 0 allocs/op |
| BenchmarkSlogJSON | 2355932 | 513.1 ns/op | 0 B/op | 0 allocs/op |
| BenchmarkSlogJSON | 2373483 | 511.4 ns/op | 0 B/op | 0 allocs/op |
| BenchmarkSlogWithSource | 1000000 | 1056 ns/op | 584 B/op | 6 allocs/op |
| BenchmarkSlogWithSource | 1000000 | 1044 ns/op | 584 B/op | 6 allocs/op |
| BenchmarkSlogWithSource | 1000000 | 1044 ns/op | 584 B/op | 6 allocs/op |
Author: Hadi Tajallaei
Copyright © 2023-2026 Syniol Limited. All rights Reserved.