Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Sterownik go-mssqldb umożliwia konfigurowalne logowanie do rozwiązywania problemów z połączeniem, zapytań oraz analizy wydajności. Ten artykuł opisuje dostępne flagi logów oraz sposób korzystania z niestandardowych loggerów.
Flagi logów
Użyj parametru połączenia log , aby włączyć wyjście diagnostyczne. Flagi logu to wartości masek bitowych, co oznacza, że można je ze sobą łączyć, dodając wartości liczb całkowitych:
| Wartość flagi | Kategoria | Opis |
|---|---|---|
1 |
Errors | Loguj komunikaty o błędach. |
2 |
Messages | Rejestruj informacyjne wiadomości z serwera. |
4 |
Wiersze | Dane wiersza logu. |
8 |
SQL | Loguj wypowiedzi SQL wysyłane na serwer. |
16 |
Parametry | Loguj nazwy i wartości parametrów. |
32 |
Transactions | Rejestruj zdarzenia rozpoczęcia, zatwierdzania i cofania transakcji. |
64 |
Debug | Rejestruj szczegóły protokołu niskiego poziomu i TDS. |
128 |
Ponowne próby | Rejestruj próby ponowienia połączenia. |
Flagi 4 (wiersze) i 16 (parametry) mogą ujawniać dane aplikacji, informacje poufne lub dane osobowe umożliwiające identyfikację osoby. Traktuj je jako krótkotrwałe sygnały diagnostyczne, a nie jako rutynowe ustawienia produkcyjne.
Examples
Rejestruj tylko błędy:
sqlserver://<user>:<password>@<server>?database=AdventureWorks2025&log=1
Błędy logów, instrukcje SQL i parametry:
sqlserver://<user>:<password>@<server>?database=AdventureWorks2025&log=25
Uwaga / Notatka
Wartość 25 oblicza się jako 1 + 8 + 16 (błędy + SQL + parametry).
Zapisuj wszystko:
sqlserver://<user>:<password>@<server>?database=AdventureWorks2025&log=255
Warning
Wysokie wartości flagi logarytmu (64, 128, 255) powodują rozwlekły wynik i mogą wpływać na wydajność. Używaj ich tylko do debugowania.
Domyślny rejestrator
Domyślnie sterownik zapisuje logi za pomocą standardowego pakietu log języka Go, który zapisuje do os.Stderr. Wyjście zawiera znaczniki czasu oraz kategorię logu:
2026/03/28 10:15:30 mssql: login successful
2026/03/28 10:15:30 mssql: SQL: SELECT 1
Niestandardowy rejestrator z użyciem SetLogger
Użyj mssql.SetLogger, aby przekierować dane wyjściowe dziennika sterownika do niestandardowego rejestratora. Logger musi implementować interfejs 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
}
Logger świadomy kontekstu z SetContextLogger
Użyj mssql.SetContextLogger do zapewnienia loggera uwzględniającego kontekst. Rejestrator musi implementować interfejs mssql.ContextLogger, który udostępnia jedną metodę Log, przyjmującą kontekst, kategorię dziennika oraz ciąg znaków komunikatu. Takie podejście pozwala skorelować logi sterownika z danymi śledzenia powiązanymi z konkretnym żądaniem (na przykład identyfikatorami śledzenia):
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
}
Lista kontrolna diagnostyki
Podczas rozwiązywania problemów z połączeniem lub zapytaniem:
- Zacznij od
log=1dla błędów lublog=3jeśli potrzebujesz też komunikatów serwerowych. - Odtworzyć problem i przejrzeć tekst błędu przed włączeniem kolejnych kategorii.
- Dodaj
8, jeśli musisz potwierdzić, która instrukcja SQL lub które wywołanie procedury zostały wysłane. - Dodaj
16lub4tylko w bezpiecznym środowisku, w którym wartości parametrów i zwracane wiersze mogą być rejestrowane bez ujawniania danych wrażliwych. - Jeśli problem wydaje się dotyczyć poziomu protokołu lub być związany z ponawianiem prób, zwiększ do
log=64lub dodaj128w celu diagnostyki ponawiania prób. - Usuń lub ogranicz logowanie po rozwiązaniu problemu.
Logowanie strukturalne za pomocą log/slog
Go 1.21 wprowadziło log/slog do ustrukturyzowanego logowania. Używa się SetContextLogger do kierowania wyjścia sterownika przez 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.
}
Integracja z zerolog
zerolog to strukturalny logger o zerowej alokacji. Trasowanie logów kierowców przez 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})
}
Integracja z zap
zap to wysokowydajny strukturalny logger. Trasowanie dzienników kierowców przez 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})
}
Propagacja identyfikatora korelacji
W systemach rozproszonych propaguj identyfikator korelacji przez kontekst, aby logi sterowników mogły być skorelowane z żądaniem, które je wywołało:
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)),
)
}
Następnie przekażcie ID korelacji przez kontekst żądania:
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 praktycznie używać identyfikatorów korelacji
Używaj identyfikatorów korelacji jako klucza do śledzenia w logach, ponowieniach i odwołaniach do bazy danych:
- Wygeneruj lub zaakceptuj identyfikator korelacji na granicy żądania.
- Przechowuj go w kontekście żądań i uwzględniaj w logach aplikacji i sterowników.
- Do rozwiązywania problemów po stronie SQL ustaw to w kontekście sesji za pomocą
sp_set_session_contexti odczytaj za pomocąSESSION_CONTEXT.
Identyfikatory korelacji nie są automatycznie przechowywane w tabelach SQL Server.
SESSION_CONTEXT ma zakres sesji, więc wartości dotyczą tylko bieżącego połączenia i nie są zachowywane po zakończeniu sesji.
Jeśli potrzebujesz trwałej historii, zapisz identyfikator korelacji bezpośrednio w tabelach audytowych lub biznesowych (na przykład w tabeli AuditLog zawierającej correlation_id, znacznik czasu, operację i status).
Konfiguracja logowania produkcji
W produkcji należy umożliwić minimalne logowanie, aby uniknąć narzutu wydajnościowego i zapobiec pojawianiu się wrażliwych danych w logach:
| Środowisko | Zalecana log wartość |
Co przechwytuje |
|---|---|---|
| Development |
63 (błędy + wiadomości + wiersze + SQL + parametry + transakcje) |
Pełna widoczność do debugowania. |
| Staging |
3 (błędy + komunikaty) |
Błędy i komunikaty serwera bez szczegółów zapytań. |
| Produkcja |
1 (błędy) lub 0 (wyłączone) |
Tylko błędy albo całkowicie wyłącz rejestrowanie sterownika. |
Uwaga
Flaga Parameters (16) rejestruje rzeczywiste wartości parametrów, które mogą obejmować dane osobowe (PII), hasła lub inne wrażliwe dane. Nigdy nie włączaj tej flagi w produkcji. Pełną ocenę ryzyka każdej flagi można znaleźć w artykule o najlepszych praktykach bezpieczeństwa.
Wyłącz logowanie w środowisku produkcyjnym
Używaj zmiennych środowiskowych do kontrolowania poziomu logu na etapie wdrożenia:
if os.Getenv("APP_ENV") == "production" {
// Use only error-level logging in production.
connString += "&log=1"
} else {
// Full logging in development.
connString += "&log=63"
}