<p align="center">
<h1 align="center">LogDot SDK for Elixir</h1>
<p align="center">
<strong>Cloud logging and metrics made simple</strong>
</p>
</p>
<p align="center">
<a href="https://hex.pm/packages/logdot"><img src="https://img.shields.io/hexpm/v/logdot?style=flat-square&color=blue" alt="Hex.pm version"></a>
<a href="https://hex.pm/packages/logdot"><img src="https://img.shields.io/hexpm/dt/logdot?style=flat-square" alt="Hex.pm downloads"></a>
<a href="https://github.com/logdot-io/logdot-elixir/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-green?style=flat-square" alt="MIT License"></a>
<a href="https://elixir-lang.org/"><img src="https://img.shields.io/badge/elixir-%3E%3D1.14-purple?style=flat-square&logo=elixir&logoColor=white" alt="Elixir 1.14+"></a>
<a href="https://www.erlang.org/"><img src="https://img.shields.io/badge/OTP-%3E%3D25-red?style=flat-square" alt="OTP 25+"></a>
</p>
<p align="center">
<a href="https://logdot.io">Website</a> •
<a href="https://docs.logdot.io">Documentation</a> •
<a href="#quick-start">Quick Start</a> •
<a href="#api-reference">API Reference</a>
</p>
---
## Features
- **Separate Clients** — Independent Logger and Metrics GenServers for maximum flexibility
- **Context-Aware Logging** — Create loggers with persistent context that automatically flows through your application
- **OTP Compliant** — Built as proper OTP application with supervision tree
- **Entity-Based Metrics** — Create/find entities, then bind to them for organized metric collection
- **Batch Operations** — Efficiently send multiple logs or metrics in a single request
- **Automatic Retry** — Exponential backoff retry with configurable attempts
## Installation
Add `logdot` to your dependencies in `mix.exs`:
```elixir
def deps do
[
{:logdot, "~> 1.0"}
]
end
```
## Configuration
```elixir
# config/config.exs
config :logdot,
api_key: "ilog_live_YOUR_API_KEY",
hostname: "my-app",
timeout: 5000,
retry_attempts: 3,
debug: false
```
## Quick Start
```elixir
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# LOGGING
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
LogDot.info("Application started", %{version: "1.0.0"})
LogDot.error("Something went wrong", %{error_code: 500})
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# METRICS
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# Create or find an entity first
{:ok, entity} = LogDot.Metrics.get_or_create_entity(
"my-service",
"My production service",
%{environment: "production"}
)
# Bind to the entity for sending metrics
:ok = LogDot.Metrics.for_entity(entity.id)
# Now send metrics
LogDot.metric("response_time", 123.45, "ms", %{endpoint: "/api/users"})
```
## Logging
### Log Levels
```elixir
LogDot.debug("Debug message")
LogDot.info("Info message")
LogDot.warn("Warning message")
LogDot.error("Error message")
```
### Structured Tags
```elixir
LogDot.info("User logged in", %{
user_id: 12345,
ip_address: "192.168.1.1",
session_id: "abc123"
})
```
### Context-Aware Logging
Create loggers with persistent context that automatically flows through your application:
```elixir
# Create a context for a specific request
ctx = LogDot.with_context(%{request_id: "abc-123", user_id: 456})
# All logs include request_id and user_id automatically
LogDot.info(ctx, "Processing request", %{})
LogDot.debug(ctx, "Fetching user data", %{})
# Chain contexts — they merge together
detailed_ctx = LogDot.with_context(ctx, %{operation: "checkout"})
# This log has request_id, user_id, AND operation
LogDot.info(detailed_ctx, "Starting checkout process", %{})
```
### Batch Logging
Send multiple logs in a single HTTP request:
```elixir
LogDot.begin_batch()
LogDot.info("Step 1 complete")
LogDot.info("Step 2 complete")
LogDot.info("Step 3 complete")
LogDot.send_batch() # Single HTTP request
LogDot.end_batch()
```
## Metrics
### Entity Management
```elixir
# Create a new entity
{:ok, entity} = LogDot.Metrics.create_entity(
"my-service",
"Production API server",
%{environment: "production", region: "us-east-1"}
)
# Find existing entity
{:ok, existing} = LogDot.Metrics.get_entity_by_name("my-service")
# Get or create (recommended)
{:ok, entity} = LogDot.Metrics.get_or_create_entity(
"my-service",
"Created if not exists"
)
```
### Sending Metrics
```elixir
:ok = LogDot.Metrics.for_entity(entity.id)
# Single metric
LogDot.metric("cpu_usage", 45.2, "percent")
LogDot.metric("response_time", 123.45, "ms", %{
endpoint: "/api/users",
method: "GET"
})
```
### Batch Metrics
```elixir
# Same metric, multiple values
LogDot.begin_metric_batch("temperature", "celsius")
LogDot.add_metric(23.5, %{sensor: "room1"})
LogDot.add_metric(24.1, %{sensor: "room2"})
LogDot.add_metric(23.8, %{sensor: "room3"})
LogDot.send_metric_batch()
LogDot.end_metric_batch()
# Multiple different metrics
LogDot.begin_multi_batch()
LogDot.add_multi_metric("cpu", 45.5, "percent")
LogDot.add_multi_metric("memory", 8192, "MB")
LogDot.add_multi_metric("disk", 75.0, "percent")
LogDot.send_metric_batch()
LogDot.end_metric_batch()
```
## API Reference
### LogDot (Main Module)
| Function | Description |
|----------|-------------|
| `with_context(context)` | Create a context struct |
| `with_context(ctx, context)` | Chain contexts together |
| `get_context(ctx)` | Get context map |
| `debug/info/warn/error(message, tags \\ %{})` | Send log at level |
| `debug/info/warn/error(ctx, message, tags)` | Send log with context |
| `begin_batch()` | Start batch mode |
| `send_batch()` | Send queued logs |
| `end_batch()` | End batch mode |
| `clear_batch()` | Clear queue without sending |
### LogDot.Metrics
| Function | Description |
|----------|-------------|
| `create_entity(name, description, metadata)` | Create new entity |
| `get_entity_by_name(name)` | Find entity by name |
| `get_or_create_entity(name, description, metadata)` | Get or create entity |
| `for_entity(entity_id)` | Bind to entity for metrics |
## Requirements
- Elixir 1.14+
- OTP 25+
- [Req](https://hex.pm/packages/req) HTTP client
## License
MIT License — see [LICENSE](LICENSE) for details.
---
<p align="center">
<a href="https://logdot.io">logdot.io</a> •
Built with care for developers
</p>