Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace a custom logger with off the shelf implementation #7559

Merged
merged 32 commits into from
Sep 4, 2023

Conversation

hubertp
Copy link
Contributor

@hubertp hubertp commented Aug 10, 2023

Pull Request Description

This change replaces Enso's custom logger with an existing, mostly off the shelf logging implementation. The change attempts to provide a 1:1 replacement for the existing solution while requiring only a minimal logic for the initialization.

Loggers are configured completely via logging-server section in application.conf HOCON file, all initial logback configuration has been removed. This opens up a lot of interesting opportunities because we can benefit from all the well maintained slf4j implementations without being to them in terms of functionality.

Most important differences have been outlined in docs/infrastructure/logging.md.

Important Notes

Addresses:

Checklist

Please ensure that the following checklist has been satisfied before submitting the PR:

  • The documentation has been updated, if necessary.
  • Screenshots/screencasts have been attached, if there are any visual changes. For interactive or animated visual changes, a screencast is preferred.
  • All code follows the
    Scala,
    Java,
    and
    Rust
    style guides. In case you are using a language not listed above, follow the Rust style guide.
  • All code has been tested:
    • Unit tests have been written where possible.
    • If GUI codebase was changed, the GUI was tested when built using ./run ide build.

@hubertp hubertp changed the title Replace a custom logger with sth off the shelf Replace a custom logger with off the shelf implementation Aug 11, 2023
@hubertp hubertp force-pushed the wip/hubert/7253-replace-custom-logger branch from c30d431 to d844b56 Compare August 14, 2023 16:15
Copy link
Member

@JaroslavTulach JaroslavTulach left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not easy for me to see what is an API to use and what is an implementation. I'd like to ensure somehow the implementation classes that implement appenders/loghandlers do not appear on compilation path of modules that only use the logging.

I believe we need a guidance for using the logging. Is it sl4j or jul? What is the format of log record messages to use?

@JaroslavTulach
Copy link
Member

Important note. Currently the slf4j classes are duplicated. They are both in:

enso$ unzip -v runner.jar | grep -i slf4j
enso$ unzip -v runtime.jar | grep -i slf4j

that's wrong. We cannot have two logging API classes and we cannot have two logging implementations!

@hubertp
Copy link
Contributor Author

hubertp commented Aug 21, 2023

Important note. Currently the slf4j classes are duplicated. They are both in:

enso$ unzip -v runner.jar | grep -i slf4j
enso$ unzip -v runtime.jar | grep -i slf4j

that's wrong. We cannot have two logging API classes and we cannot have two logging implementations!

slf4j comes not only from direct libs dependencies that we control but also from indirect dependencies. The assembled jar will have slf4j API classes, no matter whether I turn everything in the repo to jul (I don't plan to) or not.
Runtime has no slf4j implementation, runner does. The former uses jul, the latter does not, that's all intended and works just fine.

@enso-bot
Copy link

enso-bot bot commented Aug 23, 2023

Jaroslav Tulach reports a new STANDUP for yesterday (2023-08-22):

Progress: - argument info PR: #7629

Next Day: Python Interop on Mac CI + better error messages

Discord
Discord is the easiest way to communicate over voice, video, and text. Chat, hang out, and stay close with your friends and communities.

@@ -207,7 +208,7 @@ case class Launcher(cliOptions: GlobalCLIOptions) {
def runRepl(
projectPath: Option[Path],
versionOverride: Option[SemVer],
logLevel: LogLevel,
logLevel: Level,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think having our own logging abstractions has benefits, i.e. whenever we want to change the implementation, the interface will stay the same. Do we really want to swap it with slf4j?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't see any benefit of having a yet another layer of abstraction and slf4j appears to be a the most commonly used one.
The implementation can be easily added (see e.g. logging-truffle-connection) for the existing example.

This change disables an Enso's custom logger with an existing, off the
shelf logging implementation with some custom setup and appenders.
The change attempts to provide a 1:1 replacement for the existing
solution.

Currently configuration is a mixture of `application.conf` HOCON file
with logback's configuration and programatically changed logger's
contexts.
Conversion of raw messages to slf4j's style is now done in the handler.
Still not behaving as expected when setting up loggers for launcher.
When started, launcher should already make use of the logging's
configuration.
Cleaned up implementation for all appenders. All logback configs are
gone, everything is done via our application configs.

Still missing some documentation but no more features are planned.
Ensured that imported subprojects don't add logback in transitive
dependencies and one has to explicitly enable it.
Logback implementation is now completely separate from the API used to
setup logging in different services. Loading is done once, by reading
implementation classes from the configuration file and intializing via
reflection.

Also discovered and fixed various problems with native image compilation.
More documentation that hopefully helps to clarify the usage.
Copy link
Member

@JaroslavTulach JaroslavTulach left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left few comments, but I'd like us to also move forward. Merge soon!

docs/infrastructure/logging.md Outdated Show resolved Hide resolved
docs/infrastructure/logging.md Outdated Show resolved Hide resolved
docs/infrastructure/logging.md Outdated Show resolved Hide resolved
docs/infrastructure/logging.md Show resolved Hide resolved
that corresponds to the indicated stack location, for example `Main.java:123`.
Native methods may be handled differently, as well as code from different
languages, for example Enso also includes the columns - `Test.enso:4:3-19`.
Any custom log level is therefore defined with `-Dx.y.Z.Logger.level` where `x`,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

import org.slf4j.event.Level;

/** Base class to be implemented by the underlying logging implementation. */
public abstract class LoggerSetup {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LoggerSetup is used by "client code" - how can it be in the same project as implementation classes like SocketAppender that shall not be accessed directly?

There should be a module (maybe logging-jutil) that contains just the API to use by "client code". Appender class doesn't need to be visible by "client code", right?

Copy link
Contributor

@4e6 4e6 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left a bunch of comments but overall the PR looks good to me

build.sbt Outdated Show resolved Hide resolved
build.sbt Outdated Show resolved Hide resolved
build.sbt Outdated Show resolved Hide resolved
build.sbt Show resolved Hide resolved
build.sbt Outdated Show resolved Hide resolved
@@ -55,6 +55,10 @@ public void initContext() {
RuntimeOptions.LANGUAGE_HOME_OVERRIDE,
Paths.get("../../distribution/component").toFile().getAbsolutePath()
)
.option(
RuntimeOptions.LOG_LEVEL,
"FINEST"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder how did it pass the formatted check

case TRACE:
return java.util.logging.Level.FINEST;
default:
return java.util.logging.Level.ALL;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The match is already exhaustive. It should be a dead code, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are dealing with Java ;)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Write the code like:

    return switch (l) {
      case DEBUG -> -1;
      case ERROR -> -3;
      case INFO -> 5;
      case WARN -> 10;
      case TRACE -> 1;
    };

and then you will not need to complain.

Copy link
Member

@radeusgd radeusgd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I have looked (did not go too deep), it looks good to me.

Just a few small suggestions from me

@hubertp hubertp added the CI: Clean build required CI runners will be cleaned before and after this PR is built. label Sep 4, 2023
@hubertp hubertp added the CI: Ready to merge This PR is eligible for automatic merge label Sep 4, 2023
@mergify mergify bot merged commit 8a60bc6 into develop Sep 4, 2023
25 checks passed
@mergify mergify bot deleted the wip/hubert/7253-replace-custom-logger branch September 4, 2023 09:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CI: Clean build required CI runners will be cleaned before and after this PR is built. CI: Ready to merge This PR is eligible for automatic merge
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants