TeleDec

Zero-dependency Elixir library for declarative telemetry instrumentation using compile-time decorators.

TeleDec provides a clean, efficient way to add telemetry events to your functions with minimal boilerplate. Simply add @telemetry attributes to your functions, and the library handles all the instrumentation at compile-time with negligible runtime overhead.

Features

Installation

Add tele_dec to your list of dependencies in mix.exs:

def deps do
[
{:tele_dec, "~> 0.1.0"}
]
end

Quick Start

Basic Usage with Auto-Inferred Names

# config/config.exs
config :tele_dec, app: :my_app
# lib/my_app/user_service.ex
defmodule MyApp.UserService do
use TeleDec
@telemetry_service :user_service
@telemetry true
def create_user(attrs) do
# Your implementation
# Emits: [:my_app, :user_service, :create_user, :start/:stop/:exception]
end
@telemetry include: [:user_count]
def list_users() do
users = fetch_users()
user_count = length(users) # This will be included in telemetry metadata
users
end
end

Explicit Event Names

defmodule MyApp.Service do
use TeleDec
@telemetry {[:my_app, :service, :process], []}
def process(data) do
# Implementation
# Emits: [:my_app, :service, :process, :start/:stop/:exception]
end
end

Configuration

Global Configuration

Set in config/config.exs:

config :tele_dec,
app: :my_app, # Application name prefix for auto-inferred events
enabled: true # Global enable/disable flag (default: true)

Module Configuration

defmodule MyApp.Service do
use TeleDec
# Set service name for auto-inferred event names
@telemetry_service :service_name
# Functions...
end

Function Options

# Auto-infer event name
@telemetry true
# Auto-infer with options
@telemetry include: [:computed_value]
# Explicit event name
@telemetry {[:custom, :event], [include: [:var1]]}
# Available options:
# - mode: :span (default) or :one_shot
# - include: list of variables to include in stop event metadata
# - args: list of specific arguments to capture (default: all)
# - metadata: set to false to skip all metadata capture
# - enabled: set to false to disable at compile-time

Performance Modes

Span Mode (default)

Full telemetry span with start, stop, and exception events:

@telemetry true
def process(data) do
# ~700ns overhead
end

One-Shot Mode

Single event on completion, approximately 2x faster:

@telemetry mode: :one_shot
def fast_operation(x, y) do
# ~300ns overhead
# No start event, no exception tracking
end

Metadata-Free Mode

Maximum performance, no metadata capture:

@telemetry metadata: false
def high_frequency_operation() do
# Minimal overhead
end

Performance Characteristics

TeleDec is designed for minimal overhead:

All metadata capture happens at compile-time via direct map construction, avoiding runtime reflection and Kernel.binding() calls.

Event Structure

Span Mode Events

One-Shot Mode Events

Attaching Handlers

Use standard :telemetry functions to attach handlers:

:telemetry.attach_many(
"my-handler",
[
[:my_app, :user_service, :create_user, :start],
[:my_app, :user_service, :create_user, :stop],
[:my_app, :user_service, :create_user, :exception]
],
fn event, measurements, metadata, config ->
# Handle event
end,
%{some: :config}
)

Documentation

Full documentation is available on HexDocs.

License

MIT License - see LICENSE for details.

Contributing

Issues and pull requests are welcome on GitHub.