agentsclimarketplace

Kora aop logging

Skill kora-projects/kora-skills/plugins/kora-v1/skills/kora-aop-logging

Agent Skills for Kora Framework — compile-time DI for Java/Kotlin backend development.

Install
npx -y skills add kora-projects/kora-skills --skill kora-aop-logging

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Declarative method logging in Kora via the logging-common module — @Log (args + result), @Log.in / @Log.out / @Log.result, @Log.off to suppress a parameter or method, and @Mdc for Mapped Diagnostic Context (key/value, ${expr} interpolation, global thread scope). Covers the imperative ru.tinkoff.kora.logging.common.MDC API and the SLF4J-MDC import pitfall. Use when adding entry/exit logging to a service method, enriching logs with contextual keys, hiding sensitive arguments from log output, or wiring LoggingModule into a @KoraApp.

SKILL.md

8.7 KB, as published. Nobody here has run it

Kora AOP Logging — @Log and @Mdc

Declarative, compile-time method logging. The annotation processor generates a *Aspect class around your method; there is no reflection or runtime proxy. The aspect writes through SLF4J, so your Logback configuration controls the final format.

Use this skill when you need to:

  • log method entry/exit with arguments and return value (@Log),
  • enrich every log line of a call with contextual keys (@Mdc),
  • suppress credentials or large payloads from log output (@Log.off),
  • wire LoggingModule into a @KoraApp.

Quick Start

1. Dependencies

logging-common is usually pulled transitively by a logging backend (logging-logback). Add it explicitly only if it is missing. All Kora artifacts inherit their version from the kora-parent BOM — never pin an individual ru.tinkoff.kora:* version.

dependencies {
    koraBom platform("ru.tinkoff.kora:kora-parent:1.2.17")

    // Mandatory: without the annotation processor no aspect is generated
    annotationProcessor "ru.tinkoff.kora:annotation-processors"

    implementation "ru.tinkoff.kora:logging-logback" // pulls logging-common transitively
}

Kotlin replaces the processor with KSP:

ksp "ru.tinkoff.kora:symbol-processors"
implementation "ru.tinkoff.kora:logging-logback"

2. Enable in the application graph

@KoraApp
public interface Application extends LoggingModule { }

3. Log a method

The enclosing class must be non-final (Java) / open (Kotlin) so the aspect can subclass it.

@Component
public class UserService {          // NOT final

    @Log
    public User getUser(String id) {
        return userRepository.findById(id);
    }
}

4. Enrich with MDC

@Log
public User getUser(@Mdc(key = "userId") String id) {
    return userRepository.findById(id); // every log line in this call carries userId=<id>
}

@Log family

All annotations live in ru.tinkoff.kora.logging.common.annotation.

AnnotationEffect
@LogLog on entry and exit
@Log.inLog on method entry only
@Log.outLog on method exit only
@Log.resultLog the return value only
@Log.off on a parameterSuppress that one value in the log line
@Log.off on a methodSuppress all logging for the method

Choosing the level

@Log, @Log.in, and @Log.out accept the level as the annotation value — the attribute is value, not level, and the type is org.slf4j.event.Level.

import org.slf4j.event.Level;

@Log(Level.DEBUG)            // value attribute, not level =
public User getUser(String id) { ... }

Default level is INFO for @Log/@Log.in/@Log.out and DEBUG for @Log.result.

There is no Level.OFForg.slf4j.event.Level only has TRACE, DEBUG, INFO, WARN, ERROR. To disable logging for a method, use @Log.off (not a level).

Output by configured logger level

For @Log on methodWithArgs(String strParam, int numParam) returning "testResult", the actual output depends on the logger level configured in logback.xml for that class:

Logger levelOutput
TRACE / DEBUG> {data: {strParam: "s", numParam: "4"}} then < {data: {out: "testResult"}}
INFO> then < (boundary markers only, no argument or result data)
WARN+nothing

So @Log is safe on hot-path methods in production at INFO — you get execution traces with no PII or large payloads. Drop the logger to DEBUG to see argument/result data.


@Mdc — Mapped Diagnostic Context

@Mdc attaches key/value pairs to Kora's MDC for the duration of the method call (or, with global = true, for the rest of the thread's life). The annotation is @Repeatable, so multiple @Mdc on one method/parameter are allowed.

@Mdc attributeDefaultMeaning
keyannotated parameter / method nameMDC key
valueannotated parameter's runtime valueMDC value; supports ${expr} interpolation
globalfalseIf true, the value stays on the thread after the method returns

On a parameter

public Order create(@Mdc UUID orderId) { ... }            // key = "orderId", value = orderId.toString()
public Order create(@Mdc(key = "order_id") UUID id) { ... } // explicit key

On a method (with interpolation)

${expression} references method parameters by name and can call methods.

@Mdc(key = "tenant", value = "${tenantId}")
@Mdc(key = "requestId", value = "${java.util.UUID.randomUUID().toString()}")
public Order create(String tenantId, CreateOrderDto body) { ... }

Global MDC

@Mdc(key = "tenant", value = "${tenantId}", global = true)
public void enterTenantContext(String tenantId) { ... }

After the method returns, tenant remains in the MDC for the rest of the thread's life. Use sparingly — global keys leak into unrelated work on a pooled thread. Remove them imperatively with the static MDC.remove("tenant") when the unit of work ends.

Imperative API

Kora's imperative MDC is ru.tinkoff.kora.logging.common.MDC (static methods):

import ru.tinkoff.kora.logging.common.MDC;

MDC.put("userId", "42");   // also overloads for Integer, Long, Boolean, StructuredArgumentWriter
MDC.remove("userId");
MDC.get();                 // current MDC instance

Never import org.slf4j.MDC. SLF4J's stock MDC writes into a different thread-local that KoraAsyncAppender does not propagate and Kora's encoder does not render — values silently vanish. IDE auto-import picks the SLF4J one by default; verify the import on every MDC usage. There is no MDC.wrap(...) / MDC.clear() in Kora's API.


Combined example

@Component
public class OrderService {                       // NOT final

    @Log                                          // entry + exit
    @Mdc(key = "tenant", value = "${tenantId}")
    @Mdc(key = "operation", value = "create-order")
    public Order create(
        @Mdc String tenantId,                     // value lands in MDC as tenantId
        @Log.off CreateOrderDto body              // body never appears in log output
    ) {
        return repository.save(body.toEntity());
    }
}

MDC keys present during the call: tenant, operation, tenantId. The log line shows tenantId (and the boundary markers); body is suppressed.


Supported signatures

JavaKotlin
T myMethod()fun myMethod(): T (or T?, Unit)
Optional<T> myMethod()
CompletionStage<T> myMethod()suspend fun myMethod(): T
Mono<T> / Flux<T> (needs io.projectreactor:reactor-core)Flow<T> (needs kotlinx-coroutines-core)

Java class must be non-final; Kotlin class must be open.


Common pitfalls

SymptomFix
@Log compiles but nothing is loggedThe class is final (Java) / not open (Kotlin), or the annotation processor / KSP is missing
MDC values never appear in outputorg.slf4j.MDC imported instead of ru.tinkoff.kora.logging.common.MDC
@Log(level = ...) does not compileThe attribute is value, not level: write @Log(Level.DEBUG)
Looking for Level.OFFIt does not exist; use @Log.off to disable a method
Want full args but see only > / <The logger level for that class is INFO; set it to DEBUG in logback.xml
Sensitive argument leaks into logsAdd @Log.off to that parameter
Global MDC bleeds across requestsAvoid global = true, or remove the key with the static MDC.remove(key) at the end of the unit of work

References

Assets

  • assets/LoggedService.java.template, assets/LoggedService.kt.template — runnable @Log + @Mdc service templates. See assets/README.md.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.