Tags
Tags enable you to categorize and organize logs, making them easier to search, filter, and analyze. Use tags to identify log sources, types, and severity without cluttering log messages.
Tags Overview
Tags are string labels attached to log entries that help identify their source and purpose:
Go
import "github.com/bytehide/bytehide-logs-go"
// Add single tag
logs.WithTags("auth").Info("User login attempt")
// Add multiple tags
logs.WithTags("api", "request", "incoming").
Info("Processing API request")
// Tags with context
logs.WithTags("database", "slow_query").
WithContext("duration_ms", 5000).
Warn("Query execution exceeded threshold")import "github.com/bytehide/bytehide-logs-go"
// Add single tag
logs.WithTags("auth").Info("User login attempt")
// Add multiple tags
logs.WithTags("api", "request", "incoming").
Info("Processing API request")
// Tags with context
logs.WithTags("database", "slow_query").
WithContext("duration_ms", 5000).
Warn("Query execution exceeded threshold")Common Tag Conventions
Functional Tags
Identify system components and functions:
Go
// Authentication and authorization
logs.WithTags("auth", "login").Info("User logged in")
logs.WithTags("auth", "logout").Info("User logged out")
logs.WithTags("auth", "token_refresh").Debug("Token refreshed")
logs.WithTags("auth", "permission_denied").Warn("User lacks permission")
// Order processing
logs.WithTags("order", "creation").Info("Order created")
logs.WithTags("order", "payment").Error("Payment failed", err)
logs.WithTags("order", "shipping").Info("Order shipped")
logs.WithTags("order", "cancellation").Warn("Order cancelled")
// Database operations
logs.WithTags("database", "query").Trace("Executing query")
logs.WithTags("database", "connection").Debug("Connection opened")
logs.WithTags("database", "migration").Info("Running migration")
// API interactions
logs.WithTags("api", "request").Debug("API request sent")
logs.WithTags("api", "response").Debug("API response received")
logs.WithTags("api", "rate_limit").Warn("Rate limit approaching")// Authentication and authorization
logs.WithTags("auth", "login").Info("User logged in")
logs.WithTags("auth", "logout").Info("User logged out")
logs.WithTags("auth", "token_refresh").Debug("Token refreshed")
logs.WithTags("auth", "permission_denied").Warn("User lacks permission")
// Order processing
logs.WithTags("order", "creation").Info("Order created")
logs.WithTags("order", "payment").Error("Payment failed", err)
logs.WithTags("order", "shipping").Info("Order shipped")
logs.WithTags("order", "cancellation").Warn("Order cancelled")
// Database operations
logs.WithTags("database", "query").Trace("Executing query")
logs.WithTags("database", "connection").Debug("Connection opened")
logs.WithTags("database", "migration").Info("Running migration")
// API interactions
logs.WithTags("api", "request").Debug("API request sent")
logs.WithTags("api", "response").Debug("API response received")
logs.WithTags("api", "rate_limit").Warn("Rate limit approaching")Severity/Importance Tags
Distinguish critical operations from routine ones:
Go
// High priority
logs.WithTags("critical", "security").Error("Unauthorized access attempt", err)
logs.WithTags("critical", "payment").Error("Payment processing failed", err)
logs.WithTags("critical", "data_loss").Critical("Data integrity check failed")
// Standard priority
logs.WithTags("standard", "info").Info("User action completed")
logs.WithTags("standard", "debug").Debug("Cache retrieved successfully")
// Low priority
logs.WithTags("internal", "debug").Trace("Internal state calculation")
logs.WithTags("internal", "optimization").Debug("Cache optimization completed")// High priority
logs.WithTags("critical", "security").Error("Unauthorized access attempt", err)
logs.WithTags("critical", "payment").Error("Payment processing failed", err)
logs.WithTags("critical", "data_loss").Critical("Data integrity check failed")
// Standard priority
logs.WithTags("standard", "info").Info("User action completed")
logs.WithTags("standard", "debug").Debug("Cache retrieved successfully")
// Low priority
logs.WithTags("internal", "debug").Trace("Internal state calculation")
logs.WithTags("internal", "optimization").Debug("Cache optimization completed")Domain-Specific Tags
Organize by business domains:
Go
// E-commerce domain
logs.WithTags("ecommerce", "inventory").Info("Stock updated")
logs.WithTags("ecommerce", "pricing").Debug("Price calculated")
logs.WithTags("ecommerce", "checkout").Info("Checkout process started")
// User management domain
logs.WithTags("users", "registration").Info("User registered")
logs.WithTags("users", "profile").Debug("Profile information updated")
logs.WithTags("users", "preferences").Debug("User preferences saved")
// Notification domain
logs.WithTags("notification", "email").Info("Email sent")
logs.WithTags("notification", "sms").Warn("SMS delivery failed")
logs.WithTags("notification", "push").Debug("Push notification queued")// E-commerce domain
logs.WithTags("ecommerce", "inventory").Info("Stock updated")
logs.WithTags("ecommerce", "pricing").Debug("Price calculated")
logs.WithTags("ecommerce", "checkout").Info("Checkout process started")
// User management domain
logs.WithTags("users", "registration").Info("User registered")
logs.WithTags("users", "profile").Debug("Profile information updated")
logs.WithTags("users", "preferences").Debug("User preferences saved")
// Notification domain
logs.WithTags("notification", "email").Info("Email sent")
logs.WithTags("notification", "sms").Warn("SMS delivery failed")
logs.WithTags("notification", "push").Debug("Push notification queued")Fluent API with Tags
Tags with Other Features
Go
// Tags with context
logs.WithTags("payment", "processing").
WithContext("amount", 99.99).
WithContext("currency", "USD").
Info("Processing payment")
// Tags with correlation ID
logs.WithTags("request", "handling").
WithCorrelationID("req_abc123").
WithContext("endpoint", "/api/orders").
Debug("Processing request")
// Tags with exception
err := processPayment()
if err != nil {
logs.WithTags("payment", "error", "critical").
WithException(err).
Error("Payment processing failed", err)
}
// Tags with user
logs.SetUser(&logs.AuthUser{ID: "user_123", Email: "user@example.com"})
logs.WithTags("auth", "action").
WithContext("action", "login").
Info("User logged in")// Tags with context
logs.WithTags("payment", "processing").
WithContext("amount", 99.99).
WithContext("currency", "USD").
Info("Processing payment")
// Tags with correlation ID
logs.WithTags("request", "handling").
WithCorrelationID("req_abc123").
WithContext("endpoint", "/api/orders").
Debug("Processing request")
// Tags with exception
err := processPayment()
if err != nil {
logs.WithTags("payment", "error", "critical").
WithException(err).
Error("Payment processing failed", err)
}
// Tags with user
logs.SetUser(&logs.AuthUser{ID: "user_123", Email: "user@example.com"})
logs.WithTags("auth", "action").
WithContext("action", "login").
Info("User logged in")Practical Examples
Service Layer with Tags
Go
type PaymentService struct {
gateway PaymentGateway
repo PaymentRepository
}
func (s *PaymentService) ProcessPayment(ctx context.Context, orderId string, amount float64) (string, error) {
logs.WithTags("payment", "processing").
WithContext("orderId", orderId).
WithContext("amount", amount).
Info("Starting payment processing")
// Validate amount
if amount <= 0 {
logs.WithTags("payment", "validation").
WithContext("amount", amount).
Warn("Invalid payment amount")
return "", fmt.Errorf("invalid amount")
}
// Call payment gateway
transactionId, err := s.gateway.Charge(ctx, amount)
if err != nil {
logs.WithTags("payment", "gateway", "error").
WithContext("amount", amount).
WithException(err).
Error("Payment gateway request failed", err)
return "", err
}
// Save transaction
err = s.repo.SaveTransaction(&Transaction{
ID: transactionId,
OrderID: orderId,
Amount: amount,
})
if err != nil {
logs.WithTags("payment", "storage", "error").
WithContext("transactionId", transactionId).
WithException(err).
Error("Failed to save transaction", err)
return "", err
}
logs.WithTags("payment", "success").
WithContext("transactionId", transactionId).
WithContext("amount", amount).
Info("Payment processed successfully")
return transactionId, nil
}type PaymentService struct {
gateway PaymentGateway
repo PaymentRepository
}
func (s *PaymentService) ProcessPayment(ctx context.Context, orderId string, amount float64) (string, error) {
logs.WithTags("payment", "processing").
WithContext("orderId", orderId).
WithContext("amount", amount).
Info("Starting payment processing")
// Validate amount
if amount <= 0 {
logs.WithTags("payment", "validation").
WithContext("amount", amount).
Warn("Invalid payment amount")
return "", fmt.Errorf("invalid amount")
}
// Call payment gateway
transactionId, err := s.gateway.Charge(ctx, amount)
if err != nil {
logs.WithTags("payment", "gateway", "error").
WithContext("amount", amount).
WithException(err).
Error("Payment gateway request failed", err)
return "", err
}
// Save transaction
err = s.repo.SaveTransaction(&Transaction{
ID: transactionId,
OrderID: orderId,
Amount: amount,
})
if err != nil {
logs.WithTags("payment", "storage", "error").
WithContext("transactionId", transactionId).
WithException(err).
Error("Failed to save transaction", err)
return "", err
}
logs.WithTags("payment", "success").
WithContext("transactionId", transactionId).
WithContext("amount", amount).
Info("Payment processed successfully")
return transactionId, nil
}HTTP Handler with Tags
Go
func (h *OrderHandler) ListOrders(w http.ResponseWriter, r *http.Request) {
logs.WithTags("api", "request", "orders_list").
WithContext("method", r.Method).
WithContext("path", r.URL.Path).
Debug("Processing orders list request")
// Parse query parameters
page := r.URL.Query().Get("page")
if page == "" {
page = "1"
}
logs.WithTags("api", "pagination").
WithContext("page", page).
Trace("Parsed pagination parameters")
// Fetch orders
orders, err := h.service.GetOrders(page)
if err != nil {
logs.WithTags("api", "database", "error").
WithContext("page", page).
WithException(err).
Error("Failed to fetch orders", err)
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
logs.WithTags("api", "response", "orders_list").
WithContext("count", len(orders)).
Debug("Successfully retrieved orders")
// Return response
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(orders)
}func (h *OrderHandler) ListOrders(w http.ResponseWriter, r *http.Request) {
logs.WithTags("api", "request", "orders_list").
WithContext("method", r.Method).
WithContext("path", r.URL.Path).
Debug("Processing orders list request")
// Parse query parameters
page := r.URL.Query().Get("page")
if page == "" {
page = "1"
}
logs.WithTags("api", "pagination").
WithContext("page", page).
Trace("Parsed pagination parameters")
// Fetch orders
orders, err := h.service.GetOrders(page)
if err != nil {
logs.WithTags("api", "database", "error").
WithContext("page", page).
WithException(err).
Error("Failed to fetch orders", err)
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
logs.WithTags("api", "response", "orders_list").
WithContext("count", len(orders)).
Debug("Successfully retrieved orders")
// Return response
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(orders)
}Background Job with Tags
Go
func (w *Worker) ProcessOrders(ctx context.Context) error {
logs.WithTags("job", "background", "orders").
Info("Starting order processing job")
orders, err := w.repo.GetPendingOrders()
if err != nil {
logs.WithTags("job", "background", "orders", "error").
WithException(err).
Error("Failed to fetch pending orders", err)
return err
}
logs.WithTags("job", "background", "orders").
WithContext("count", len(orders)).
Debug("Processing pending orders")
for _, order := range orders {
err := w.processOrder(ctx, order)
if err != nil {
logs.WithTags("job", "background", "orders", "error").
WithContext("orderId", order.ID).
WithException(err).
Warn("Failed to process order")
continue
}
logs.WithTags("job", "background", "orders", "success").
WithContext("orderId", order.ID).
Trace("Order processed successfully")
}
logs.WithTags("job", "background", "orders").
Info("Order processing job completed")
return nil
}func (w *Worker) ProcessOrders(ctx context.Context) error {
logs.WithTags("job", "background", "orders").
Info("Starting order processing job")
orders, err := w.repo.GetPendingOrders()
if err != nil {
logs.WithTags("job", "background", "orders", "error").
WithException(err).
Error("Failed to fetch pending orders", err)
return err
}
logs.WithTags("job", "background", "orders").
WithContext("count", len(orders)).
Debug("Processing pending orders")
for _, order := range orders {
err := w.processOrder(ctx, order)
if err != nil {
logs.WithTags("job", "background", "orders", "error").
WithContext("orderId", order.ID).
WithException(err).
Warn("Failed to process order")
continue
}
logs.WithTags("job", "background", "orders", "success").
WithContext("orderId", order.ID).
Trace("Order processed successfully")
}
logs.WithTags("job", "background", "orders").
Info("Order processing job completed")
return nil
}Database Operations with Tags
Go
func (r *OrderRepository) GetOrderByID(ctx context.Context, orderId string) (*Order, error) {
logs.WithTags("database", "query", "select").
WithContext("orderId", orderId).
Trace("Executing select query")
query := "SELECT id, customer_id, total, status FROM orders WHERE id = $1"
row := r.db.QueryRowContext(ctx, query, orderId)
var order Order
err := row.Scan(&order.ID, &order.CustomerID, &order.Total, &order.Status)
if err != nil {
if err == sql.ErrNoRows {
logs.WithTags("database", "query", "not_found").
WithContext("orderId", orderId).
Debug("Order not found")
return nil, fmt.Errorf("order not found")
}
logs.WithTags("database", "query", "error").
WithContext("orderId", orderId).
WithException(err).
Error("Query execution failed", err)
return nil, err
}
logs.WithTags("database", "query", "success").
WithContext("orderId", orderId).
Trace("Order retrieved successfully")
return &order, nil
}func (r *OrderRepository) GetOrderByID(ctx context.Context, orderId string) (*Order, error) {
logs.WithTags("database", "query", "select").
WithContext("orderId", orderId).
Trace("Executing select query")
query := "SELECT id, customer_id, total, status FROM orders WHERE id = $1"
row := r.db.QueryRowContext(ctx, query, orderId)
var order Order
err := row.Scan(&order.ID, &order.CustomerID, &order.Total, &order.Status)
if err != nil {
if err == sql.ErrNoRows {
logs.WithTags("database", "query", "not_found").
WithContext("orderId", orderId).
Debug("Order not found")
return nil, fmt.Errorf("order not found")
}
logs.WithTags("database", "query", "error").
WithContext("orderId", orderId).
WithException(err).
Error("Query execution failed", err)
return nil, err
}
logs.WithTags("database", "query", "success").
WithContext("orderId", orderId).
Trace("Order retrieved successfully")
return &order, nil
}Best Practices
Tag Best Practices
- Use consistent tag naming across your codebase (e.g., always use "auth" not "authentication")
- Keep tags concise - use short, meaningful labels
- Combine tags logically - group related concepts (e.g., "payment" with "processing")
- Use lowercase for all tags for consistency
- Avoid high-cardinality tags - don't use dynamic values (use context instead)
- Document tag conventions in your team's logging guidelines
- Limit tags per log - typically 2-4 tags per entry
Tags vs Context
Use tags for static, predefined categories (auth, payment, database). Use context for dynamic, specific values (userId, orderId, duration).