Help Understanding Logging in OpenMRS

This is probably too academic but anyway here is how it goes. I have been trying to understand how logging works in OpenMRS. I notice that commons-logging dependency is explicitly excluded when declaring dependencies to external libraries in core for example, here, here and a dozen other places in the same POM file. I also noticed there is a dependency on slf4j and log4j. As I am going through the POM I get the impression that developers are supposed to use the SLF4J APIs for logging. However that does not seem to be the case. As far as I can remember I have only seen logging code using the Apache’s commons-logging API. I think most of the developers are familiar with this line of code below in the OpenMRS code base.

private final Log log = LogFactory.getLog(getClass());

Both Log & LogFactory come from the commons library. Personally I have always used that same style. I have three questions.

  1. Why does commons-logging APIs work while it is excluded ? I even tried to do a mvn dependency:resolve| grep commons-logging but it does not come up!
  2. How is logging intended/supposed to work?
  3. Why aren’t the developers using the SLF4J API? ( I am guilty too but I simply started using the style I found being used when I started working on OpenMRS projects).

Thanks in advance.

Note that we are also including jcl-over-slf4j and slf4j-log4j12. As far as I remember these expose the log4j API but uses the slf4j implementation (because commons-logging was buggy or memory leaky or something).

So basically the expectation is to keep using the same (old) log style.

At some level this doesn’t matter, right? It works, and nobody ever has to think about it (e.g. you didn’t even notice for years). :slight_smile:

1 Like

Thanks Darius but your explanation still does not answer my first question, or am I missing something? (Like I said my question is probably too academic but I am curious :smile:)

The answer has to do with the two other dependencies I mentioned. We are using someone else’s implementation of the commons logging API. I don’t remember the specifics but I bet Google will clarify. :slight_smile:

2 Likes

@willa libraries like jcl-over-slf4j and log4j-over-slf4j are intended to be bridges to enable projects to migrate from jcl and log4j respectively to slf4j, there is reasons behind why a project might need to make this migration e.g address classloading issues specifically with jcl and to make their code independent of a particular logging framework but that’s a topic for another day. So jcl-over-slf4j being a bridge it means you can remove the commons logging dependency and not have to make any code changes in your project because it provides classes with the same exact fully qualified names as those of the library you are migrating from or want to push deeper down the layers. Under the hood the bridge will delegate the logging calls to the appropriate binding library for the logging framework of your preference.

FYI slf4j isn’t really a logging framework but rather an abstraction, under the hood it also delegates to a concrete logging implementation like log4j or jcl, kind of like JPA and hibernate, in theory it means you can switch from one logging framework to another by just swapping the jar files.

1 Like

In short to answer @willa’s 3rd question, Log & LogFactory are not coming from commons logging but rather jcl-over-slf4j, if we were moving from log4j to slf4j then we would include log4j-over-slf4j instead which would provide bridge classes for Logger and LoggerFactory, that way we make no code changes.

2 Likes

Thanks man, you totally cleared all my questions.

2 Likes