The benefits of observability into the code we run cannot be overstated. Being able to see problems before they affect functionality, being able to look at the bigger picture of how applications are working; these are just a few of the benefits. But these can only truly be reaped when you not only implement observability tools in your application but consolidate and visualize the data in a way that your team can process swiftly.

This is even truer in the case of Serverless applications — the inherent loss of transparency that running on a serverless provider brings, as well as the problems that are unique to serverless, make it more important than ever to make sure your serverless apps are based on observability.

But observability is a broad term, and cannot be fixed with just one technique of collecting data — and that data most certainly cannot only make sense to a small part of your application team. You need a plan to collect data from many sides and that can be interpreted by all of your dev team. This way comprehensive troubleshooting, and solutions can be performed and created from developer and operations teams.

In this post, we’ll take a look at 3 of the main pillars of observability: Metrics, Tracing, and Logging, and discuss the problems they solve. We’ll also look at the problem each one doesn’t solve, pulling together the idea that it takes a robust solution, using many techniques, to create observability for your serverless applications.

The First Pillar: Metrics

The less you have to instrument your code, the better. And metrics are great in this sense because most providers automate a lot of metrics for your serverless functions without needing to overload your functions with several lines of code. Metrics are easy to visualize, and there are many metrics that are easy to pinpoint thanks to community research and pain.

It’s also very easy to sift through and classify serverless function invocations with metrics; you can see all invocations that took longer than 200ms to run, for example. Metrics are a great and easily implemented way to get started with observability, and the data they provide helps start the context-building process.

But there are definitely reasons that metrics is but one of three of the pillars of observability; metrics are great at telling you what’s going on, but not necessarily as good at pointing to the cause of a problem. Also, if the problem isn’t a blatant issue, or you don’t know precisely what you’re looking for in your data, you can find yourself staring inefficiently at a giant load of graphs.

The Second Pillar: Tracing

Tracing is the action of placing start and stop flags at points in your code and measuring the time that passes between them. This can, when used properly, be used to get a concise and easy-to-digest look at what your functions are doing, and when.

Traces can be used to quickly determine code behavior and pinpoint many performance issues, and lends further classification handles to your invocations; for example, you could find which invocations took more than 100ms on an encryption function. Traces also give you a lot of control over what you measure in your functions, and are great for recording data specific to the problem your function is trying to solve.

However, with great control comes great responsibility; you will usually have to instrument your code in order to obtain tracing data, and knowing when to trace or not is more of an art than a science at this point. The effort, however, is well worth it in large serverless applications, and the time gained in debugging and squashing bugs can be a boon.

The Third Pillar: Logging

Logging is a natural instinct for many developers for a quick debug. Raise your hand if you’ve ever used console.log or an equivalent to debug your code. My hand is raised. Logs are also our oldest friend in the data-gathering world: logging is almost as old as code itself, and certainly internet-eons older than serverless!

Logging can be categorized into many well-known priority levels (info, log, and error are a few). Logs tend to provide a lot of data that can’t be easily captured in metrics, and often provide a lot more context to those trying to debug an issue in their code.

On the other hand…ever read through a log history? It can be a giant wall of text that takes a lot of time to get through, and if it’s your only data source, this can make debugging problems that aren’t caused by something blatant to be a major slog!

The three pillars together: a complete picture of your serverless application

Each of the three pillars of observability gives us a different view of our serverless applications; the magic happens when we intermesh data from all three sources to give ourselves a much more complete view of the hows and whats and whys in the application as a whole — even beyond individual functions.

This full-picture helps us in all stages of serverless application development; from the operations standpoint of making sure everything is running smoothly, to the developer standpoint of debugging issues in the code, and even the business standpoint of making sure the application is using resources (and of course the money to pay for those resources) efficiently.

Logging in IOpipe

We’re happy to show off our third pillar implementation with the release of logging! Logging supports the same log levels you would expect: debug, info, warning, error and critical. You can configure what log level you want to collect in the call to the logger function. To learn more, you can read about it on our blog or check out the logger tutorials for Node.JS and Python.

Want to try it for yourself? Check out our 21-day free trial, or come chat with us in our community Slack to learn more.