Skip to content

Валидация Field

Подсистема валидации Field в DD проверяет имена ключей структурированных полей перед записью лога, обеспечивая соблюдение соглашений об именовании и защиту безопасности. Она предотвращает трудности парсинга логов из-за несогласованных ключей и перехватывает вредоносный контент, внедряемый через ключи Field.

Режимы валидации

РежимКонстантаПоведение
Отключён (по умолчанию)FieldValidationNoneБез валидации; все ключи принимаются
ПредупреждениеFieldValidationWarnНесоответствующие ключи выводят предупреждение в stderr; лог записывается
СтрогийFieldValidationStrictНесоответствующие ключи выводят ошибку в stderr; лог записывается

Предупреждение Методы логирования не возвращают ошибки

Поскольку методы логирования (InfoWith и т.д.) не возвращают ошибку, неудачная валидация может быть сообщена только через stderr. Строгий режим не предотвращает запись лога, но чётко сообщает об ошибках в stderr.

Соглашения об именовании

СоглашениеКонстантаПримеры
Любое (по умолчанию)NamingConventionAnyБез проверки стиля
snake_caseNamingConventionSnakeCaseuser_id, created_at
camelCaseNamingConventionCamelCaseuserId, createdAt
PascalCaseNamingConventionPascalCaseUserId, CreatedAt
kebab-caseNamingConventionKebabCaseuser-id, created-at

Быстрый старт

Вариант A: готовая конфигурация

go
package main

import (
    "log"

    "github.com/cybergodev/dd"
)

func main() {
    cfg := dd.DefaultConfig()
    cfg.FieldValidation = dd.StrictSnakeCaseConfig()
    // Эквивалентно:
    // &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"),    // ✅ корректный snake_case
        dd.String("userName", "alice"), // ⚠️ некорректно, ошибка в stderr
    )
}

Вариант B: пользовательская конфигурация

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

Вариант C: переключение во время выполнения

go
// Включить строгий snake_case
logger.SetFieldValidation(dd.StrictSnakeCaseConfig())

// Отключить валидацию
logger.SetFieldValidation(nil)

// Запросить текущую конфигурацию
fv := logger.GetFieldValidation()

Исключения для распространённых аббревиатур

С AllowCommonAbbreviations: true (значение по умолчанию для пресетов) следующие аббревиатуры разрешены, даже если они не строго соответствуют соглашению об именовании:

АббревиатураОписание
id, url, uri, ipБазовые идентификаторы
http, https, apiПротоколы и интерфейсы
json, xml, html, sqlФорматы данных
tcp, udp, ssl, tlsСетевые протоколы
jwt, oauthАутентификация
*_id, *_url, *_api и т.д.Комбинации с суффиксами (например, user_id)

Проверки безопасности

EnableSecurityValidation: true (значение по умолчанию для пресетов) выполняет следующие проверки безопасности перед валидацией соглашения об именовании:

ПроверкаПерехватываемый контентОписание
Обнаружение Log4Shell${jndi:ldap://...}Предотвращает JNDI-инъекции через ключи логов
Обнаружение гомографовКириллическая а вместо латинской aПредотвращает атаки визуального подмены
Избыточное кодирование UTF-8Кодирование не в кратчайшей формеПредотвращает обход фильтров безопасности

Опасность Подводный камень нулевого значения

Использование &dd.FieldValidationConfig{Mode: dd.FieldValidationStrict} без установки EnableSecurityValidation оставляет его false (нулевое значение), молча пропуская проверки безопасности. Всегда используйте DefaultFieldValidationConfig() или функции пресетов (StrictSnakeCaseConfig() и т.д.), которые устанавливают это поле в true.

Проекты с несколькими соглашениями

Если в вашем проекте есть как Go-бэкенд (snake_case), так и JavaScript-фронтенд (camelCase) для логирования, используйте разные Logger с разными соглашениями:

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

// Logger агрегации логов фронтенда: camelCase
frontendCfg := dd.DefaultConfig()
frontendCfg.FieldValidation = dd.StrictCamelCaseConfig()
frontendLogger, _ := dd.New(frontendCfg)

Правила валидации

Конкретные правила для каждого соглашения об именовании:

СоглашениеПравила
snake_caseстрочные буквы + цифры + подчёркивания; без _ в начале/конце; без подряд идущих __
camelCaseбуквы + цифры; первый символ — строчная буква
PascalCaseбуквы + цифры; первый символ — заглавная буква
kebab-caseстрочные буквы + цифры + дефисы; без - в начале/конце; без подряд идущих --

Следующие шаги