Skip to content

Commit f11e56e

Browse files
authored
Merge pull request #17 from stueccles/batch-implementation
New implementation with batching and retry
2 parents 32517c2 + abe350d commit f11e56e

35 files changed

Lines changed: 965 additions & 2993 deletions

README.md

Lines changed: 77 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,46 @@
11
analytics-elixir
22
================
33

4-
analytics-elixir is a non-supported third-party client for [Segment](https://segment.com)
4+
analytics-elixir is a non-official third-party client for [Segment](https://segment.com). Since version `2.0` it supports
5+
batch delivery of events and retries for the API.
56

6-
## Install
7+
## Installation
78

8-
Add the following to deps section of your mix.exs: `{:segment, github: "stueccles/analytics-elixir"}`
9+
Add `segment` to your list of dependencies in mix.exs
910

10-
and then `mix deps.get`
11+
```
12+
def deps do
13+
[
14+
{:segment, "~> 0.2.0"}
15+
]
16+
end
17+
```
18+
19+
## Documentation
20+
21+
Documentation can be be found at [https://hexdocs.pm/segment](https://hexdocs.pm/segment).
1122

1223
## Usage
1324

14-
Start the Segment agent with your write_key from Segment
15-
```
25+
Start the Segment agent with your write_key from Segment for a HTTP API Server Source
26+
```elixir
1627
Segment.start_link("YOUR_WRITE_KEY")
1728
```
1829
There are then two ways to call the different methods on the API.
19-
A basic way through `Segment.Analytics` or by passing a full Struct
20-
with all the data for the API (allowing Context and Integrations to be set)
30+
A basic way through `Segment.Analytics` functions with either the full event Struct
31+
or some helper methods (also allowing Context and Integrations to be set manually).
2132

22-
## Usage in Phoenix
33+
This way will use the defined GenServer implementation such as `Segment.Analytics.Batcher` which will
34+
queue and batch events to Segment.
2335

24-
This is how I add to a Phoenix project (may not be your preferred way)
25-
26-
1. Add the following to deps section of your mix.exs: `{:segment, github: "stueccles/analytics-elixir"}`
27-
and then `mix deps.get`
28-
2. Add segment to applications list in the Phoenix project mix.exs
29-
ie.
30-
```
31-
def application do
32-
[mod: {FormAndThread, []},
33-
applications: [:phoenix, :phoenix_html, :cowboy, :logger,
34-
:phoenix_ecto, :postgrex, :segment]]
35-
end
36-
```
37-
3. Add a config variable for your write_key (may want to make this environment dependent)
38-
ie.
39-
```
40-
config :segment,
41-
write_key: "2iFFnRsCfi"
42-
```
43-
4. Start the segment agent as a child of the application in the application file under
44-
the lib directory. In the children list add:
45-
```
46-
worker(Segment, [Application.get_env(:segment, :write_key)])
47-
```
36+
The other way is to drop down lower and use `Segment.Http` `send` and `batch` directly. This will require first creating a `client` with `Segment.Http.client/1`/`Segment.Http.client/2`
4837

4938
### Track
50-
```
39+
```elixir
5140
Segment.Analytics.track(user_id, event, %{property1: "", property2: ""})
5241
```
5342
or the full way using a struct with all the possible options for the track call
54-
```
43+
```elixir
5544
%Segment.Analytics.Track{ userId: "sdsds",
5645
event: "eventname",
5746
properties: %{property1: "", property2: ""}
@@ -60,69 +49,110 @@ or the full way using a struct with all the possible options for the track call
6049
```
6150

6251
### Identify
63-
```
52+
```elixir
6453
Segment.Analytics.identify(user_id, %{trait1: "", trait2: ""})
6554
```
6655
or the full way using a struct with all the possible options for the identify call
67-
```
56+
```elixir
6857
%Segment.Analytics.Identify{ userId: "sdsds",
6958
traits: %{trait1: "", trait2: ""}
7059
}
7160
|> Segment.Analytics.identify
7261
```
7362

7463
### Screen
75-
```
64+
```elixir
7665
Segment.Analytics.screen(user_id, name)
7766
```
7867
or the full way using a struct with all the possible options for the screen call
79-
```
68+
```elixir
8069
%Segment.Analytics.Screen{ userId: "sdsds",
8170
name: "dssd"
8271
}
8372
|> Segment.Analytics.screen
8473
```
8574

8675
### Alias
87-
```
76+
```elixir
8877
Segment.Analytics.alias(user_id, previous_id)
8978
```
9079
or the full way using a struct with all the possible options for the alias call
91-
```
80+
```elixir
9281
%Segment.Analytics.Alias{ userId: "sdsds",
9382
previousId: "dssd"
9483
}
9584
|> Segment.Analytics.alias
9685
```
9786

9887
### Group
99-
```
88+
```elixir
10089
Segment.Analytics.group(user_id, group_id)
10190
```
10291
or the full way using a struct with all the possible options for the group call
103-
```
92+
```elixir
10493
%Segment.Analytics.Group{ userId: "sdsds",
10594
groupId: "dssd"
10695
}
10796
|> Segment.Analytics.group
10897
```
10998

11099
### Page
111-
```
100+
```elixir
112101
Segment.Analytics.page(user_id, name)
113102
```
114103
or the full way using a struct with all the possible options for the page call
115-
```
104+
```elixir
116105
%Segment.Analytics.Page{ userId: "sdsds",
117106
name: "dssd"
118107
}
119108
|> Segment.Analytics.page
120109
```
121110

111+
112+
### Using the Segment Context
113+
114+
If you want to set the Context manually you should create a `Segment.Analytics.Context` struct with `Segment.Analytics.Context.new/1`
115+
116+
```elixir
117+
context = Segment.Analytics.Context.new(%{active: false})
118+
119+
Segment.Analytics.track(user_id, event, %{property1: "", property2: ""}, context)
120+
```
121+
122+
## Configuration
123+
124+
The library has a number of configuration options you can use to overwrite default values and behaviours
125+
126+
* `config :segment, :sender_impl` Allows selection of a sender implementation. At the moment this defaults to `Segment.Analytics.Batcher` which will send all events in batch. Change this value to `Segment.Analytics.Sender` to have all messages sent immediately (asyncronously)
127+
* `config :segment, :max_batch_size` The maximum batch size of messages that will be sent to Segment at one time. Default value is 100.
128+
* `config :segment, :batch_every_ms` The time (in ms) between every batch request. Default value is 2000 (2 seconds)
129+
* `config :segment, :retry_attempts` The number of times to retry sending against the segment API. Default value is 3
130+
* `config :segment, :retry_expiry` The maximum time (in ms) spent retrying. Default value is 10000 (10 seconds)
131+
* `config :segment, :retry_start` The time (in ms) to start the first retry. Default value is 100
132+
* `config :segment, :send_to_http` If set to `false`, the libray will override the Tesla Adapter implementation to only log segment calls to `debug` but not make any actual API calls. This can be useful if you want to switch off Segment for test or dev. Default value is true
133+
* `config :segment, :tesla, :adapter` This config option allows for overriding the HTTP Adapter for Tesla (which the library defaults to Hackney).This can be useful if you prefer something else, or want to mock the adapter for testing.
134+
135+
## Usage in Phoenix
136+
137+
This is how I add to a Phoenix project (may not be your preferred way)
138+
139+
1. Add the following to deps section of your mix.exs: `{:segment, "~> 0.2.0"}`
140+
and then `mix deps.get`
141+
2. Add a config variable for your write_key (you may want to make this load from ENV)
142+
ie.
143+
```elixir
144+
config :segment,
145+
write_key: "2iFFnRsCfi"
146+
```
147+
3. Start the Segment GenServer in the supervised children list. In `application.ex` add to the children list:
148+
```elixir
149+
{Segment, Application.get_env(:segment, :write_key)}
150+
```
151+
122152
## Running tests
123153

124-
There are not many tests at the moment. But you can run a live test on your segment
125-
account by running.
154+
There are not many tests at the moment. if you want to run live tests on your account you need to change the config in `test.exs` to `config :segment, :send_to_http, true` and then provide your key as an environment variable.
126155
```
127156
SEGMENT_KEY=yourkey mix test
128157
```
158+

config/config.exs

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,14 @@
1-
# This file is responsible for configuring your application
2-
# and its dependencies with the aid of the Mix.Config module.
3-
use Mix.Config
1+
import Config
42

5-
# This configuration is loaded before any dependency and is restricted
6-
# to this project. If another project depends on this project, this
7-
# file won't be loaded nor affect the parent project. For this reason,
8-
# if you want to provide default values for your application for third-
9-
# party users, it should be done in your mix.exs file.
3+
config :segment,
4+
sender_impl: Segment.Analytics.Batcher,
5+
max_batch_size: 100,
6+
batch_every_ms: 5000
107

11-
# Sample configuration:
12-
#
13-
# config :logger, :console,
14-
# level: :info,
15-
# format: "$date $time [$level] $metadata$message\n",
16-
# metadata: [:user_id]
8+
config :segment,
9+
retry_attempts: 3,
10+
retry_expiry: 10_000,
11+
retry_start: 100
1712

18-
# It is also possible to import configuration files, relative to this
19-
# directory. For example, you can emulate configuration per environment
20-
# by uncommenting the line below and defining dev.exs, test.exs and such.
21-
# Configuration from the imported file will override the ones defined
22-
# here (which is why it is important to import them last).
23-
#
24-
# import_config "#{Mix.env}.exs"
13+
env_config = "#{Mix.env()}.exs"
14+
File.exists?("config/#{env_config}") && import_config(env_config)

config/test.exs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import Config
2+
3+
config :segment, :send_to_http, true

doc/.build

Lines changed: 0 additions & 20 deletions
This file was deleted.

doc/404.html

Lines changed: 0 additions & 89 deletions
This file was deleted.

0 commit comments

Comments
 (0)