Skip to content

Commit

Permalink
Add retry mechanism (#18)
Browse files Browse the repository at this point in the history
  • Loading branch information
altjohndev authored Apr 29, 2024
1 parent c47f410 commit 98925d2
Show file tree
Hide file tree
Showing 20 changed files with 647 additions and 751 deletions.
2 changes: 2 additions & 0 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
elixir 1.16.0-otp-26
erlang 26.2.1
29 changes: 26 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,44 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Changed

- Replaced `HTTPoison` library with `Tesla`.

### Removed

- Removed `Agent` strategy in favor of configuration. See `t:Segment.options/0` for configuration
instructions.

### Added

- Retry mechanism for Segment API requests.
- Request and response logs through `MetaLogger`.
- Additional options available (see `t:Segment.options/0` for documentation):
- `:disable_meta_logger`
- `:filter_body`
- `:http_adapter`
- `:max_retries`
- `:request_timeout`
- `:retry_base_delay`
- `:retry_jitter_factor`
- `:retry_max_delay`

## [1.3.1] - 2022-03-17

## Changed
### Changed

- Update the `miss` library.

## [1.3.0] - 2022-03-16

## Changed
### Changed

- Fix the encoding for Decimal, Date and DateTime structs.

## [1.2.1] - 2022-02-25

## Changed
### Changed

- Bump Poison to v5.0.

Expand Down
128 changes: 54 additions & 74 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,63 +1,47 @@
analytics-elixir ![analytics-elixir](https://github.com/FindHotel/analytics-elixir/workflows/analytics-elixir/badge.svg?branch=master)
================
# analytics-elixir ![analytics-elixir](https://github.com/FindHotel/analytics-elixir/workflows/analytics-elixir/badge.svg?branch=master)

analytics-elixir is a non-supported third-party client for [Segment](https://segment.com)

## Install
## Installation

Add the following to deps section of your mix.exs: `{:segment, github: "FindHotel/analytics-elixir"}`
Add the following to deps section of your mix.exs:

and then `mix deps.get`
```elixir
{:segment, github: "FindHotel/analytics-elixir"}
```

## Usage
And then run:

Start the Segment agent with your write_key from Segment, and the endpoint.
The __endpoint__ is optional and if omitted, it defaults to `https://api.segment.io/v1/`.
```
Segment.start_link("YOUR_SEGMENT_KEY", "https://example.com/v1")
```sh
mix deps.get
```
There are then two ways to call the different methods on the API.
A basic way through `Segment.Analytics` or by passing a full Struct
with all the data for the API (allowing Context and Integrations to be set)

## Usage in Phoenix

This is how I add to a Phoenix project (may not be your preferred way)
## Usage

1. Add the following to deps section of your mix.exs: `{:segment, github: "FindHotel/analytics-elixir"}`
and then `mix deps.get`
For general usage, first define the `:key` configuration:

2. Add segment to applications list in the Phoenix project mix.exs
ie.
```
def application do
[mod: {FormAndThread, []},
applications: [:phoenix, :phoenix_html, :cowboy, :logger,
:phoenix_ecto, :postgrex, :segment]]
end
```elixir
config :segment, key: "your_segment_key"
```

3. Add a config variable for your write_key (may want to make this environment dependent)
ie.
```
config :segment,
key: "your_segment_key",
endpoint: "https://api.segment.io/v1/"
```
The __endpoint__ is optional (as specified in the Usage section above).
> For detailed information about configuration, see `t:Segment.options/0`.
4. Start the segment agent as a child of the application in the application file under
the lib directory. In the children list add:
```
{Segment, [Application.get_env(:segment, :key), Application.get_env(:segment, :endpoint)]}
```
Then call `Segment.Analytics` functions to send analytics.

There are then two ways to call the functions:

- By using a collection of parameters
- By using the related struct as a parameter

### Track
```

```elixir
Segment.Analytics.track(user_id, event, %{property1: "", property2: ""})
```

or the full way using a struct with all the possible options for the track call
```

```elixir
%Segment.Analytics.Track{ userId: "sdsds",
event: "eventname",
properties: %{property1: "", property2: ""}
Expand All @@ -66,90 +50,86 @@ or the full way using a struct with all the possible options for the track call
```

### Identify
```

```elixir
Segment.Analytics.identify(user_id, %{trait1: "", trait2: ""})
```

or the full way using a struct with all the possible options for the identify call
```

```elixir
%Segment.Analytics.Identify{ userId: "sdsds",
traits: %{trait1: "", trait2: ""}
}
|> Segment.Analytics.identify
```

### Screen
```

```elixir
Segment.Analytics.screen(user_id, name)
```

or the full way using a struct with all the possible options for the screen call
```

```elixir
%Segment.Analytics.Screen{ userId: "sdsds",
name: "dssd"
}
|> Segment.Analytics.screen
```

### Alias
```

```elixir
Segment.Analytics.alias(user_id, previous_id)
```

or the full way using a struct with all the possible options for the alias call
```

```elixir
%Segment.Analytics.Alias{ userId: "sdsds",
previousId: "dssd"
}
|> Segment.Analytics.alias
```

### Group
```

```elixir
Segment.Analytics.group(user_id, group_id)
```

or the full way using a struct with all the possible options for the group call
```

```elixir
%Segment.Analytics.Group{ userId: "sdsds",
groupId: "dssd"
}
|> Segment.Analytics.group
```

### Page
```

```elixir
Segment.Analytics.page(user_id, name)
```

or the full way using a struct with all the possible options for the page call
```

```elixir
%Segment.Analytics.Page{ userId: "sdsds",
name: "dssd"
}
|> Segment.Analytics.page
```

### Config as options
## Testing

You can also pass the __endpoint__ and __key__ as options to the
`Segment.Analytics.call/2` along with the struct.
```
%Segment.Analytics.Track{ userId: "sdsds",
event: "eventname",
properties: %{property1: "", property2: ""}
}
|> Segment.Analytics.call([key: "YOUR_SEGMENT_KEY", endpoint: "https://example.com/v1"])
```
Clone the repository and run:

With this approach the options take precedence over configurations stored in the Segment agent.

### Filtering null JSON attributes from request body

You can avoid sending `null` JSON attributes to the configured Segment API endpoint by passing
`drop_nil_fields: true` to the `Segment.Analytics.call/2` function.

## Running tests

There are not many tests at the moment. But you can run a live test on your segment
account by running.
```
SEGMENT_KEY=yourkey mix test
```sh
mix test
```

## Release
Expand Down
25 changes: 2 additions & 23 deletions config/config.exs
Original file line number Diff line number Diff line change
@@ -1,24 +1,3 @@
# This file is responsible for configuring your application
# and its dependencies with the aid of the Mix.Config module.
use Mix.Config
import Config

# This configuration is loaded before any dependency and is restricted
# to this project. If another project depends on this project, this
# file won't be loaded nor affect the parent project. For this reason,
# if you want to provide default values for your application for third-
# party users, it should be done in your mix.exs file.

# Sample configuration:
#
# config :logger, :console,
# level: :info,
# format: "$date $time [$level] $metadata$message\n",
# metadata: [:user_id]

# It is also possible to import configuration files, relative to this
# directory. For example, you can emulate configuration per environment
# by uncommenting the line below and defining dev.exs, test.exs and such.
# Configuration from the imported file will override the ones defined
# here (which is why it is important to import them last).
#
# import_config "#{Mix.env}.exs"
config :segment, http_adapter: Tesla.Mock, key: "my-amazing-key"
Loading

0 comments on commit 98925d2

Please sign in to comment.