Logování a diagnostika pomocí go-mssqldb

Ovladač go-mssqldb poskytuje konfigurovatelné logování pro řešení problémů s připojením, dotazy a analýzu výkonu. Tento článek popisuje dostupné logovací příznaky a jak používat vlastní loggery.

Příznaky protokolu

Použijte log parametr připojení k aktivaci diagnostického výstupu. Příznaky logu jsou hodnoty bitové masky, což znamená, že je můžete kombinovat sečtením jejich celočíselných hodnot:

Hodnota příznaku Category Description
1 Errors Zapisujte chybové zprávy.
2 Messages Zaznamenávejte informační zprávy ze serveru.
4 Řádky Záznam řádků dat.
8 SQL Zaznamenávejte SQL příkazy odeslané serveru.
16 Parametry Logaritmické názvy a hodnoty parametrů.
32 Transactions Zaznamenávejte události zahájení, potvrzení a vrácení zpět transakcí.
64 Debug Zaznamenávejte detaily nízkoúrovňového protokolu a TDS.
128 Znovupokusy Zaznamenávejte pokusy o opětovné připojení.

Příznaky 4 (řádky) a 16 parametry mohou odhalit aplikační data, tajemství nebo osobně identifikovatelné informace. Považujte je za krátkodobé diagnostické signály, ne za rutinní produkční nastavení.

Examples

Pouze chyby v logu:

sqlserver://<user>:<password>@<server>?database=AdventureWorks2025&log=1

Chyby v logu, SQL příkazy a parametry:

sqlserver://<user>:<password>@<server>?database=AdventureWorks2025&log=25

Note

Hodnota 25 se vypočítá jako 1 + 8 + 16 (chyby + SQL + parametry).

Vše zaznamenávejte:

sqlserver://<user>:<password>@<server>?database=AdventureWorks2025&log=255

Warning

Vysoké hodnoty logaritmu (64, 128, ) 255způsobují rozvláčný výstup a mohou ovlivnit výkon. Používejte je jen na ladění.

Výchozí protokolovač

Ve výchozím nastavení se ovladač loguje do standardního log balíčku Go, který zapisuje do os.Stderr. Výstup zahrnuje časová razítka a kategorii logu:

2026/03/28 10:15:30 mssql: login successful
2026/03/28 10:15:30 mssql: SQL: SELECT 1

Vlastní záznamník pomocí SetLogger

Používá se mssql.SetLogger k přesměrování výstupu z logu ovladače do vlastního loggeru. Logger musí implementovat rozhraní mssql.Logger:

import "github.com/microsoft/go-mssqldb"

type myLogger struct{}

func (l *myLogger) Printf(format string, v ...interface{}) {
    // Write to your preferred logging system
    fmt.Printf("[MSSQL] "+format+"\n", v...)
}

func (l *myLogger) Println(v ...interface{}) {
    fmt.Println(append([]interface{}{"[MSSQL]"}, v...)...)
}

func main() {
    mssql.SetLogger(&myLogger{})
    // ... open connection
}

Protokolovač zohledňující kontext se SetContextLogger

Použijte mssql.SetContextLogger k vytvoření kontextově vnímavého loggeru. Logger musí implementovat mssql.ContextLogger rozhraní, které má jedinou Log metodu přijímající kontext, kategorii logu a řetězec zpráv. Tento přístup umožňuje korelaci záznamů ovladačů s daty trasování podle požadavků (například ID tras):

import (
    "context"
    "log/slog"
    "github.com/microsoft/go-mssqldb"
    "github.com/microsoft/go-mssqldb/msdsn"
)

type contextLogger struct{}

func (l *contextLogger) Log(ctx context.Context, category msdsn.Log, msg string) {
    slog.InfoContext(ctx, msg, "category", category)
}

func main() {
    mssql.SetContextLogger(&contextLogger{})
    // ... open connection
}

Kontrolní seznam diagnostiky

Při řešení problému s připojením nebo dotazem:

  1. Začněte s log=1 pro chyby, nebo log=3 pokud potřebujete i serverové zprávy.
  2. Reprodukujte problém a zkontrolujte chybový text před povolením dalších kategorií.
  3. Přidejte 8 , pokud potřebujete potvrdit, který SQL příkaz nebo volání procedury bylo odesláno.
  4. Přidat 16 nebo 4 pouze v bezpečném prostředí, kde lze zaznamenávat hodnoty parametrů a vrácené řádky bez vystavení citlivých dat.
  5. Pokud problém souvisí s protokolem nebo s opakováním, zvyšte hodnotu na log=64 nebo přidejte 128 pro diagnostiku opakování.
  6. Po vyřešení problému odstraňte nebo omezte záznamy.

Strukturované logování pomocí log/slog

V Go 1.21 bylo zavedeno log/slog pro strukturované logování. Použití SetContextLogger pro směrování výstupu ovladače skrz slog:

import (
    "context"
    "log/slog"
    "os"

    "github.com/microsoft/go-mssqldb"
    "github.com/microsoft/go-mssqldb/msdsn"
)

type slogLogger struct {
    logger *slog.Logger
}

func (l *slogLogger) Log(ctx context.Context, category msdsn.Log, msg string) {
    level := slog.LevelInfo
    if category == msdsn.LogErrors {
        level = slog.LevelError
    }
    if category == msdsn.LogDebug {
        level = slog.LevelDebug
    }

    l.logger.LogAttrs(ctx, level, msg,
        slog.Int("category", int(category)),
    )
}

func main() {
    logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
        Level: slog.LevelInfo,
    }))

    mssql.SetContextLogger(&slogLogger{logger: logger})

    // Connection logging now produces structured JSON.
}

Integrace s nulovým logem

zerolog je strukturovaný logger s nulovou alokací. Směrování logů ovladače přes zerolog:

import (
    "context"
    "os"

    "github.com/microsoft/go-mssqldb"
    "github.com/microsoft/go-mssqldb/msdsn"
    "github.com/rs/zerolog"
)

type zerologAdapter struct {
    logger zerolog.Logger
}

func (l *zerologAdapter) Log(ctx context.Context, category msdsn.Log, msg string) {
    event := l.logger.Info()
    if category == msdsn.LogErrors {
        event = l.logger.Error()
    }
    event.Int("category", int(category)).Msg(msg)
}

func main() {
    logger := zerolog.New(os.Stdout).With().Timestamp().Logger()
    mssql.SetContextLogger(&zerologAdapter{logger: logger})
}

Integrace se Zap

ZAP je vysoce výkonný strukturovaný logger. Trasování řidičských záznamů přes Zap:

import (
    "context"

    "github.com/microsoft/go-mssqldb"
    "github.com/microsoft/go-mssqldb/msdsn"
    "go.uber.org/zap"
)

type zapAdapter struct {
    logger *zap.Logger
}

func (l *zapAdapter) Log(ctx context.Context, category msdsn.Log, msg string) {
    if category == msdsn.LogErrors {
        l.logger.Error(msg, zap.Int("category", int(category)))
    } else {
        l.logger.Info(msg, zap.Int("category", int(category)))
    }
}

func main() {
    logger, _ := zap.NewProduction()
    defer logger.Sync()

    mssql.SetContextLogger(&zapAdapter{logger: logger})
}

Propagace korelačních ID

V distribuovaných systémech přenášejte v kontextu identifikátor korelace, aby bylo možné protokoly ovladače propojit s požadavkem, který je vyvolal:

type correlationKey struct{}

func WithCorrelationID(ctx context.Context, id string) context.Context {
    return context.WithValue(ctx, correlationKey{}, id)
}

func CorrelationID(ctx context.Context) string {
    if id, ok := ctx.Value(correlationKey{}).(string); ok {
        return id
    }
    return "unknown"
}

type correlatedLogger struct {
    logger *slog.Logger
}

func (l *correlatedLogger) Log(ctx context.Context, category msdsn.Log, msg string) {
    l.logger.LogAttrs(ctx, slog.LevelInfo, msg,
        slog.String("correlation_id", CorrelationID(ctx)),
        slog.Int("category", int(category)),
    )
}

Potom předejte ID korelace v kontextu požadavku:

func handleRequest(w http.ResponseWriter, r *http.Request) {
    correlationID := r.Header.Get("X-Correlation-ID")
    if correlationID == "" {
        correlationID = uuid.NewString()
    }

    ctx := WithCorrelationID(r.Context(), correlationID)

    // All database operations using this context will include the correlation ID.
    rows, err := db.QueryContext(ctx, "SELECT TOP (10) ProductID, Name FROM Production.Product")
    // ...
}

Jak používat korelace ID v praxi

Používejte korelační ID jako klíč pro sledování napříč logy, opakovaními a databázovými voláními:

  1. Vygenerujte nebo přijměte korelační ID na hranici požadavku.
  2. Uložit ho do kontextu požadavků a zahrnout do logů aplikací a ovladačů.
  3. Pro řešení potíží na straně SQL to nastavte v kontextu relace pomocí sp_set_session_context a čtěte jej pomocí SESSION_CONTEXT.

Korelační ID nejsou automaticky uložena v tabulkách SQL Server. SESSION_CONTEXT je zaměřená na relaci, takže hodnoty platí pouze pro aktuální připojení a po skončení relace se nepřetrvávají.

Pokud potřebujete trvalou historii, napište korelaci ID explicitně do svých auditních nebo obchodních tabulek (například tabulka AuditLog s correlation_id, časovým razítkem, operací a stavem).

Konfigurace logování produkce

V produkci povolte minimální logování, abyste předešli výkonnostním režijním zátěžím a zabránili zobrazení citlivých dat v logech:

Životní prostředí Doporučená log hodnota Co zachycuje
Development 63 (chyby + zprávy + řádky + SQL + parametry + transakce) Plná viditelnost pro ladění.
Staging 3 (chyby + zprávy) Chyby a serverové zprávy bez detailů dotazu.
Produkce 1 (chyby) nebo 0 (vypnuto) Pouze chyby, nebo úplně vypnout logování ovladačů.

Caution

Příznak Parameters (16) zaznamenává skutečné hodnoty parametrů, které mohou zahrnovat osobní identifikační údaje (PII), hesla nebo jiné citlivé údaje. Nikdy tuto vlajku v produkci nezapínejte. Pro kompletní hodnocení rizik každé vlajky viz nejlepší bezpečnostní postupy.

Potlačení logování při výrobě

Používejte proměnné prostředí k řízení úrovně logu v jednotlivých fázích nasazení:

if os.Getenv("APP_ENV") == "production" {
    // Use only error-level logging in production.
    connString += "&log=1"
} else {
    // Full logging in development.
    connString += "&log=63"
}