Skip to main content

Logger interface

The Logger interface provides structured logging for the TLS Client library. All client operations that generate logs use this interface.
type Logger interface {
    Debug(format string, args ...any)
    Info(format string, args ...any)
    Warn(format string, args ...any)
    Error(format string, args ...any)
}

Methods

Debug
func(format string, args ...any)
Log debug-level messages. Only shown when debug logging is enabled.
Info
func(format string, args ...any)
Log informational messages.
Warn
func(format string, args ...any)
Log warning messages.
Error
func(format string, args ...any)
Log error messages.
All methods use printf-style formatting with a format string and optional arguments.

NewNoopLogger

Creates a logger that discards all log messages. This is the recommended logger for production use when you don’t need logging.
func NewNoopLogger() Logger
Example:
import tls_client "github.com/bogdanfinn/tls-client"

// Create a client with no logging
client, err := tls_client.NewHttpClient(
    tls_client.NewNoopLogger(),
    tls_client.WithClientProfile(profiles.Chrome_144),
)
Use NewNoopLogger() in production to avoid logging overhead.

NewLogger

Creates a logger that prints Info, Warn, and Error messages to stdout. Debug messages are discarded.
func NewLogger() Logger
Example:
import tls_client "github.com/bogdanfinn/tls-client"

// Create a client with basic logging
client, err := tls_client.NewHttpClient(
    tls_client.NewLogger(),
    tls_client.WithClientProfile(profiles.Chrome_144),
)

// Info, Warn, and Error messages will be printed
// Debug messages are still discarded

NewDebugLogger

Creates a logger wrapper that enables debug logging. This wraps an existing logger and enables Debug messages to be printed to stdout.
func NewDebugLogger(logger Logger) Logger
logger
Logger
The base logger to wrap. Debug messages will be printed to stdout, while other messages are forwarded to this logger.
Example:
import tls_client "github.com/bogdanfinn/tls-client"

// Enable debug logging
client, err := tls_client.NewHttpClient(
    tls_client.NewDebugLogger(tls_client.NewLogger()),
    tls_client.WithClientProfile(profiles.Chrome_144),
)

// All log levels (Debug, Info, Warn, Error) will be printed
NewDebugLogger() only affects Debug messages. You can also use the WithDebug() client option to enable comprehensive debug output.

Logger comparison

LoggerDebugInfoWarnErrorUse case
NewNoopLogger()Production (no logging overhead)
NewLogger()Production (basic logging)
NewDebugLogger(NewLogger())Development (full logging)

Custom logger implementation

You can implement your own logger to integrate with your logging infrastructure:
import (
    "log"
    tls_client "github.com/bogdanfinn/tls-client"
)

type CustomLogger struct {
    logger *log.Logger
}

func (l *CustomLogger) Debug(format string, args ...any) {
    l.logger.Printf("[DEBUG] "+format, args...)
}

func (l *CustomLogger) Info(format string, args ...any) {
    l.logger.Printf("[INFO] "+format, args...)
}

func (l *CustomLogger) Warn(format string, args ...any) {
    l.logger.Printf("[WARN] "+format, args...)
}

func (l *CustomLogger) Error(format string, args ...any) {
    l.logger.Printf("[ERROR] "+format, args...)
}

// Use the custom logger
logger := &CustomLogger{
    logger: log.New(os.Stdout, "", log.LstdFlags),
}

client, err := tls_client.NewHttpClient(
    logger,
    tls_client.WithClientProfile(profiles.Chrome_144),
)

Logrus

import (
    "github.com/sirupsen/logrus"
    tls_client "github.com/bogdanfinn/tls-client"
)

type LogrusAdapter struct {
    logger *logrus.Logger
}

func (l *LogrusAdapter) Debug(format string, args ...any) {
    l.logger.Debugf(format, args...)
}

func (l *LogrusAdapter) Info(format string, args ...any) {
    l.logger.Infof(format, args...)
}

func (l *LogrusAdapter) Warn(format string, args ...any) {
    l.logger.Warnf(format, args...)
}

func (l *LogrusAdapter) Error(format string, args ...any) {
    l.logger.Errorf(format, args...)
}

// Use with TLS Client
logger := &LogrusAdapter{
    logger: logrus.New(),
}

client, err := tls_client.NewHttpClient(
    logger,
    tls_client.WithClientProfile(profiles.Chrome_144),
)

Zap

import (
    "go.uber.org/zap"
    tls_client "github.com/bogdanfinn/tls-client"
)

type ZapAdapter struct {
    logger *zap.SugaredLogger
}

func (l *ZapAdapter) Debug(format string, args ...any) {
    l.logger.Debugf(format, args...)
}

func (l *ZapAdapter) Info(format string, args ...any) {
    l.logger.Infof(format, args...)
}

func (l *ZapAdapter) Warn(format string, args ...any) {
    l.logger.Warnf(format, args...)
}

func (l *ZapAdapter) Error(format string, args ...any) {
    l.logger.Errorf(format, args...)
}

// Use with TLS Client
zapLogger, _ := zap.NewProduction()
logger := &ZapAdapter{
    logger: zapLogger.Sugar(),
}

client, err := tls_client.NewHttpClient(
    logger,
    tls_client.WithClientProfile(profiles.Chrome_144),
)
Cookie jars also support custom loggers for debugging cookie operations:
// Create a cookie jar with debug logging
jar := tls_client.NewCookieJar(
    tls_client.WithDebugLogger(),
)

// Or use a custom logger
jar := tls_client.NewCookieJar(
    tls_client.WithLogger(myCustomLogger),
)
See the Cookie jar API reference for details.

What gets logged

Different components log different information:

Client operations

  • Request URLs and methods
  • Response status codes
  • Cookie operations (set, get)
  • Proxy configuration changes
  • Redirect behavior
  • Connection errors

Debug mode (WithDebug option)

  • Raw request bytes sent over the wire
  • Raw response bytes received
  • Request and response headers
  • Request and response body content
  • Protocol negotiation details
Debug mode logs sensitive information including request/response bodies. Never use WithDebug() in production with sensitive data.
  • Cookies being added to the jar
  • Cookies being skipped (with WithSkipExisting())
  • Empty cookies being filtered
  • Expired cookies being excluded

Build docs developers (and LLMs) love