Git Product home page Git Product logo

Comments (5)

grimsa avatar grimsa commented on June 1, 2024 2

@akkinoc We have kept using version 2 of this lib for now, but with upgrade to Spring Boot 3 and Jakarta EE APIs we're at the point where we either need to find a solution for this issue, or move away from logback-access entirely.

I think I see one low-effort hack that might save us.

(Assuming it is possible to add a Java class in a Kotlin project)
Add a class like this in your library:

package dev.akkinoc.spring.boot.logback.access.tomcat;

import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;

/**
 * This is a hacky workaround for https://github.com/akkinoc/logback-access-spring-boot-starter/issues/98.
 * A user who wants to modify this logic should copy this class and modify it, and make sure the modified class has a higher classloader priority.
 */
class HackyLoggingOverrides {
    /**
     * Returning {@code null} means no override.
     * Returning non-null value will result in that value being logged instead of request body.
     */
    static String overriddenRequestBody(Request request) {
        // By default, no override is used
        return null;
    }

    /**
     * Returning {@code null} means no override.
     * Returning non-null value will result in that value being logged instead of response body.
     */
    static String overriddenResponseBody(Request request, Response response) {
        // By default, no override is used
        return null;
    }
}

and then in https://github.com/akkinoc/logback-access-spring-boot-starter/blob/main/src/main/kotlin/dev/akkinoc/spring/boot/logback/access/tomcat/LogbackAccessTomcatEventSource.kt#L130-L159 add logic like this (sorry for syntax, I don't use Kotlin):

    override val requestContent: String? by lazy(LazyThreadSafetyMode.NONE) {
        // ---- this is the new code enabling the override
        String requestBodyOverride = HackyLoggingOverrides.overriddenRequestBody(request);
        if (requestBodyOverride != null) return requestBodyOverride;
        //  ---- old code below
        val bytes = request.getAttribute(LB_INPUT_BUFFER) as ByteArray?
        if (bytes == null && isFormUrlEncoded(request)) {
            return@lazy requestParameterMap.asSequence()
                .flatMap { (key, values) -> values.asSequence().map { key to it } }
                .map { (key, value) -> encode(key, UTF_8.name()) to encode(value, UTF_8.name()) }
                .joinToString("&") { (key, value) -> "$key=$value" }
        }
        bytes?.let { String(it, UTF_8) }
    }

    // ...

    override val responseContent: String? by lazy(LazyThreadSafetyMode.NONE) {
        //  ---- this is the new code enabling the override
        String responseBodyOverride = HackyLoggingOverrides.overriddenResponseBody(request, response);
        if (responseBodyOverride != null) return responseBodyOverride;
        //  ---- old code below
        if (isImageResponse(response)) return@lazy "[IMAGE CONTENTS SUPPRESSED]"
        val bytes = request.getAttribute(LB_OUTPUT_BUFFER) as ByteArray?
        bytes?.let { String(it, UTF_8) }
    }

This way:

  1. Regular users would likely not abuse it, because HackyLoggingOverrides class is package-private (so not part of the "official" API)
  2. For us it would make it possible to customize the lib with little effort - we'd only need to copy-paste this HackyLoggingOverrides class into our microservice project (leaving package and class name exactly the same), implement the logic we need to suppress some responses, and then Spring would pick up our implementation instead of the one provided in this library, effectively allowing us to change the logic we need to change.
  3. The interim fix is simple to do and would not introduce a lot of technical debt

What do you think?

from logback-access-spring-boot-starter.

grimsa avatar grimsa commented on June 1, 2024 2

@akkinoc I tested 4.1.1 - it works 🎉
Thank you!

In our Java project I added the following class (sharing here so that others could use it as a template):

package dev.akkinoc.spring.boot.logback.access;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.HttpStatus;

/**
 * This is a classloading hack.
 * <p>
 * We are loading a modified version of {@code LogbackAccessHackyLoggingOverrides} as a workaround for missing logback-access feature to suppress
 * logging of some response bodies.
 * <p>
 * The class was copied from 4.1.1 version of {@code logback-access-spring-boot-starter} lib and then modified.
 *
 * @see <a href="https://github.com/akkinoc/logback-access-spring-boot-starter/issues/98">Issue which enabled this workaround</a>
 * @see <a href="https://jira.qos.ch/browse/LOGBACK-1526">LOGBACK-1526</a>
 */
@SuppressWarnings("unused")
public final class LogbackAccessHackyLoggingOverrides {
    private LogbackAccessHackyLoggingOverrides() {
    }

    public static String overriddenRequestBody(HttpServletRequest request) {
        return null;
    }

    public static String overriddenResponseBody(HttpServletRequest request, HttpServletResponse response) {
        boolean shouldSuppressResponseBodyLogging = "/endpoint-that-returns-a-binary-document".equals(request.getServletPath())
                && response.getStatus() == HttpStatus.OK.value();
        return shouldSuppressResponseBodyLogging
                ? "[CONTENTS SUPPRESSED]"
                : null;
    }
}

from logback-access-spring-boot-starter.

akkinoc avatar akkinoc commented on June 1, 2024 1

Thank you for the report!
I think LOGBACK-1526 is difficult to work around with version 3 in Java.
I would like to provide an extension point to resolve the LOGBACK-1526 in a future version.

from logback-access-spring-boot-starter.

akkinoc avatar akkinoc commented on June 1, 2024 1

@grimsa
Thanks for your suggestion! Sorry for the delay.
I've released #379 in v4.1.1, so please give it a try when you can!

from logback-access-spring-boot-starter.

akkinoc avatar akkinoc commented on June 1, 2024

Thanks for trying and sharing! 🎉

from logback-access-spring-boot-starter.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.