astronomer 2.0.14
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +2 -0
- data/History.md +160 -0
- data/Makefile +8 -0
- data/README.md +91 -0
- data/Rakefile +7 -0
- data/analytics-ruby.gemspec +23 -0
- data/astronomer-2.0.13.gem +0 -0
- data/lib/segment.rb +1 -0
- data/lib/segment/analytics.rb +31 -0
- data/lib/segment/analytics/client.rb +359 -0
- data/lib/segment/analytics/defaults.rb +20 -0
- data/lib/segment/analytics/logging.rb +35 -0
- data/lib/segment/analytics/request.rb +82 -0
- data/lib/segment/analytics/response.rb +16 -0
- data/lib/segment/analytics/utils.rb +88 -0
- data/lib/segment/analytics/version.rb +5 -0
- data/lib/segment/analytics/worker.rb +60 -0
- data/spec/segment/analytics/client_spec.rb +302 -0
- data/spec/segment/analytics/request_spec.rb +191 -0
- data/spec/segment/analytics/response_spec.rb +30 -0
- data/spec/segment/analytics/worker_spec.rb +96 -0
- data/spec/segment/analytics_spec.rb +106 -0
- data/spec/spec_helper.rb +81 -0
- metadata +143 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d463274a2d9c4d0a44f928244d36bbe6f6ace22f
|
4
|
+
data.tar.gz: 10244ef783c53eb830d8a207869a5f262b0dbbfb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fa6df4f342b81e25dd8393965224cb33b14e419e118ffc072c095b3e0f66befcfb70a45cbe1eb9141b0bd47b91cdad325478a090eeaed0254390360f92fd5ff2
|
7
|
+
data.tar.gz: 67c26e707743e9081f28e13da25d3fb7fbeadcbfb63f4ad9abcf2ebf1b0a35a5cd693b160b528300ee97c8dcefe3bb16d024ea864ed9f6d3cd5c3dc5a15f29f6
|
data/Gemfile
ADDED
data/History.md
ADDED
@@ -0,0 +1,160 @@
|
|
1
|
+
2.0.12 / 2015-01-10
|
2
|
+
==================
|
3
|
+
|
4
|
+
* Fix batch being cleared and causing duplicates
|
5
|
+
|
6
|
+
2.0.11 / 2014-09-22
|
7
|
+
==================
|
8
|
+
|
9
|
+
* fix: don't clear batch if request failed
|
10
|
+
|
11
|
+
2.0.10 / 2014-09-22
|
12
|
+
==================
|
13
|
+
|
14
|
+
* Move timeout retry above output
|
15
|
+
|
16
|
+
2.0.9 / 2014-09-22
|
17
|
+
==================
|
18
|
+
|
19
|
+
* Fix rescuing timeouts
|
20
|
+
|
21
|
+
2.0.8 / 2014-09-11
|
22
|
+
==================
|
23
|
+
* fix: add 3 ms to timestamp
|
24
|
+
|
25
|
+
2.0.7 / 2014-08-27
|
26
|
+
==================
|
27
|
+
* fix: include optional options hash in calls
|
28
|
+
|
29
|
+
2.0.6 / 2014-08-12
|
30
|
+
==================
|
31
|
+
* fix: category param on #page and #screen
|
32
|
+
|
33
|
+
2.0.5 / 2014-05-26
|
34
|
+
==================
|
35
|
+
* fix: datetime conversions
|
36
|
+
|
37
|
+
2.0.4 / 2014-06-11
|
38
|
+
==================
|
39
|
+
* fix: isofying trait dates in #group
|
40
|
+
|
41
|
+
2.0.3 / 2014-06-04
|
42
|
+
==================
|
43
|
+
* fix: undefined method `is_requesting?' for nil:NilClass when calling flush (#51)
|
44
|
+
|
45
|
+
2.0.2 / 2014-05-30
|
46
|
+
==================
|
47
|
+
* fix: formatting ios dates
|
48
|
+
* fix: respond_to? implementation
|
49
|
+
* add: able to stub requests by setting STUB env var
|
50
|
+
|
51
|
+
2.0.1 / 2014-05-15
|
52
|
+
==================
|
53
|
+
* add: namespace under Segment::Analytics
|
54
|
+
* add: can create multiple instances with creator method (rather than
|
55
|
+
having a singleton)
|
56
|
+
* add: logging with Logger instance or Rails.logger if available
|
57
|
+
* add: able to stub requests so they just log and don't hit the server
|
58
|
+
* fix: worker continues running across forked processes
|
59
|
+
* fix: removed usage of ActiveSupport methods since its not a dependency
|
60
|
+
* fix: sending data that matches segment's new api spec
|
61
|
+
|
62
|
+
(there is no v2.0.0)
|
63
|
+
|
64
|
+
1.1.0 / 2014-04-17
|
65
|
+
==================
|
66
|
+
* adding .initialized? by [@lumberj](https://github.com/lumberj)
|
67
|
+
|
68
|
+
1.0.0 / 2014-03-12
|
69
|
+
==================
|
70
|
+
* removing faraday dependency
|
71
|
+
|
72
|
+
0.6.0 / 2014-02-19
|
73
|
+
==================
|
74
|
+
* adding .group(), .page(), and .screen() calls
|
75
|
+
* relaxing faraday dependency, fixes #31
|
76
|
+
|
77
|
+
0.5.4 / 2013-12-31
|
78
|
+
==================
|
79
|
+
* Add `requestId` fields to all requests for tracing.
|
80
|
+
|
81
|
+
0.5.3 / 2013-12-31
|
82
|
+
==================
|
83
|
+
* Allow the consumer thread to shut down so it won't remain live in hot deploy scenarios. This fixes the jruby memory leak by [@nirvdrum](https://github.com/nirvdrum)
|
84
|
+
|
85
|
+
0.5.2 / 2013-12-02
|
86
|
+
==================
|
87
|
+
* adding `sleep` backoff between connection retries
|
88
|
+
|
89
|
+
0.5.1 / 2013-11-22
|
90
|
+
==================
|
91
|
+
* adding retries for connection hangups
|
92
|
+
|
93
|
+
0.5.0 / 2013-10-03
|
94
|
+
==================
|
95
|
+
* Removing global Analytics constant in favor of adding it to our config. NOTE: If you are upgrading from a previous version and want to continue using the `Analytics` namespace, you'll have to add `Analytics = AnalyticsRuby` to your config. Otherwise you WILL NOT be sending analytics data. See the [setup docs for more info](https://segment.io/libraries/ruby)
|
96
|
+
|
97
|
+
0.4.0 / 2013-08-30
|
98
|
+
==================
|
99
|
+
* Adding support and tests for 1.8.7
|
100
|
+
|
101
|
+
0.3.4 / 2013-08-26
|
102
|
+
==================
|
103
|
+
* Pass `Time` values as iso8601 timestamp strings
|
104
|
+
|
105
|
+
0.3.3 / 2013-08-02
|
106
|
+
==================
|
107
|
+
* Allow init/track/identify/alias to accept strings as keys. by [@shipstar](https://github.com/shipstar)
|
108
|
+
|
109
|
+
0.3.2 / 2013-05-28
|
110
|
+
==================
|
111
|
+
* Adding faraday timeout by [@yanchenyun](https://github.com/yangchenyun)
|
112
|
+
|
113
|
+
0.3.1 / 2013-04-29
|
114
|
+
==================
|
115
|
+
* Adding check for properties to be a Hash
|
116
|
+
|
117
|
+
0.3.0 / 2013-04-05
|
118
|
+
==================
|
119
|
+
* Adding alias call
|
120
|
+
|
121
|
+
0.2.0 / 2013-03-21
|
122
|
+
==================
|
123
|
+
* Adding flush method
|
124
|
+
|
125
|
+
0.1.4 / 2013-03-19
|
126
|
+
==================
|
127
|
+
* Adding ClassMethods for more extensibility by [arronmabrey](https://github.com/arronmabrey)
|
128
|
+
|
129
|
+
0.1.3 / 2013-03-19
|
130
|
+
==================
|
131
|
+
* Fixing user_id.to_s semantics, reported by [arronmabrey](https://github.com/arronmabrey)
|
132
|
+
* Reduced faraday requirements by [arronmabrey](https://github.com/arronmabrey)
|
133
|
+
|
134
|
+
0.1.2 / 2013-03-11
|
135
|
+
==================
|
136
|
+
* Fixing thrown exception on non-initialized tracks thanks to [sbellity](https://github.com/sbellity)
|
137
|
+
|
138
|
+
0.1.1 / 2013-02-11
|
139
|
+
==================
|
140
|
+
* Updating dependencies
|
141
|
+
* Adding actual support for MultiJson 1.0
|
142
|
+
|
143
|
+
0.1.0 / 2013-01-22
|
144
|
+
==================
|
145
|
+
* Updated docs to point at segment.io
|
146
|
+
|
147
|
+
0.0.5 / 2013-01-21
|
148
|
+
==================
|
149
|
+
* Renaming of all the files for proper bundling usage
|
150
|
+
|
151
|
+
0.0.4 / 2013-01-17
|
152
|
+
==================
|
153
|
+
* Updated readme and install instruction courtesy of [@zeke](https://github.com/zeke)
|
154
|
+
* Removed typhoeus and reverted to default adapter
|
155
|
+
* Removing session_id in favor of a single user_id
|
156
|
+
|
157
|
+
0.0.3 / 2013-01-16
|
158
|
+
==================
|
159
|
+
* Rakefile and renaming courtesy of [@kiennt](https://github.com/kiennt)
|
160
|
+
* Updated tests with mocks
|
data/Makefile
ADDED
data/README.md
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
analytics-ruby
|
2
|
+
==============
|
3
|
+
|
4
|
+
[![Build Status](https://travis-ci.org/segmentio/analytics-ruby.png?branch=master)](https://travis-ci.org/segmentio/analytics-ruby)
|
5
|
+
|
6
|
+
analytics-ruby is a ruby client for [Segment](https://segment.com)
|
7
|
+
|
8
|
+
## Install
|
9
|
+
|
10
|
+
Into Gemfile from rubygems.org:
|
11
|
+
```
|
12
|
+
gem 'analytics-ruby', :require => "segment"
|
13
|
+
```
|
14
|
+
|
15
|
+
Into environment gems from rubygems.org:
|
16
|
+
```
|
17
|
+
gem install 'analytics-ruby'
|
18
|
+
```
|
19
|
+
|
20
|
+
## Usage
|
21
|
+
|
22
|
+
Create an instance of the Analytics object:
|
23
|
+
```
|
24
|
+
analytics = Segment::Analytics.new({
|
25
|
+
write_key: 'YOUR_WRITE_KEY'
|
26
|
+
})
|
27
|
+
```
|
28
|
+
|
29
|
+
Sample usage:
|
30
|
+
```
|
31
|
+
user = User.last
|
32
|
+
|
33
|
+
# Identify the user for the people section
|
34
|
+
analytics.identify(
|
35
|
+
{
|
36
|
+
user_id: user.id,
|
37
|
+
traits: {
|
38
|
+
email: user.email,
|
39
|
+
first_name: user.first_name,
|
40
|
+
last_name: user.last_name
|
41
|
+
}
|
42
|
+
}
|
43
|
+
)
|
44
|
+
|
45
|
+
# Track a user event
|
46
|
+
analytics.track(
|
47
|
+
{
|
48
|
+
user_id: user.id,
|
49
|
+
event: 'Created Account'
|
50
|
+
}
|
51
|
+
)
|
52
|
+
```
|
53
|
+
|
54
|
+
Refer to the section below for documenation on individual available calls.
|
55
|
+
|
56
|
+
## Documentation
|
57
|
+
|
58
|
+
Documentation is available at [segment.com/libraries/ruby](https://segment.com/libraries/ruby)
|
59
|
+
|
60
|
+
## Testing
|
61
|
+
|
62
|
+
You can use the `stub` option to Segment::Analytics.new to cause all requests to be stubbed, making it easier to test with this library.
|
63
|
+
|
64
|
+
## License
|
65
|
+
|
66
|
+
```
|
67
|
+
WWWWWW||WWWWWW
|
68
|
+
W W W||W W W
|
69
|
+
||
|
70
|
+
( OO )__________
|
71
|
+
/ | \
|
72
|
+
/o o| MIT \
|
73
|
+
\___/||_||__||_|| *
|
74
|
+
|| || || ||
|
75
|
+
_||_|| _||_||
|
76
|
+
(__|__|(__|__|
|
77
|
+
```
|
78
|
+
|
79
|
+
(The MIT License)
|
80
|
+
|
81
|
+
Copyright (c) 2013 Segment Inc. <friends@segment.com>
|
82
|
+
|
83
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
84
|
+
|
85
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
86
|
+
|
87
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
88
|
+
|
89
|
+
|
90
|
+
[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/segmentio/analytics-ruby/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
|
91
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.expand_path('../lib/segment/analytics/version', __FILE__)
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = 'astronomer'
|
5
|
+
spec.version = '2.0.14'
|
6
|
+
spec.files = Dir.glob('**/*')
|
7
|
+
spec.require_paths = ['lib']
|
8
|
+
spec.summary = 'Segment.io analytics library, adapted by Astronomer.io'
|
9
|
+
spec.description = 'The Segment.io ruby analytics library, adapted by Astronomer.io'
|
10
|
+
spec.authors = ['Segment.io', 'Astronomer.io']
|
11
|
+
spec.email = 'greg@astronomer.io'
|
12
|
+
spec.homepage = 'https://github.com/astronomerio/analytics-ruby.git'
|
13
|
+
spec.license = 'MIT'
|
14
|
+
|
15
|
+
# Ruby 1.8 requires json
|
16
|
+
spec.add_dependency 'json', ['~> 1.7'] if RUBY_VERSION < "1.9"
|
17
|
+
|
18
|
+
spec.add_development_dependency 'rake', '~> 10.3'
|
19
|
+
spec.add_development_dependency 'wrong', '~> 0.0'
|
20
|
+
spec.add_development_dependency 'rspec', '~> 2.0'
|
21
|
+
spec.add_development_dependency 'tzinfo', '1.2.1'
|
22
|
+
spec.add_development_dependency 'activesupport', '>= 3.0.0', '<4.0.0'
|
23
|
+
end
|
Binary file
|
data/lib/segment.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'segment/analytics'
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'segment/analytics/defaults'
|
2
|
+
require 'segment/analytics/utils'
|
3
|
+
require 'segment/analytics/version'
|
4
|
+
require 'segment/analytics/client'
|
5
|
+
require 'segment/analytics/worker'
|
6
|
+
require 'segment/analytics/request'
|
7
|
+
require 'segment/analytics/response'
|
8
|
+
require 'segment/analytics/logging'
|
9
|
+
|
10
|
+
module Segment
|
11
|
+
class Analytics
|
12
|
+
def initialize options = {}
|
13
|
+
Request.stub = options[:stub]
|
14
|
+
@client = Segment::Analytics::Client.new options
|
15
|
+
end
|
16
|
+
|
17
|
+
def method_missing message, *args, &block
|
18
|
+
if @client.respond_to? message
|
19
|
+
@client.send message, *args, &block
|
20
|
+
else
|
21
|
+
super
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def respond_to? method_name, include_private = false
|
26
|
+
@client.respond_to?(method_name) || super
|
27
|
+
end
|
28
|
+
|
29
|
+
include Logging
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,359 @@
|
|
1
|
+
require 'thread'
|
2
|
+
require 'time'
|
3
|
+
require 'segment/analytics/utils'
|
4
|
+
require 'segment/analytics/worker'
|
5
|
+
require 'segment/analytics/defaults'
|
6
|
+
|
7
|
+
module Segment
|
8
|
+
class Analytics
|
9
|
+
class Client
|
10
|
+
include Segment::Analytics::Utils
|
11
|
+
|
12
|
+
# public: Creates a new client
|
13
|
+
#
|
14
|
+
# attrs - Hash
|
15
|
+
# :app_id - String of your project's app_id
|
16
|
+
# :max_queue_size - Fixnum of the max calls to remain queued (optional)
|
17
|
+
# :on_error - Proc which handles error calls from the API
|
18
|
+
def initialize attrs = {}
|
19
|
+
symbolize_keys! attrs
|
20
|
+
|
21
|
+
@queue = Queue.new
|
22
|
+
@app_id = attrs[:app_id]
|
23
|
+
@max_queue_size = attrs[:max_queue_size] || Defaults::Queue::MAX_SIZE
|
24
|
+
@options = attrs
|
25
|
+
@worker_mutex = Mutex.new
|
26
|
+
@worker = Worker.new @queue, @app_id, @options
|
27
|
+
|
28
|
+
check_app_id!
|
29
|
+
|
30
|
+
at_exit { @worker_thread && @worker_thread[:should_exit] = true }
|
31
|
+
end
|
32
|
+
|
33
|
+
# public: Synchronously waits until the worker has flushed the queue.
|
34
|
+
# Use only for scripts which are not long-running, and will
|
35
|
+
# specifically exit
|
36
|
+
#
|
37
|
+
def flush
|
38
|
+
while !@queue.empty? || @worker.is_requesting?
|
39
|
+
ensure_worker_running
|
40
|
+
sleep(0.1)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# public: Tracks an event
|
45
|
+
#
|
46
|
+
# attrs - Hash
|
47
|
+
# :anonymous_id - String of the user's id when you don't know who they are yet. (optional but you must provide either an anonymous_id or user_id. See: https://segment.io/docs/tracking - api/track/#user - id)
|
48
|
+
# :context - Hash of context. (optional)
|
49
|
+
# :event - String of event name.
|
50
|
+
# :integrations - Hash specifying what integrations this event goes to. (optional)
|
51
|
+
# :options - Hash specifying options such as user traits. (optional)
|
52
|
+
# :properties - Hash of event properties. (optional)
|
53
|
+
# :timestamp - Time of when the event occurred. (optional)
|
54
|
+
# :user_id - String of the user id.
|
55
|
+
def track attrs
|
56
|
+
symbolize_keys! attrs
|
57
|
+
check_user_id! attrs
|
58
|
+
|
59
|
+
event = attrs[:event]
|
60
|
+
properties = attrs[:properties] || {}
|
61
|
+
timestamp = attrs[:timestamp] || Time.new
|
62
|
+
context = attrs[:context] || {}
|
63
|
+
|
64
|
+
check_timestamp! timestamp
|
65
|
+
|
66
|
+
if event.nil? || event.empty?
|
67
|
+
fail ArgumentError, 'Must supply event as a non-empty string'
|
68
|
+
end
|
69
|
+
|
70
|
+
fail ArgumentError, 'Properties must be a Hash' unless properties.is_a? Hash
|
71
|
+
isoify_dates! properties
|
72
|
+
|
73
|
+
add_context context
|
74
|
+
|
75
|
+
enqueue({
|
76
|
+
:event => event,
|
77
|
+
:userId => attrs[:user_id],
|
78
|
+
:anonymousId => attrs[:anonymous_id],
|
79
|
+
:context => context,
|
80
|
+
:options => attrs[:options],
|
81
|
+
:integrations => attrs[:integrations],
|
82
|
+
:properties => properties,
|
83
|
+
:timestamp => datetime_in_iso8601(timestamp),
|
84
|
+
:type => 'track'
|
85
|
+
})
|
86
|
+
end
|
87
|
+
|
88
|
+
# public: Identifies a user
|
89
|
+
#
|
90
|
+
# attrs - Hash
|
91
|
+
# :anonymous_id - String of the user's id when you don't know who they are yet. (optional but you must provide either an anonymous_id or user_id. See: https://segment.io/docs/tracking - api/track/#user - id)
|
92
|
+
# :context - Hash of context. (optional)
|
93
|
+
# :integrations - Hash specifying what integrations this event goes to. (optional)
|
94
|
+
# :options - Hash specifying options such as user traits. (optional)
|
95
|
+
# :timestamp - Time of when the event occurred. (optional)
|
96
|
+
# :traits - Hash of user traits. (optional)
|
97
|
+
# :user_id - String of the user id
|
98
|
+
def identify attrs
|
99
|
+
symbolize_keys! attrs
|
100
|
+
check_user_id! attrs
|
101
|
+
|
102
|
+
traits = attrs[:traits] || {}
|
103
|
+
timestamp = attrs[:timestamp] || Time.new
|
104
|
+
context = attrs[:context] || {}
|
105
|
+
|
106
|
+
check_timestamp! timestamp
|
107
|
+
|
108
|
+
fail ArgumentError, 'Must supply traits as a hash' unless traits.is_a? Hash
|
109
|
+
isoify_dates! traits
|
110
|
+
|
111
|
+
add_context context
|
112
|
+
|
113
|
+
enqueue({
|
114
|
+
:userId => attrs[:user_id],
|
115
|
+
:anonymousId => attrs[:anonymous_id],
|
116
|
+
:integrations => attrs[:integrations],
|
117
|
+
:context => context,
|
118
|
+
:traits => traits,
|
119
|
+
:options => attrs[:options],
|
120
|
+
:timestamp => datetime_in_iso8601(timestamp),
|
121
|
+
:type => 'identify'
|
122
|
+
})
|
123
|
+
end
|
124
|
+
|
125
|
+
# public: Aliases a user from one id to another
|
126
|
+
#
|
127
|
+
# attrs - Hash
|
128
|
+
# :context - Hash of context (optional)
|
129
|
+
# :integrations - Hash specifying what integrations this event goes to. (optional)
|
130
|
+
# :options - Hash specifying options such as user traits. (optional)
|
131
|
+
# :previous_id - String of the id to alias from
|
132
|
+
# :timestamp - Time of when the alias occured (optional)
|
133
|
+
# :user_id - String of the id to alias to
|
134
|
+
def alias(attrs)
|
135
|
+
symbolize_keys! attrs
|
136
|
+
|
137
|
+
from = attrs[:previous_id]
|
138
|
+
to = attrs[:user_id]
|
139
|
+
timestamp = attrs[:timestamp] || Time.new
|
140
|
+
context = attrs[:context] || {}
|
141
|
+
|
142
|
+
check_presence! from, 'previous_id'
|
143
|
+
check_presence! to, 'user_id'
|
144
|
+
check_timestamp! timestamp
|
145
|
+
add_context context
|
146
|
+
|
147
|
+
enqueue({
|
148
|
+
:previousId => from,
|
149
|
+
:userId => to,
|
150
|
+
:integrations => attrs[:integrations],
|
151
|
+
:context => context,
|
152
|
+
:options => attrs[:options],
|
153
|
+
:timestamp => datetime_in_iso8601(timestamp),
|
154
|
+
:type => 'alias'
|
155
|
+
})
|
156
|
+
end
|
157
|
+
|
158
|
+
# public: Associates a user identity with a group.
|
159
|
+
#
|
160
|
+
# attrs - Hash
|
161
|
+
# :context - Hash of context (optional)
|
162
|
+
# :integrations - Hash specifying what integrations this event goes to. (optional)
|
163
|
+
# :options - Hash specifying options such as user traits. (optional)
|
164
|
+
# :previous_id - String of the id to alias from
|
165
|
+
# :timestamp - Time of when the alias occured (optional)
|
166
|
+
# :user_id - String of the id to alias to
|
167
|
+
def group(attrs)
|
168
|
+
symbolize_keys! attrs
|
169
|
+
check_user_id! attrs
|
170
|
+
|
171
|
+
group_id = attrs[:group_id]
|
172
|
+
user_id = attrs[:user_id]
|
173
|
+
traits = attrs[:traits] || {}
|
174
|
+
timestamp = attrs[:timestamp] || Time.new
|
175
|
+
context = attrs[:context] || {}
|
176
|
+
|
177
|
+
fail ArgumentError, '.traits must be a hash' unless traits.is_a? Hash
|
178
|
+
isoify_dates! traits
|
179
|
+
|
180
|
+
check_presence! group_id, 'group_id'
|
181
|
+
check_timestamp! timestamp
|
182
|
+
add_context context
|
183
|
+
|
184
|
+
enqueue({
|
185
|
+
:groupId => group_id,
|
186
|
+
:userId => user_id,
|
187
|
+
:traits => traits,
|
188
|
+
:integrations => attrs[:integrations],
|
189
|
+
:options => attrs[:options],
|
190
|
+
:context => context,
|
191
|
+
:timestamp => datetime_in_iso8601(timestamp),
|
192
|
+
:type => 'group'
|
193
|
+
})
|
194
|
+
end
|
195
|
+
|
196
|
+
# public: Records a page view
|
197
|
+
#
|
198
|
+
# attrs - Hash
|
199
|
+
# :anonymous_id - String of the user's id when you don't know who they are yet. (optional but you must provide either an anonymous_id or user_id. See: https://segment.io/docs/tracking - api/track/#user - id)
|
200
|
+
# :category - String of the page category (optional)
|
201
|
+
# :context - Hash of context (optional)
|
202
|
+
# :integrations - Hash specifying what integrations this event goes to. (optional)
|
203
|
+
# :name - String name of the page
|
204
|
+
# :options - Hash specifying options such as user traits. (optional)
|
205
|
+
# :properties - Hash of page properties (optional)
|
206
|
+
# :timestamp - Time of when the pageview occured (optional)
|
207
|
+
# :user_id - String of the id to alias from
|
208
|
+
def page(attrs)
|
209
|
+
symbolize_keys! attrs
|
210
|
+
check_user_id! attrs
|
211
|
+
|
212
|
+
name = attrs[:name].to_s
|
213
|
+
properties = attrs[:properties] || {}
|
214
|
+
timestamp = attrs[:timestamp] || Time.new
|
215
|
+
context = attrs[:context] || {}
|
216
|
+
|
217
|
+
fail ArgumentError, '.properties must be a hash' unless properties.is_a? Hash
|
218
|
+
isoify_dates! properties
|
219
|
+
|
220
|
+
check_timestamp! timestamp
|
221
|
+
add_context context
|
222
|
+
|
223
|
+
enqueue({
|
224
|
+
:userId => attrs[:user_id],
|
225
|
+
:anonymousId => attrs[:anonymous_id],
|
226
|
+
:name => name,
|
227
|
+
:category => attrs[:category],
|
228
|
+
:properties => properties,
|
229
|
+
:integrations => attrs[:integrations],
|
230
|
+
:options => attrs[:options],
|
231
|
+
:context => context,
|
232
|
+
:timestamp => datetime_in_iso8601(timestamp),
|
233
|
+
:type => 'page'
|
234
|
+
})
|
235
|
+
end
|
236
|
+
# public: Records a screen view (for a mobile app)
|
237
|
+
#
|
238
|
+
# attrs - Hash
|
239
|
+
# :anonymous_id - String of the user's id when you don't know who they are yet. (optional but you must provide either an anonymous_id or user_id. See: https://segment.io/docs/tracking - api/track/#user - id)
|
240
|
+
# :category - String screen category (optional)
|
241
|
+
# :context - Hash of context (optional)
|
242
|
+
# :integrations - Hash specifying what integrations this event goes to. (optional)
|
243
|
+
# :name - String name of the screen
|
244
|
+
# :options - Hash specifying options such as user traits. (optional)
|
245
|
+
# :properties - Hash of screen properties (optional)
|
246
|
+
# :timestamp - Time of when the screen occured (optional)
|
247
|
+
# :user_id - String of the id to alias from
|
248
|
+
def screen(attrs)
|
249
|
+
symbolize_keys! attrs
|
250
|
+
check_user_id! attrs
|
251
|
+
|
252
|
+
name = attrs[:name].to_s
|
253
|
+
properties = attrs[:properties] || {}
|
254
|
+
timestamp = attrs[:timestamp] || Time.new
|
255
|
+
context = attrs[:context] || {}
|
256
|
+
|
257
|
+
fail ArgumentError, '.properties must be a hash' unless properties.is_a? Hash
|
258
|
+
isoify_dates! properties
|
259
|
+
|
260
|
+
check_timestamp! timestamp
|
261
|
+
add_context context
|
262
|
+
|
263
|
+
enqueue({
|
264
|
+
:userId => attrs[:user_id],
|
265
|
+
:anonymousId => attrs[:anonymous_id],
|
266
|
+
:name => name,
|
267
|
+
:properties => properties,
|
268
|
+
:category => attrs[:category],
|
269
|
+
:options => attrs[:options],
|
270
|
+
:integrations => attrs[:integrations],
|
271
|
+
:context => context,
|
272
|
+
:timestamp => timestamp.iso8601,
|
273
|
+
:type => 'screen'
|
274
|
+
})
|
275
|
+
end
|
276
|
+
|
277
|
+
# public: Returns the number of queued messages
|
278
|
+
#
|
279
|
+
# returns Fixnum of messages in the queue
|
280
|
+
def queued_messages
|
281
|
+
@queue.length
|
282
|
+
end
|
283
|
+
|
284
|
+
private
|
285
|
+
|
286
|
+
# private: Enqueues the action.
|
287
|
+
#
|
288
|
+
# returns Boolean of whether the item was added to the queue.
|
289
|
+
def enqueue(action)
|
290
|
+
# add our request id for tracing purposes
|
291
|
+
action[:messageId] = uid
|
292
|
+
unless queue_full = @queue.length >= @max_queue_size
|
293
|
+
ensure_worker_running
|
294
|
+
@queue << action
|
295
|
+
end
|
296
|
+
!queue_full
|
297
|
+
end
|
298
|
+
|
299
|
+
# private: Ensures that a string is non-empty
|
300
|
+
#
|
301
|
+
# obj - String|Number that must be non-blank
|
302
|
+
# name - Name of the validated value
|
303
|
+
#
|
304
|
+
def check_presence!(obj, name)
|
305
|
+
if obj.nil? || (obj.is_a?(String) && obj.empty?)
|
306
|
+
fail ArgumentError, "#{name} must be given"
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
# private: Adds contextual information to the call
|
311
|
+
#
|
312
|
+
# context - Hash of call context
|
313
|
+
def add_context(context)
|
314
|
+
context[:library] = { :name => "analytics-ruby", :version => Segment::Analytics::VERSION.to_s }
|
315
|
+
end
|
316
|
+
|
317
|
+
# private: Checks that the app_id is properly initialized
|
318
|
+
def check_app_id!
|
319
|
+
fail ArgumentError, 'App id must be initialized' if @app_id.nil?
|
320
|
+
end
|
321
|
+
|
322
|
+
# private: Checks the timstamp option to make sure it is a Time.
|
323
|
+
def check_timestamp!(timestamp)
|
324
|
+
fail ArgumentError, 'Timestamp must be a Time' unless timestamp.is_a? Time
|
325
|
+
end
|
326
|
+
|
327
|
+
def event attrs
|
328
|
+
symbolize_keys! attrs
|
329
|
+
|
330
|
+
{
|
331
|
+
:userId => user_id,
|
332
|
+
:name => name,
|
333
|
+
:properties => properties,
|
334
|
+
:context => context,
|
335
|
+
:timestamp => datetime_in_iso8601(timestamp),
|
336
|
+
:type => 'screen'
|
337
|
+
}
|
338
|
+
end
|
339
|
+
|
340
|
+
def check_user_id! attrs
|
341
|
+
fail ArgumentError, 'Must supply either user_id or anonymous_id' unless attrs[:user_id] || attrs[:anonymous_id]
|
342
|
+
end
|
343
|
+
|
344
|
+
def ensure_worker_running
|
345
|
+
return if worker_running?
|
346
|
+
@worker_mutex.synchronize do
|
347
|
+
return if worker_running?
|
348
|
+
@worker_thread = Thread.new do
|
349
|
+
@worker.run
|
350
|
+
end
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
def worker_running?
|
355
|
+
@worker_thread && @worker_thread.alive?
|
356
|
+
end
|
357
|
+
end
|
358
|
+
end
|
359
|
+
end
|