We’ve covered how to log in eight different languages so far: C#, Java, Python, Ruby, Go, JavaScript, PHP, and Swift We’ve also included a few libraries and platforms, like Log4J, Node.js, Spring Boot, and Rails. Now, it’s time to show how you can get started quickly with Scala logging.
First, I’ll show you with a quick example of manual logging with Scala. I’ll use IntelliJ IDEA to create and run a Scala project, using sbt to build the code. So, you can use the application to get started on any platform that supports Scala and Java.
Then, I’ll discuss details of how and why logging matters. Finally, I’ll move on to using the Scala Logging wrapper in an application and how it can improve your ability to monitor your applications and issues.
Let’s get started!
A Simple Scala Logging Implementation
Creating a Scala Project
We’ll use IntelliJ IDEA for this tutorial. You can download the free community edition here.
First, make sure you have the Scala plugin installed and activated. Start IntelliJ. Before you open any projects, select preferences from the start screen.
Select Plugins from the configure menu.
This will open the plugins management window.
Now, click Install JetBrains plugin… On the bottom left-hand side of the window. This will bring up a window listing the official JetBrains-supported plugins for IDEA.
Now, select the Languages category at the top and scroll down until you find Scala. Install the plugin if it is not already there. You will be prompted to restart the IDE after the plugin is downloaded and restarted.
You’re ready to write Scala applications now!
So, back at the start window, click on Create New Project.
In the next window, select Scala and sbt as shown, and then click “Next.”
Next, give the project a name at the top. Verify that the latest JDK you have available selected, as well as the Scala SDK and sbt version.
If Scala is not installed, no SDK will be available. Click the create button and download the latest available version, 2.12.7 as of this writing. Now, click Finish, and IDEA will create your project.
We have one more step before we start coding. Adding the Scala framework to the project will make creating Scala classes and object easier. After the project is finished loading, right click on the project name in the browser window.
Select Add Framework Support… as shown. This brings up the Add Frameworks window. Scroll down in the left-hand pane until you find Scala. Check the box and then click OK.
That’s it. Let’s write some code!
Simple Scala Logging
Let’s start with a new class. Open up the src folder in the project browser and navigate to the scala folder.
Right-click and select Scala Class.
Change the selector from class to object, and give your new object a name. Then, click OK.
IDEA will create a file and add skeleton code to it.
object LoggingTutorial { }
Now, modify the new class to extend the App class so we can run it, and then add a single line of code.
object LoggingTutorial extends App { println("Hello there!") }
Next, have the IDE run the class. Right click on the object name in the project browser.
Select run in the menu as shown.
A run pane will open in the IDE, and you’ll see the program output.
/Library/Java/JavaVirtualMachines/jdk1.8.0_152.jdk/Contents/Home/bin/java... Hello there! Process finished with exit code 0
That was easy! But now the requirements for your application have changed. You need to not only log to the console, but to a file. Your operations personnel want to be able to go back and look at log messages in the past.
There are several options for writing to a text file in Scala, but let’s use the simplest option. Edit the code in the object, so it looks like this.
import java.io.{File, PrintWriter} object LoggingTutorial extends App { println("Hello there!") val writer = new PrintWriter(new File("output.log")) writer.write("Hello there!") writer.close() }
Now, rerun the program. The output is the same, but a new file appears in the project browser.
Double-click on output.log and the IDE will display the contents.
Hello there!
We have a log file.
There are some issues with this approach. For example, PrintWriter uses the current platform’s default encoding, so log files created on a Mac will not look correct when examined on Windows, and vice versa. Let’s discuss some logging basics, and then we’ll see a better method for Scala logging.
What Is Application Logging?
What is logging? Why do we need it? When do we need it?
You probably have an idea of what logging is, and you may have already dealt with it in an application that you created or maintained. But let’s define it so we can evaluate a logging framework in terms of what we need. Way back in the first article in this series, we defined application logging this way:
Application logging involves recording information about your application’s runtime behavior to a more persistent medium.
Let’s take a close look at this definition.
When we log, we record runtime behavior. We document the events that occur inside an application. While it’s not explicit in this sentence, we can also assume that the events are recorded in chronological order.
Second, we store logs in a more persistent medium. Sometimes application events occur more quickly than we can follow in real time. We want to be able to review them later. Maybe we’re trying to track down an error, or perhaps we have to maintain an audit trail. A persistent medium is a disk, a relational database, or a search engine.
The following list contains some examples of things that you’ll probably want to capture in a log entry:
- A timestamp. Exactly when did the event take place? (You’ll want to record times in UTC and using a standard format such as ISO-8601, in case you’re logging to a file.)
- A context that makes it clear to a reader what the entry’s about. Just recording “Hello, user!” might be difficult to decipher weeks or months later. A better message might say, “User greeting of ‘Hello, user!’”
- Log levels, such as “error,” “warning,” or “information,” that provide context.
Enter the Logging Framework
So, that’s what logging is. Our simple solution above only scratches the surface of what we need for effective logging. It also relies on the developer to open the file, close it, manage the log entry format, and avoid overwriting old log entries when the application is restarted. Also, the solution wouldn’t scale across multiple objects. We would have to write a library or framework for that.
I could continue, but you understand. Creating a sound logging approach requires a lot of work and a lot of thought. But, these problems have already been solved for Java and, as a result, for Scala.
Scala-logging is a library that wraps the Simple Logging Facade for Java (SLF4J) in a Scala-friendly library. SLF4J supports many different logging frameworks, including both log4j, which we’ve covered in an earlier post, and logback a similar framework. We’re going to use logback for this tutorial because the set will be easier.
Let’s get back to the tutorial.
Using a Framework for Scala Logging
First, we need to add SLF4J to our application dependencies. Open build.sbt in the code editor.
Add the dependency for scala-logging, so the file contents look like this.
name := "LoggingTutorial" version := "0.1" scalaVersion := "2.12.7" libraryDependencies += "com.typesafe.scala-logging" %% "scala-logging" % "3.9.0"
Next, we need to download jar files for logback and add them to the runtime classpath.
First, create a new directory in your project folder named libs.
Then, add it to the project’s classpath. Right click on the project name and select Open Module Settings.
Select the Dependencies tab, and then the plus sign to add a directory.
When you select Add jars or directories, IDEA will open a chooser to select the folder. Below is the display for IDEA on a Mac.
Select the folder, and then click OK.
We’ve added a folder to the classpath. Now we need to add the jars. Download the latest logback jars from here. Open the archive and copy logback-classic-XXX.jar and logback-core-XXX.jar to the libs directory, where XXX is the latest version.
We’re finally ready to write some code.
Modify your tutorial class to look like this.
import com.typesafe.scalalogging.Logger object LoggingTutorial extends App { val logger = Logger("Root") logger.info("Hello there!") logger.debug("Hello there!") logger.error("Hello there!") }
We’re importing the logger class, and then creating an instance named logger. Then, we print a log message at the error logging facility.
Rerun the application.
/Library/Java/JavaVirtualMachines/jdk1.8.0_152.jdk/Contents/Home/bin/java... 18:14:29.784 [main] INFO ROOT - Hello there! 18:14:29.789 [main] DEBUG ROOT - Hello there! 18:14:29.789 [main] ERROR ROOT - Hello there! Process finished with exit code 0
SLF4J passed our log messages to logback, and logback printed them to the console, which is the default behavior when no configuration is specified. We see that each log message has a timestamp, a level that corresponds to the function we called with each message, and the name of the thread that logged. We’ve satisfied our list of requirements for log messages, and we wrote less code than in the “simple” example above.
Scala Logging: Mission Accomplished
This is only the beginning. Java’s existing logging frameworks support Scala, so getting started is the easy part. But that doesn’t mean you shouldn’t spend time developing a strategy for logging. If you want to learn more about Scala logging and logging strategies in general, you won’t find a better place than right here on this blog.
Scalyr has a log aggregation tool that can help you manage your log files and data. It’ll help you organize, search, and make sense of your application events. Sign up for a trial today!
This post was written by Eric Goebelbecker. Eric has worked in the financial markets in New York City for 25 years, developing infrastructure for market data and financial information exchange (FIX) protocol networks. He loves to talk about what makes teams effective (or not so effective!)