Go با مثال: لاگ‌گیری

کتابخانهٔ استاندارد Go ابزارهای سرراستی برای تولید لاگ در برنامه‌های Go دارد: بستهٔ log برای خروجی آزاد و بستهٔ log/slog برای خروجی ساخت‌یافته (structured).

package main
import (
    "bytes"
    "fmt"
    "log"
    "os"
    "log/slog"
)
func main() {

صدا زدن ساده‌ی توابعی مثل Println از بستهٔ log از لاگرِ استاندارد استفاده می‌کند که از قبل برای خروجی لاگ معقول در os.Stderr پیکربندی شده است. متدهای دیگری مثل Fatal* یا Panic* پس از ثبت لاگ از برنامه خارج می‌شوند.

    log.Println("standard logger")

لاگرها را می‌توان با فلگ‌ها پیکربندی کرد تا قالب خروجی‌شان تعیین شود. به‌طور پیش‌فرض، لاگر استاندارد فلگ‌های log.Ldate و log.Ltime را دارد که در log.LstdFlags جمع شده‌اند. برای مثال می‌توانیم فلگ‌هایش را تغییر دهیم تا زمان را با دقت میکروثانیه ثبت کند.

    log.SetFlags(log.LstdFlags | log.Lmicroseconds)
    log.Println("with micro")

همچنین از ثبت نام فایل و شماره خطی که تابع log از آن صدا زده شده پشتیبانی می‌کند.

    log.SetFlags(log.LstdFlags | log.Lshortfile)
    log.Println("with file/line")

ممکن است مفید باشد یک لاگر سفارشی بسازیم و آن را جابه‌جا کنیم. هنگام ساختن لاگر جدید می‌توانیم یک پیشوند (prefix) تعیین کنیم تا خروجی‌اش از لاگرهای دیگر قابل تشخیص باشد.

    mylog := log.New(os.Stdout, "my:", log.LstdFlags)
    mylog.Println("from mylog")

با متد SetPrefix می‌توانیم پیشوند لاگرهای موجود (از جمله لاگر استاندارد) را هم تنظیم کنیم.

    mylog.SetPrefix("ohmy:")
    mylog.Println("from mylog")

لاگرها می‌توانند مقصدهای خروجی سفارشی داشته باشند؛ هر io.Writerی کار می‌کند.

    var buf bytes.Buffer
    buflog := log.New(&buf, "buf:", log.LstdFlags)

این فراخوانی خروجی لاگ را در buf می‌نویسد.

    buflog.Println("hello")

این یکی آن را واقعاً در خروجی استاندارد نشان می‌دهد.

    fmt.Print("from buflog:", buf.String())

بستهٔ slog خروجی لاگِ ساخت‌یافته فراهم می‌کند. برای مثال، ثبت لاگ با قالب JSON ساده است.

    jsonHandler := slog.NewJSONHandler(os.Stderr, nil)
    myslog := slog.New(jsonHandler)
    myslog.Info("hi there")

علاوه بر پیام، خروجی slog می‌تواند هر تعداد دلخواه جفت key=value داشته باشد.

    myslog.Info("hello again", "key", "val", "age", 25)
}

نمونهٔ خروجی؛ تاریخ و زمان ثبت‌شده به زمان اجرای مثال بستگی دارد.

$ go run logging.go
2023/08/22 10:45:16 standard logger
2023/08/22 10:45:16.904141 with micro
2023/08/22 10:45:16 logging.go:40: with file/line
my:2023/08/22 10:45:16 from mylog
ohmy:2023/08/22 10:45:16 from mylog
from buflog:buf:2023/08/22 10:45:16 hello

این خطوط برای خوانایی در وب‌سایت شکسته شده‌اند؛ در واقعیت هر کدام در یک خط ثبت می‌شوند.

{"time":"2023-08-22T10:45:16.904166391-07:00",
 "level":"INFO","msg":"hi there"}
{"time":"2023-08-22T10:45:16.904178985-07:00",
    "level":"INFO","msg":"hello again",
    "key":"val","age":25}

مثال بعدی: .