Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Logging and Dependency Injection

I try to build and application based on Java.

For dependency injection I use Google Guice.

Now I came up with the problem of logging some information during the application. I do not talk about general logging in a way of method calls etc. I know about AOP and that I can do like method call tracing etc. with that.

What I look for is manual logging. I need some way of logging in nearly each class in my application. So I thought about two options:

  1. getting the logger by using the Guice injection framework doing this for me through the constructor (or setter or private ...) but it feels like adding the logging concern really to each class and pollutes my constructor
  2. using a global service locator in the method where I want to call the log. Uhh but all DI fans will hate me for doing that

So what is the best way from a practical point of view?

like image 510
SimFirehawk Avatar asked Jul 12 '13 11:07

SimFirehawk


People also ask

What is the role of dependencies for logging?

Logging is a very important dependency for Spring because a) it is the only mandatory external dependency, b) everyone likes to see some output from the tools they are using, and c) Spring integrates with lots of other tools all of which have also made a choice of logging dependency.

What are the three types of dependency injection?

There are three main styles of dependency injection, according to Fowler: Constructor Injection (also known as Type 3), Setter Injection (also known as Type 2), and Interface Injection (also known as Type 1).

Which dependency is used for log?

In the case of logging, the only mandatory dependency is Apache Commons Logging. We need to import it only when using Spring 4.

What is logging in .NET Core?

In ASP.NET Core, logging providers store the logs. You can configure multiple logging providers for your application. The default ASP.NET Core configures the following logging providers: Console, Debug, EventSource, and EventLog (on Windows).


1 Answers

I need some way of logging in nearly each class in my application.

Think again. If you think you need logging in nearly every class, there is something wrong with your design. This Stackoverflow answer talks about what might be wrong with your design. It's answered in the context of .NET, but the answer is applicable to Java as well.

That answer mainly talks about exception logging, for non-exception logging I would say: Prevent logging too much information at too many places. For each info or warning that you want to log, question whether this shouldn't have been an exception in the first place. For instance, don't log things like "we shouldn't be in this branch", but throw an exception!

And even when you want to log debug information, does anyone ever going to read this? You'll end up with log files with thousands and thousands of lines that nobody will read. And if they read it, they have to wade through all those lines of text and do complicated regex searches through it to get the information they were looking for.

Another reason I see developers do this is to cover up for their bad code. Just as comments are used in this way. I see developers log things like "we have executed this block" or "this if branch skipped". This way they can trace through the code and big methods.

However, instead of writing big methods, we all know by now that methods should be small. No, even smaller. Besides, if you unit test your code thoroughly, there is not much reason to debug the code and you have verified that it does what it is supposed to do.

And again good design can help here. When you use a design as described in that Stackoverflow answer (with command handlers), you can again create a single decorator that can serialize any arbitrary command message and log it to disk before the execution starts. This gives you an amazingly accurate log. Just add some context information (such as execution time and user name) to the log and you have an audit trail that could even be used to replay commands during debugging or even load testing.

I use this type of application design for a couple of years now, and since then, I hardly ever have any reason to do extra logging within the business logic. It is needed now and then, but those cases are pretty rare.

but it feels like adding the logging concern really to each class and pollutes my constructor

It does, and you'll end up with constructors with too many parameters. But don't blame the logger, blame your code. You are violating the Single Responsibility Principle here. You can 'hide' this dependency by calling it through a static facade, but that doesn't lower the number of dependencies and overall complexity of a class.

using a global service locator in the method where I want to call the log. Uhh but all DI fans will hate me for doing that

In the end, you will hate yourself for that, because every class is still has an extra dependency (a well hidden dependency in this case). This makes each class more complicated, and will force you to have more code: more code to test, more code to have bugs, more code to maintain.

like image 60
Steven Avatar answered Sep 22 '22 14:09

Steven