Location Macro — a useful Scala macro

Yasuhiro Matsuda
Keep It Up
Published in
2 min readOct 15, 2014

It is sometimes very useful to know the locations where a particular method is called. Of course your IDE tells you all of the locations in your source code. However, when investigating runtime issues, such as performance bottlenecks in production, logging is a simple yet powerful tool.

How do we know the location of the method invocation? One way is to inspect the stack trace in the invoked method by using Throwable.getStackTrace. Although this works, it may be too expensive to get a stack trace for every invocation at runtime. We want something more lightweight.

In C, there are preprocessor macros __FILE__ and __LINE__ that expand to a file name and a line number. We can do something similar in Scala using a very simple Scala macro. Since this is a macro, the runtime overhead is small. Here is the code.

The Scala compiler evaluates locationMacro at compile time for each place Location.capture is called. It extracts the name of a class and a method and the line number where Location.capture is called. Finally the compiler replaces the Location.capture call with new Location(“[class][method]:line#”)

You can call Location.capture explicitly or implicitly (the capture method is declared as implicit). Adding an implicit parameter of Location to your method may be easier than adding explicit call everywhere.

For example, we added a Location implicit parameter to our transaction method.

The code that calls readWrite must import the capture method into the scope, then it can call readWrite without explicitly calling Location.capture.

Inside the readWrite method, we get the string value from the Location instance passed in and add it to the log message. We find this quite useful in identifying hot spots and bottlenecks in database accesses.

We wrote this post while working on Kifi — Connecting people with knowledge. Learn more.

Originally published at eng.kifi.com on October 15, 2014.

--

--