Uploaded image for project: 'SonarLint Core Library'
  1. SonarLint Core Library
  2. SLCORE-10

Slf4J appender configuration may conflict with client code

    XMLWordPrintable

    Details

    • Type: Improvement
    • Status: Closed
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 3.5
    • Component/s: None
    • Labels:
      None

      Description

      Current logging architecture

      Sonar analyzers use either slf4j API or the sonar logging API to log. SonarLint core uses mostly the sonar logging API.
      The sonar logging API (implemented in sonar-core) by default forwards all logs to slf4j.

      Generally, when sonarlint is executed as a plugin of the IDE, we want to use slf4j to log to the IDE's logging framework, using it's configuration.
      However, when running an analysis, we want to collect the logs to be able to handle them in a custom way, filtering certain parts out of it and display them in a sonarlint log window. These logs should not be forwarded to the IDE's logging framework. The scope of an analysis includes sonarlint-core (what we could the 'engine'), and the execution of the analyzer plugins.

      The way we currently accomplish this is very hacky: when an analysis starts, we dynamically change the appenders of slf4j to be able to control what happens to the logs. We then assign for each thread it's own configurable sink for the logs, that is used to collect the logs for each analysis (done by thread).

      Because we need to manipulate the appenders, we package in sonarlint-core an implementation of slf4j. This makes slf4j-api complain because it finds multiple bindings with the classloader. The other major problem is that the slf4j implementation might pick up the logging configuration of the IDE, potentially causing us to lose debug logs, for example.
      It's also dangerous for two reasons:

      • If the IDE's logging configuration specifies a class that is not packaged in sonarlint-core (because it was shaded, or because of different versions), sonarlint may fail with ClassNotFoundException;
      • If SonarLint is loaded for some reason with a parent-first classloader, the 'wrong' implementation of slf4j will be picked up;

      Better solution (maybe)

      We should drop the usage of slf4j API in SonarLint and be in full control of the logs. This avoids any collision of implementations of sl4j in the classpath and also avoids sonarlint picking up logging configuration files from the IDE.
      Steps to achieve this:

      1. Keep using slf4j in client-side of sonarlint (to log to the IDE);
      2. Ensure that sonarlint-core only uses sonar logging API;
      3. Create a fake slf4j API that all it does is redirect logs to the sonar logging API;
      4. Modify the classloader that loads sonar plugins to include this fake slf4j API and mask it to prevent slf4j classes to be loaded from the parent classloader;
      5. Include in sonarlint-core a custom implementation of the sonar logging API to have customized sink for the logs, configurable per thread.

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              duarte.meneses Duarte Meneses
              Reporter:
              julien.henry Julien Henry
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

                Dates

                Due:
                Created:
                Updated:
                Resolved: