log.go 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. package internal
  2. import (
  3. "fmt"
  4. "io"
  5. "log"
  6. "log/slog"
  7. "net/http"
  8. "os"
  9. "strings"
  10. )
  11. func InitSlog(level string, sink io.Writer) *slog.Logger {
  12. var programLevel slog.Level
  13. if err := (&programLevel).UnmarshalText([]byte(level)); err != nil {
  14. fmt.Fprintf(os.Stderr, "invalid log level %s: %v, using info\n", level, err)
  15. programLevel = slog.LevelInfo
  16. }
  17. leveler := &slog.LevelVar{}
  18. leveler.Set(programLevel)
  19. h := slog.NewJSONHandler(sink, &slog.HandlerOptions{
  20. AddSource: true,
  21. Level: leveler,
  22. })
  23. result := slog.New(h)
  24. return result
  25. }
  26. func GetRequestLogger(base *slog.Logger, r *http.Request) *slog.Logger {
  27. host := r.Host
  28. if host == "" {
  29. host = r.Header.Get("X-Forwarded-Host")
  30. }
  31. return base.With(
  32. "host", host,
  33. "method", r.Method,
  34. "path", r.URL.Path,
  35. "user_agent", r.UserAgent(),
  36. "accept_language", r.Header.Get("Accept-Language"),
  37. "priority", r.Header.Get("Priority"),
  38. "x-forwarded-for", r.Header.Get("X-Forwarded-For"),
  39. "x-real-ip", r.Header.Get("X-Real-Ip"),
  40. )
  41. }
  42. // ErrorLogFilter is used to suppress "context canceled" logs from the http server when a request is canceled (e.g., when a client disconnects).
  43. type ErrorLogFilter struct {
  44. Unwrap *log.Logger
  45. }
  46. func (elf *ErrorLogFilter) Write(p []byte) (n int, err error) {
  47. logMessage := string(p)
  48. if strings.Contains(logMessage, "context canceled") {
  49. return len(p), nil // Suppress the log by doing nothing
  50. }
  51. if strings.Contains(logMessage, "Unsolicited response received on idle HTTP channel") {
  52. return len(p), nil
  53. }
  54. if elf.Unwrap != nil {
  55. return elf.Unwrap.Writer().Write(p)
  56. }
  57. return len(p), nil
  58. }
  59. func GetFilteredHTTPLogger() *log.Logger {
  60. stdErrLogger := log.New(os.Stderr, "", log.LstdFlags) // essentially what the default logger is.
  61. return log.New(&ErrorLogFilter{Unwrap: stdErrLogger}, "", 0)
  62. }