🌲 Timber - Beautiful, Fast, Powerful Elixir Logging
Timber.io is a hosted service for aggregating logs across your entire stack - any language, any platform, any data source.
Unlike traditional logging tools, Timber integrates with language runtimes to automatically capture in-app context and metadata, turning your text-based logs into rich structured events. Timber integrates with Elixir through this library. And Timber's free-form query tools, real-time tailing, and graphing make using your logs easier than ever.
The result: Beautiful, fast, powerful Elixir logging.
Installation
Grab your API key at Timber.io.
In your
mix.exsfile add the:timberdependency:defp deps do [{:timber, "~> 3.1"}] endIn your
config.exsfile install the Timber logger backend:config :logger, backends: [Timber.LoggerBackends.HTTP], config :timber, api_key: "{{your-api-key}}"Test the pipes with:
mix timber.test_the_pipes
Usage
Timber works directly with the Elixir Logger, making it simple to use and adopt:
# Context is automatically included in all logs within the current process
Timber.add_context(user: %{id: "5c06a0df5f37972e07cb7213"})
# The `:event` metadata key allows for the inclusion of structured data
Logger.info("Order #1234 placed", event: %{order_placed: %{id: 1234, total: 100.54}})
The end result is a well structured JSON object that's easy to work with:
{
"dt": "2019-01-29T17:11:48.992670Z",
"level": "info",
"message": "Order #1234 placed",
"order_placed": {
"id": 1234,
"total": 100.54
},
"context": {
"user": {
"id": "5c06a0df5f37972e07cb7213"
},
"system": {
"pid": 20643,
"hostname": "ec2-44-125-241-8"
},
"runtime": {
"vm_pid": "<0.9960.261>",
"module_name": "MyModule",
"line": 371,
"function": "my_func/2",
"file": "lib/my_app/my_module.ex",
"application": "my_app"
}
}
}
Allowing you to run powerful queries like:
- Tail a user:
context.user.id:5c06a0df5f37972e07cb7213 - Find orders of a certain value:
order_placed.total:>=100 - View logs in the context of the VM process:
context.runtime.vm_pid:"<0.9960.261>"
See more usage examples in our Elixir documentation.
Configuration
All configuration options are documented in the Timber.Config module. Some highlights are:
config :timber, system_context: true- Automatically capture system contextconfig :timber, runtime_context: true- Automatically capture runtime context (Elixir pid, module / file / line number, )config :timber, heroku_context: true- Automatically capture Heroku contextconfig :timber, ec2_context: true- Automatically capture EC2 metadata context- ...see more in the
Timber.Configdocs
Integrations
Upgrade 3rd party library logs with Timber integrations:
:timber_ecto- UpgradeEctologs with context and metadata.:timber_exceptions- Upgrade error logs with context and metadata.:timber_phoenix- UpgradePhoenixlogs with context and metadata.:timber_plug- UpgradePluglogs with context and metadata.
Performance & Reliability
Extreme care was taken into the design of Timber to be fast and reliable:
- Timber works directly with the Elixir [
Logger](https://hexdocs.pm/logger/Logger.html), automatically assuming all of the stability and performance benefits this provides, such as back pressure, load shedding, and defensability aroundLoggerfailures. - Log data is buffered and flushed on an interval to optimize performance and delivery.
- The Timber HTTP backend uses a controlled multi-buffer design to efficiently ship data to the Timber service.
- Connections are re-used and rotated to ensure efficient delivery of log data.
- Delivery failures are retried with an exponential backoff, maximizing successful delivery.
- Msgpack is used for payload encoding for it's superior performance and memory management.
- The Timber service ingest endpoint is a HA servce designed to handle extreme fluctuations of volume, it responds in under 50ms to reduce back pressure.