stueccles / analytics-elixir Goto Github PK
View Code? Open in Web Editor NEWSegment.com library for Elixir
License: MIT License
Segment.com library for Elixir
License: MIT License
I saw that a hex package was published awhile ago that does not bring in changes from this repository.
Do you have any intention of releasing on hex so that dependency management for projects that rely on this becomes a bit easier?
Thanks!
hackney is pinned to an older version, either widen the accepted range or update the dependency please :)
In our production environment, sentry logged a couple of errors which seem to be internal to the Segment library.
They are function clause errors and they happen when calling log_result
. It's being called with the following parameters:
Segment.Analytics.log_result(
{:error, %HTTPoison.Error{id: nil, reason: :timeout}},
"identify",
%{} # this is a trait map, which I omitted
)
Apparently, log_result
has no matcher for a HTTPoison.Error
struct. Should it be added, or should we expect the library to throw an error here?
hey Stu, what's the average number of events/sec you had in mind when writing this library? We're looking at batching options for more throughput, to avoid hitting Segment's API rate limit (500/s), and to mitigate issues with our http connection pool.
Due to the async nature of calls to the Segment API, events that are fired close together can arrive simultaneously or out of order.
For example, this is an issue for an identify
event followed immediately by a track
event - frequently, the track
event ends up without any of the related user data provided by identify
in instruments such as Amplitude.
Since events return a Task
, this could be handled at the call site by awaiting the first event, but this solution feels a little weird since the await
also belongs in a separate process of its own so as not to block.
Any suggestions for a workaround or an API to support synchronous events in the package?
I'm happy to put some effort into it.
user_id
is one of the required arguments for the group/4
. But Segment's own group docs only mention two fields; groupId
and traits
. This is because usually, you would use this to identify the group itself and not associate a user with a group.
This method should be updated to remove the user_id
argument. If someone needs to pass it, they can use group/1
.
Thanks for merging in some of those PRs today! Is there any chance we could push an update to hex for the version bump?
I have multiple environments and I would like to be able to disable segment from the config for some of the envs.
Something like:
config :segment, enable: false
First and foremost, thanks so much for this library!
I was just toying around with my application and segment when I realized that this library uses compile time configuration. Although I changed my segment configuration from send_to_http: true
to send_to_http: false
the behavior remained the same. I had to recompile the application with all dependencies to apply the configuration change. This behavior is listed as a anti-pattern in the official Elixir docs for libraries: https://hexdocs.pm/elixir/library-guidelines.html#avoid-compile-time-application-configuration
If you are interested I can write a PR to change the compile time configuration to runtime based configuration (as proposed in the Elixir docs).
Regards,
Dominique
It fails to start with the app. These are my logs:
(segment) lib/segment/batcher.ex:33: Segment.Analytics.Batcher.start_link/1
Tesla.client([{Tesla.Middleware.BaseUrl, "https://api.segment.io/v1/"}, Tesla.Middleware.JSON, {Tesla.Middleware.BasicAuth, %{password: "", username: "<REDACTED>"}}], {Tesla.Adapter.Hackney, [recv_timeout: 30000]})
** (UndefinedFunctionError) function Tesla.client/2 is undefined (module Tesla is not available)
** (EXIT) an exception was raised:
05:30:19.685 [info] Application family_five exited: FamilyFive.Application.start(:normal, []) returned an error: shutdown: failed to start child: Segment
Kernel pid terminated (application_controller) ({application_start_failure,family_five,{{shutdown,{failed_to_start_child,'Elixir.Segment',{'EXIT',{undef,[{'Elixir.Tesla',client,[[{'Elixir.Tesla.Middle
{"Kernel pid terminated",application_controller,"{application_start_failure,family_five,{{shutdown,{failed_to_start_child,'Elixir.Segment',{'EXIT',{undef,[{'Elixir.Tesla',client,[[{'Elixir.Tesla.Middleware.BaseUrl',<<\"https://api.segment.io/v1/\">>},'Elixir.Tesla.Middleware.JSON',{'Elixir.Tesla.Middleware.BasicAuth',#{password => <<>>,username => <<\"VuwApBWk0NccFDgpcFhCvnf1sDOOxZbc\">>}}],{'Elixir.Tesla.Adapter.Hackney',[{recv_timeout,30000}]}],[]},{'Elixir.Segment.Analytics.Batcher',start_link,1,[{file,\"lib/segment/batcher.ex\"},{line,33}]},{supervisor,do_start_child_i,3,[{file,\"supervisor.erl\"},{line,379}]},{supervisor,do_start_child,2,[{file,\"supervisor.erl\"},{line,365}]},{supervisor,'-start_children/2-fun-0-',3,[{file,\"supervisor.erl\"},{line,349}]},{supervisor,children_map,4,[{file,\"supervisor.erl\"},{line,1157}]},{supervisor,init_children,2,[{file,\"supervisor.erl\"},{line,315}]},{gen_server,init_it,2,[{file,\"gen_server.erl\"},{line,374}]}]}}}},{'Elixir.FamilyFive.Application',start,[normal,[]]}}}"}
Crash dump is being written to: erl_crash.dump...done
Not a great deal of time to research this, so I rolled it back to the old version which works fine. It works when starting with mix, so I guess it has something to do with running elixir as a release.
Using the python client as a reference, there are some fields that aren't supported. I need support for timestamp
specifically, but it would be helpful to support all the fields that the standard clients to.
in addition to existing user_id
, event
, properties
and context
, we'd need to support timestamp
, anonymous_id
, and integrations
.
Looking at the official SDKs, it looks like they take a ton of positional arguments, which I find to be awkward and error prone, since some may not be used in many cases. Proposal for this is to add a Segment.Event
data structure, with supporting functions to add fields into the event using a pipeline. The code is the caller's app may look as follows:
defmodule MyApp.UserAnalytics do
import Segment.Event
def track(user_id, :my_app_event, data) do
Segment.Event
|> add_type("My App Event")
|> add_context(%{locale: "en-US"})
|> add_timestamp(data.inserted_at)
|> Segment.Analytics.track()
end
end
With this, we'd add 1-arity version of the functions in Segment.Analytics
, which would easily map into the existing internal structs there.
I can do this, just want to throw it up for some feedback first.
Hey Stuart, thought I'd check and see how you use the package in dev and test mode. Analytics is pretty central for what I do, so testing will be critical. As a result, I was considering creating multiple logging strategies, but wanted to see if you'd already come up with a simpler solution.
My first thought was to create multiple strategies. In production, that strategy would be what you already have. The HTTP api. In Dev, it would probably just log to the console, and in Test, I was thinking about writing to an in memory data store (an Agent Array) or something.
Any thoughts / suggestions?
Thanks!
Hello! Thanks for this lib, very much needed
Is there a way to assert in a test that a call was made to Segment?
I tried using send_to_http: false
but the debug
log level is not recorded in the test environment. Changing it in config/test.exs
doesn't make sense because ecto also uses debug level for queries which makes it hard to assert for the Segment debug log.
Thanks!
lib/segment/batcher.ex in Segment.Analytics.Batcher.handle_info/2 at line 87
{:ssl_closed, {:sslsocket, {:gen_tcp, #Port<0.474374>, :tls_connection, :undefined}, [#PID<0.12199.528>, #PID<0.12634.528>]}}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.