Логирование
Модуль для декларативного логирования аргументов и результата методов с помощью аннотаций аспектов.
Подключение¶
Скорее всего уже транзитивно подключен из других зависимостей либо из Logback, в противном случае требуется подключить:
Зависимость build.gradle:
Модуль:
Зависимость build.gradle.kts:
Модуль:
Логирование¶
Предполагается использовать специальные комбинации аннотаций для настройки логирование методов.
Аргументов¶
| Уровень логгирования | Лог |
|---|---|
| TRACE, DEBUG |
DEBUG [main] r.t.e.e.Example.doWork: > {data: {numParam: "4"}} |
| INFO |
INFO [main] r.t.e.e.Example.doWork: > |
Результата¶
| Уровень логгирования | Лог |
|---|---|
| TRACE, DEBUG |
DEBUG [main] r.t.e.e.Example.doWork: < {data: {out: "testResult"}} |
| INFO |
INFO [main] r.t.e.e.Example.doWork: < |
Аргументов и результата¶
| Уровень логгирования | Лог |
|---|---|
| TRACE, DEBUG |
DEBUG [main] r.t.e.e.Example.doWork: > {data: {strParam: "s", numParam: "4"}} DEBUG [main] r.t.e.e.Example.doWork: < {data: {out: "testResult"}} |
| INFO |
INFO [main] r.t.e.e.Example.doWork: > INFO [main] r.t.e.e.Example.doWork: < |
Выборочное логирование¶
| Уровень логгирования | Лог |
|---|---|
| TRACE, DEBUG |
INFO [main] r.t.e.e.Example.doWork: < |
| INFO |
INFO [main] r.t.e.e.Example.doWork: < |
Структурированный параметр¶
В случае если представление параметра как строкой не является желаемым поведением,
его можно реализовать интерфейс StructuredArgument и параметр научится логировать себя сам:
public record Entity(String name, String code) implements StructuredArgument {
@Override
public String fieldName() {
return "name";
}
@Override
public void writeTo(JsonGenerator generator) throws IOException {
generator.writeString(name);
}
}
@Log.in
public String doWork(Entity entity) {
return "testResult";
}
| Уровень логгирования | Лог |
|---|---|
| TRACE, DEBUG |
INFO [main] r.t.e.e.Example.doWork: > data={"entity":"Bob"} |
| INFO |
INFO [main] r.t.e.e.Example.doWork: > data={"entity":"Bob"} |
Конвертация параметров¶
В случае если представление параметра как строкой не является желаемым поведением,
его можно переназначить через указание StructuredArgumentMapper напротив желаемого аргумента:
public record Entity(String name, String code) { }
public final class EntityLogMapper implements StructuredArgumentMapper<Entity> {
public void write(JsonGenerator gen, Entity value) throws IOException {
gen.writeString(value.name());
}
}
@Log.in
public String doWork(@Mapping(EntityLogMapper.class) Entity entity) {
return "testResult";
}
data class Entity(val name: String, val code: String)
class EntityLogMapper : StructuredArgumentMapper<Entity> {
@Throws(IOException::class)
override fun write(gen: JsonGenerator, value: Entity) = gen.writeString(value.name)
}
@Log.`in`
fun doWork(@Mapping(EntityLogMapper::class) entity: Entity): String {
return "testResult"
}
| Уровень логгирования | Лог |
|---|---|
| TRACE, DEBUG |
INFO [main] r.t.e.e.Example.doWork: > data={"entity":"Bob"} |
| INFO |
INFO [main] r.t.e.e.Example.doWork: > data={"entity":"Bob"} |
MDC (Mapped Diagnostic Context)¶
Аннотация @Mdc позволяет добавлять пары ключ-значение в MDC (Mapped Diagnostic Context) для структурированного логирования.
MDC позволяет добавлять контекстную информацию к каждому лог-сообщению.
Аннотация может применяться к методам и параметрам методов. Поддерживается множественное применение.
Параметры аннотации @Mdc:
key()- Ключ для MDC записи. Если не указано, используется имя аннотированного параметра.value()- Значение для MDC записи. Если не указано, используется значение аннотированного параметра.global()- Если true, MDC значение будет доступно глобально в рамках потока, а не только во время выполнения метода.
Аннотация параметра¶
В этом случае ключ MDC будет совпадать с именем параметра ("s"), а значением будет значение параметра.
Аннотация параметра с ключом¶
Здесь ключ MDC будет "123", а значением - значение параметра "s".
Аннотация метода¶
В этом примере демонстрируется: - Аннотация метода с локальным MDC значением
Комбинированное¶
В этом примере к методу применены две аннотации MDC, а к параметру одна аннотация.
Генерация значения из кода¶
При вызове метода в MDC будет добавлена запись с ключом "key" и в данном случае значением будет случайный UUID.
Пример лога с MDC:
INFO [main] r.t.e.e.Example.test: > {data: {s: "testValue"}} key=some-uuid-value key1=value2 123=testValue
Сигнатуры¶
Доступные сигнатуры для методов которые поддерживают аннотации из коробки:
Класс не должен быть final, чтобы аспекты работали.
Под T подразумевается тип возвращаемого значения, либо Void.
T myMethod()Optional<T> myMethod()CompletionStage<T> myMethod()CompletionStageMono<T> myMethod()Project Reactor (надо подключить зависимость)Flux<T> myMethod()Project Reactor (надо подключить зависимость)
Класс должен быть open, чтобы аспекты работали.
Под T подразумевается тип возвращаемого значения, либо T?, либо Unit.
myMethod(): Tsuspend myMethod(): TKotlin Coroutine (надо подключить зависимость какimplementation)myMethod(): Flow<T>Kotlin Coroutine (надо подключить зависимость какimplementation)