Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Log Appender: What Is It and Why Would You Use It?

DZone's Guide to

Log Appender: What Is It and Why Would You Use It?

This article aims to clear up what a log appender is, and why it's integral to the logging process to address certain concerns.

· DevOps Zone ·
Free Resource

Learn more about how CareerBuilder was able to resolve customer issues 5x faster by using Scalyr, the fastest log management tool on the market. 

If you're not familiar with application logging, I can understand there being some confusion when you hear the term "log appender." What do you mean, "append"? I want to write stuff to a file. Isn't that kinda the whole deal with log files?

So let's demystify things a little. A log appender is a specific part of the general logging process. Meaning, yes, logging is often about writing to files, and a log appender can help you with that. But it can actually help you with a whole lot more besides.

The appender is the part of a logging system that's responsible for sending the log messages to some destination or medium. It answers the question "where do you want to store this stuff?"

Anatomy of a Logging Operation

If all you've ever done with logging is dump messages to a file, this might smack of over-engineering. "What do you mean 'part of a logging system'? You call the file API and write stuff to a file."

Well, that certainly works for simple and small cases. But as you expand your logging operation, you might need to get a little more sophisticated since simple file writes will start to create conflicts and other problems. You might even adopt a first-class logging framework. (In fact, you should.) When you do this, logging becomes a more involved proposition, and it's one that you can split into three main concerns:

  • Message recording and formatting. This is where you decide what should go in the log and how to format it.
  • Log appender. This is, as I've already mentioned, the part of the operation that decides where the messages go and how they get there.
  • Log consumption. This can range from someone simply inspecting the logs to sophisticated search, intelligence, and visualization.

Even in the simplest logging implementation, all of these things actually take place. For instance, consider this pseudocode:

public void keepTrackOfSomething() {
     _file.write("This method doesn't seem super-useful", "log.txt", File.Append);
}

Let's see how our three concerns apply.

  • Recording and formatting is just creating the string "This method doesn't seem super-useful."
  • The appending is a simple file write in append mode to "log.txt"
  • Consumption happens later when someone scans through log.txt and reads the message.

The Different Flavors of Log Appender

So you can see that a log appender can, in concept, be as simple as a file dump. And that might be what you're used to. But the world of log appenders is actually much wider than that.

First, ask yourself some questions about just that file, log.txt. Is your code going to write to that file forever? Will you just hum along eternally, hoping the file never grows to gigabyte- and then terabyte-size, clogging your whole disk?

Or do you want to do something to manage the file? Maybe you want to cap it in size and delete the oldest entries as you go. Or maybe you want to create "archive" copies of older versions that a system admin or piece of automation can remove. Even the simple log file has non-trivial concerns when you imagine it in production.

Log appenders address those concerns. A so-called rolling file appender periodically starts logging to a new file, archiving the old one. This style of appender is sophisticated enough to let you configure what triggers backups (set time, certain file size, etc.) and whether or not you compress the backups, among other things.

Of course, the log appender covers a lot more ground than just files. Yes, in case you'd never considered it before, you can log to media other than files. Let's look at a few common examples.

Database Appenders

Logging to files is extremely common, but people also log to databases. Without diving too far into the philosophy behind such things, consider that logs are, in fact, data. And putting data into a database is a perfectly reasonable thing to do.

For instance, Java developers can use the JDBC appender to route log messages in the same way that they'd wire up a connection string and connect to an application database. But you're not limited to traditional relational databases either. Many document databases and NoSQL solutions, in general, have their own appenders as well.

Console Appenders

Have you ever wanted to watch your log in real time, as you debugged? If so, did you do it? If you're using bash, did you do this?

tail -f log.txt

Or maybe you opened the log in Sublime Text and furiously refreshed? Or maybe you just didn't bother?

Well, regardless, you can accomplish this nicely with an appender known as a console appender. This type of appender sends all output to the console for your review as you debug.

Async Appenders

One last interesting example is the async appender. Typically, logging is a relatively low priority in your application. After all, you wouldn't want your application to come screeching to a halt because some debug level message failed to log.

To accommodate this, most logging frameworks execute pretty unobtrusively. But you can take it a step further by using an async appender, which operates on a different, lower priority thread and dispatches messages to other styles of appenders, such as file appenders or database appenders.

Build Your Own Log Appender

If you check out the Apache site, you can see examples of a ton of different appenders. I encourage you to explore them.

But there's an ability that the log appender paradigm earns you that deserves its own section here. Specifically, that's the ability to easily create your own, custom appender, if you so choose.

Logging frameworks have evolved to support a plug-in architecture. This means that the frameworks support both logging appenders that currently exist and also ones that you might dream up. In order to make this work, you just have to have implemented a predefined interface so you adhere to the contract. If you do that, the framework will happily use any appender you build.

This can help immensely if you have a niche need, but be careful with this. There's a good chance you can use and configure an existing appender, and you probably don't want to get into the business of log appenders on top of whatever your actual business is. Take care not to reinvent the wheel.

What Are the Benefits?

Let's close by taking a look at the "why" of all of this. Why use these log appenders and logging frameworks?

Well, as you've no doubt inferred by now, a big benefit is time savings. You don't have to write your own code to manage files or connect to databases - you can just use stuff others have written. And yes, that's critical.

But there's another powerful benefit as well. Log appenders give you a lot of design flexibility because you configure them in application config files and decouple them from both the formatting of log messages and the consumption of the logs. So think back to my humble message from earlier. If you use log appenders instead of the file API, you can configure that message to go to a database, a console, or wherever else, without ever touching a line of your own code. In fact, you can do it without even redeploying. Just change a setting in your config file, and the messages start streaming elsewhere.

Logs provide you with invaluable intelligence about your applications in production. And the log appender gives you the ability to send that intelligence wherever you want, whenever you want.

Find out more about how Scalyr built a proprietary database that does not use text indexing for their log management tool.

Topics:
log appender ,logging ,devops ,application logging

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}