# LogsnagEx
[![Hex.pm](https://img.shields.io/hexpm/v/logsnag_ex.svg)](https://hex.pm/packages/logsnag_ex)
[![Docs](https://img.shields.io/badge/hex-docs-blue.svg)](https://hexdocs.pm/logsnag_ex)
An Elixir client for [LogSnag](https://logsnag.com) - The event tracking platform for monitoring your products, services, and user behavior.
## Installation
Add `logsnag_ex` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:logsnag_ex, "~> 1.0.0"}
]
end
```
## Configuration
Configure LogSnag in your `config/config.exs` (or environment-specific config file):
```elixir
config :logsnag_ex,
default: [
token: System.get_env("LOGSNAG_TOKEN"),
project: System.get_env("LOGSNAG_PROJECT"),
disabled: Mix.env() != :prod # optional, defaults to false
]
```
### Multiple Clients
You can configure multiple LogSnag clients for different purposes:
```elixir
config :logsnag_ex,
default: [
token: System.get_env("LOGSNAG_TOKEN"),
project: System.get_env("LOGSNAG_PROJECT")
],
analytics: [
token: System.get_env("LOGSNAG_TOKEN"),
project: System.get_env("LOGSNAG_PROJECT_2"),
name: MyApp.AnalyticsLogSnag
]
```
Then in your application supervision tree:
```elixir
children = [
{LogsnagEx.Client, Application.get_env(:logsnag_ex, :default, [])},
{LogsnagEx.Client, Application.get_env(:logsnag_ex, :analytics, [])}
]
```
## Setup
The library is an OTP application, so it will automatically start its supervision tree. You don't need to add anything to your supervision tree unless you're using multiple clients.
### Single Client (Default)
Just add the configuration to your `config/config.exs`:
```elixir
config :logsnag_ex,
default: [
token: System.get_env("LOGSNAG_TOKEN"),
project: System.get_env("LOGSNAG_PROJECT")
]
```
### Multiple Clients
For multiple clients, configure them in your config:
```elixir
config :logsnag_ex,
default: [
token: System.get_env("LOGSNAG_TOKEN"),
project: System.get_env("LOGSNAG_PROJECT")
],
analytics: [
token: System.get_env("LOGSNAG_TOKEN"),
project: System.get_env("LOGSNAG_PROJECT_2"),
client: MyApp.AnalyticsLogSnag
]
```
Then add the additional clients to your supervision tree:
```elixir
# lib/your_app/application.ex
def start(_type, _args) do
children = [
# ... your other children ...
{LogsnagEx.Client, Application.get_env(:logsnag_ex, :analytics, [])}
]
opts = [strategy: :one_for_one, name: YourApp.Supervisor]
Supervisor.start_link(children, opts)
end
```
## Usage
### Tracking Events
```elixir
# Simple event
LogsnagEx.track("user-signup", "New User Registered")
# Event with all options
LogsnagEx.track("payments", "Payment Received",
description: "User completed payment for premium plan",
icon: "💰",
tags: %{
order_id: "12345",
amount: "$99.99"
},
notify: true,
user_id: "user-123", # Optional user association
parser: "markdown", # Optional: "markdown" or "text"
date: DateTime.utc_now() # Optional timestamp
)
```
### Using Insights
Insights help you track metrics and KPIs:
```elixir
# Track a metric
LogsnagEx.Insight.track("Active Users", 100, icon: "👥")
# Increment a metric
LogsnagEx.Insight.increment("Total Sales", 99.99)
# Using custom client
LogsnagEx.Insight.track("Daily Revenue", 10_000,
client: MyApp.AnalyticsLogSnag
)
```
### User Identification
Track user properties:
```elixir
LogsnagEx.identify("user-123",
%{
email: "user@example.com",
name: "John Doe",
plan: "premium"
}
)
```
### Group Tracking
Track organization or group properties:
```elixir
LogsnagEx.group("user-123", "org-456",
%{
name: "Acme Corp",
plan: "enterprise",
employees: 50
}
)
```
## Options
### Event Tracking Options
- `:description` - Additional details about the event
- `:icon` - Single emoji to represent the event
- `:tags` - Map of key-value pairs for additional data
- `:notify` - Boolean to enable push notifications
- `:parser` - String "markdown" or "text" for description parsing
- `:date` - DateTime for historical events
- `:client` - Atom name of custom client to use
### Insight Options
- `:icon` - Single emoji to represent the insight
- `:client` - Atom name of custom client to use
## Development Environment
For development or testing, you can disable tracking:
```elixir
config :logsnag_ex,
default: [
token: "test-token",
project: "test-project",
disabled: true
]
```
## Testing
The package uses Mox for testing. In your `test_helper.exs`:
```elixir
Mox.defmock(LogsnagEx.MockClient, for: LogsnagEx.Client.Behaviour)
Application.put_env(:logsnag_ex, :client_module, LogsnagEx.MockClient)
```
Example test:
```elixir
test "track/3 sends a log event" do
expect(LogsnagEx.MockClient, :request, fn :post, "/log", body, _name ->
assert body["channel"] == "test-channel"
assert body["event"] == "test-event"
{:ok, body}
end)
assert {:ok, response} = LogsnagEx.track("test-channel", "test-event")
end
```
## Error Handling
All functions return `{:ok, result}` or `{:error, error}`:
```elixir
case LogsnagEx.track("channel", "event") do
{:ok, response} ->
# Handle success
{:error, %LogsnagEx.Error{message: message, data: data}} ->
# Handle error
end
```
## Contributing
1. Fork it
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create new Pull Request
## License
MIT License. See LICENSE for details.