# EppoSdk
[Eppo](https://www.geteppo.com/) is a modular flagging and experimentation analysis tool.
Before proceeding you'll need an Eppo account.
## Features
- Feature gates
- Kill switches
- Progressive rollouts
- A/B/n experiments
- Mutually exclusive experiments (Layers)
- Holdouts
- Contextual multi-armed bandits
- Dynamic configuration
## Installation
Add `eppo_sdk` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:eppo_sdk, "~> 0.1.0"}
]
end
```
## Usage
### Setup
Add the Eppo Client Server to your application's supervision tree:
```elixir
# In your application.ex
defmodule YourApp.Application do
use Application
def start(_type, _args) do
config = %EppoSdk.Client.Config{
api_key: System.get_env("EPPO_API_KEY"),
assignment_logger: YourApp.AssignmentLogger,
# ... other config options ...
}
children = [
# ... other children ...
{EppoSdk.Server, config}
]
opts = [strategy: :one_for_one, name: YourApp.Supervisor]
Supervisor.start_link(children, opts)
end
end
```
### Implementing an Assignment Logger
The assignment logger is used to track experiment assignments for analytics. Implement the `EppoSdk.AssignmentLogger` behaviour in your application:
```elixir
defmodule YourApp.AssignmentLogger do
@behaviour EppoSdk.AssignmentLogger
@impl true
def log_assignment(event) do
# Implement your logging logic here
IO.inspect(event, label: "log_assignment")
end
end
```
### Using the Client
Once the server is started, you can access the client instance anywhere in your application:
```elixir
# Get the client instance
client = EppoSdk.Server.get_instance()
# Use the client to evaluate feature flags
assignment = EppoSdk.Client.get_string_assignment(
client,
"flag-key",
"user-123",
%{},
"default"
)
```
### Manual Start (e.g., for testing)
If you need to start the server manually (not recommended for production):
```elixir
config = %EppoSdk.Client.Config{api_key: "your-api-key", assignment_logger: YourApp.AssignmentLogger}
{:ok, _pid} = EppoSdk.Server.start_link(config)
# When testing locally, wait for the client to initialize
client = EppoSdk.Server.get_instance()
EppoSdk.Client.wait_for_initialization(client)
# Then use as normal
client = EppoSdk.Server.get_instance()
```
Or you can use the client directly:
```elixir
{:ok, client} = EppoSdk.Client.new(config)
# When testing locally, wait for the client to initialize
EppoSdk.Client.wait_for_initialization(client)
```
### Local Development with eppo_core
When developing the Elixir SDK alongside eppo_core, you can configure Cargo to use the local eppo_core package instead of the published version:
1. Copy the template configuration file:
```bash
cp .cargo/config.toml.template .cargo/config.toml
```
2. This will configure Cargo to use the local eppo_core package located at `../eppo_core` relative to the elixir-sdk directory.
3. Compile the SDK to use your local eppo_core version:
```bash
mix compile
```
4. Any changes to the local eppo_core package will now be reflected when you recompile the Elixir SDK.
For publishing releases, make sure to:
1. Test with the published eppo_core version (remove the .cargo/config.toml)
2. Ensure the version in native/sdk_core/Cargo.toml matches the published eppo_core version
### Testing
To run the tests:
```bash
mix test
```