Skip to content

Field Validation

DD's field validation subsystem validates the key names of structured fields before log write, enforcing naming conventions and providing security protection. It prevents log parsing difficulties from inconsistent keys and intercepts malicious content injected via field keys.

Validation Modes

ModeConstantBehavior
Off (default)FieldValidationNoneNo validation; all keys accepted
WarnFieldValidationWarnNon-conforming keys emit stderr warning; log still written
StrictFieldValidationStrictNon-conforming keys emit stderr error; log still written

Logging methods don't return errors

Since logging methods (InfoWith, etc.) don't return error, validation failures can only be reported via stderr. Strict mode does not prevent the log from being written but clearly reports errors to stderr.

Naming Conventions

ConventionConstantExamples
Any (default)NamingConventionAnyNo style check
snake_caseNamingConventionSnakeCaseuser_id, created_at
camelCaseNamingConventionCamelCaseuserId, createdAt
PascalCaseNamingConventionPascalCaseUserId, CreatedAt
kebab-caseNamingConventionKebabCaseuser-id, created-at

Quick Start

Option A: Preset Config

go
package main

import (
    "log"

    "github.com/cybergodev/dd"
)

func main() {
    cfg := dd.DefaultConfig()
    cfg.FieldValidation = dd.StrictSnakeCaseConfig()
    // Equivalent to:
    // &dd.FieldValidationConfig{
    //     Mode:                     dd.FieldValidationStrict,
    //     Convention:               dd.NamingConventionSnakeCase,
    //     AllowCommonAbbreviations: true,
    //     EnableSecurityValidation: true,
    // }

    logger, err := dd.New(cfg)
    if err != nil {
        log.Fatal(err)
    }
    defer logger.Close()

    logger.InfoWith("user action",
        dd.String("user_id", "123"),    // ✅ valid snake_case
        dd.String("userName", "alice"), // ⚠️ invalid, stderr error
    )
}

Option B: Custom Config

go
cfg := dd.DefaultConfig()
cfg.FieldValidation = &dd.FieldValidationConfig{
    Mode:                     dd.FieldValidationWarn,
    Convention:               dd.NamingConventionCamelCase,
    AllowCommonAbbreviations: true,
    EnableSecurityValidation: true,
}

Option C: Runtime Toggle

go
// Enable strict snake_case
logger.SetFieldValidation(dd.StrictSnakeCaseConfig())

// Disable validation
logger.SetFieldValidation(nil)

// Query current config
fv := logger.GetFieldValidation()

Common Abbreviation Exemptions

With AllowCommonAbbreviations: true (preset default), the following abbreviations are allowed even if they don't strictly match the naming convention:

AbbreviationDescription
id, url, uri, ipBasic identifiers
http, https, apiProtocols & interfaces
json, xml, html, sqlData formats
tcp, udp, ssl, tlsNetwork protocols
jwt, oauthAuthentication
*_id, *_url, *_api, etc.Suffix combinations (e.g., user_id)

Security Validation

EnableSecurityValidation: true (preset default) executes the following security checks before naming convention validation:

CheckIntercepted ContentDescription
Log4Shell detection${jndi:ldap://...}Prevents JNDI injection via log keys
Homograph detectionCyrillic а replacing Latin aPrevents visual spoofing attacks
Overlong UTF-8 encodingNon-shortest-form encodingPrevents bypassing security filters

Zero-value pitfall

Using &dd.FieldValidationConfig{Mode: dd.FieldValidationStrict} without setting EnableSecurityValidation leaves it false (zero value), silently skipping security checks. Always use DefaultFieldValidationConfig() or preset functions (StrictSnakeCaseConfig(), etc.) which set this field to true.

Multi-Convention Projects

If your project has both a Go backend (snake_case) and JavaScript frontend (camelCase) logging, use different Loggers with different conventions:

go
// Backend Logger: snake_case
backendCfg := dd.DefaultConfig()
backendCfg.FieldValidation = dd.StrictSnakeCaseConfig()
backendLogger, _ := dd.New(backendCfg)

// Frontend log aggregation Logger: camelCase
frontendCfg := dd.DefaultConfig()
frontendCfg.FieldValidation = dd.StrictCamelCaseConfig()
frontendLogger, _ := dd.New(frontendCfg)

Validation Rules

Specific rules for each naming convention:

ConventionRules
snake_caselowercase + digits + underscores; no leading/trailing _; no consecutive __
camelCaseletters + digits; first char is lowercase letter
PascalCaseletters + digits; first char is uppercase letter
kebab-caselowercase + digits + hyphens; no leading/trailing -; no consecutive --

Next Steps