itly-plugin-iteratively 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rspec +1 -0
- data/Gemfile +17 -0
- data/Steepfile +9 -0
- data/bin/console +15 -0
- data/bin/rspec +18 -0
- data/bin/setup +8 -0
- data/itly-plugin-iteratively.gemspec +32 -0
- data/lib/itly/plugin-iteratively.rb +13 -0
- data/lib/itly/plugin/iteratively/client.rb +163 -0
- data/lib/itly/plugin/iteratively/iteratively.rb +134 -0
- data/lib/itly/plugin/iteratively/options.rb +79 -0
- data/lib/itly/plugin/iteratively/track_model.rb +52 -0
- data/lib/itly/plugin/iteratively/track_type.rb +16 -0
- data/lib/itly/plugin/iteratively/version.rb +9 -0
- data/sig/client.rbs +31 -0
- data/sig/iteratively.rbs +27 -0
- data/sig/options.rbs +25 -0
- data/sig/track_model.rbs +23 -0
- data/sig/track_type.rbs +11 -0
- metadata +97 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e2c1016650bf9c0d05a4e662f4a15b6eb14a125416fdb362e69c0fc433cd531a
|
4
|
+
data.tar.gz: 40c0b7f79658aed2cd2be23565c9e440389bb4f772fce4bfa8c473897a055f4b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 33d0b5132356ad3a88d896d347e67b3af337aefd3c2f21c16f67843436c013279a5bde132720a01193ba10a69a886c22cbf53b2c959bfa16c1c6e0481e3366f3
|
7
|
+
data.tar.gz: 9b16bbc696d83b861669303b96067d50864292218328bc2e66057e1078d5da7c9d7fa2e40778ca92d86cacca02bafb92ad5efa4dd7940a212ba180415b93b33f
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--require spec_helper
|
data/Gemfile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source 'https://rubygems.org'
|
4
|
+
|
5
|
+
# Specify your gem's dependencies in itly-plugin-iteratively.gemspec
|
6
|
+
gemspec
|
7
|
+
|
8
|
+
gem 'rake', '~> 13.0'
|
9
|
+
|
10
|
+
if ENV['LOCAL_ITLY_GEM']
|
11
|
+
# TODO: before publication to RubyGems, switch to version 1
|
12
|
+
gem 'itly-sdk', '~> 0.1', path: '../sdk'
|
13
|
+
end
|
14
|
+
|
15
|
+
gem 'rbs', '~> 1.0'
|
16
|
+
gem 'rspec'
|
17
|
+
gem 'steep', '~> 0.41'
|
data/Steepfile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'itly/plugin-iteratively'
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
+
# require "pry"
|
12
|
+
# Pry.start
|
13
|
+
|
14
|
+
require 'irb'
|
15
|
+
IRB.start(__FILE__)
|
data/bin/rspec
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# Configure and load RBS
|
5
|
+
unless ENV['DISABLE_TYPE_CHECKING']
|
6
|
+
ENV['RBS_TEST_TARGET'] = 'Itly::*'
|
7
|
+
ENV['RBS_TEST_LOGLEVEL'] = 'warn'
|
8
|
+
ENV['RBS_TEST_DOUBLE_SUITE'] = 'rspec'
|
9
|
+
ENV['RBS_TEST_OPT'] = '-I./sig -I../sdk/sig'
|
10
|
+
|
11
|
+
require 'rbs/test/setup'
|
12
|
+
end
|
13
|
+
|
14
|
+
# Start RSpec
|
15
|
+
require 'rspec/core'
|
16
|
+
|
17
|
+
ENV['RSPEC_RUN_FROM_SCRIPT'] = 'true'
|
18
|
+
RSpec::Core::Runner.invoke
|
data/bin/setup
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'lib/itly/plugin/iteratively/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'itly-plugin-iteratively'
|
7
|
+
spec.version = Itly::Plugin::Iteratively::VERSION
|
8
|
+
spec.authors = ['Iteratively', 'Benjamin Bouchet', 'Justin Fiedler', 'Andrey Sokolov']
|
9
|
+
spec.email = ['support@iterative.ly']
|
10
|
+
|
11
|
+
spec.summary = 'Iteratively plugin for Iteratively SDK for Ruby'
|
12
|
+
spec.description = 'Track and validate analytics with a unified, extensible interface ' \
|
13
|
+
'that works with all your 3rd party analytics providers.'
|
14
|
+
spec.homepage = 'https://github.com/iterativelyhq/itly-sdk-ruby'
|
15
|
+
spec.license = 'MIT'
|
16
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 2.6.0')
|
17
|
+
|
18
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org/'
|
19
|
+
|
20
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
21
|
+
spec.metadata['source_code_uri'] = 'https://github.com/iterativelyhq/itly-sdk-ruby/plugin-iteratively'
|
22
|
+
|
23
|
+
# Specify which files should be added to the gem when it is released.
|
24
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
25
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
26
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
|
27
|
+
end
|
28
|
+
spec.require_paths = ['lib']
|
29
|
+
|
30
|
+
spec.add_dependency 'concurrent-ruby', '~> 1.1'
|
31
|
+
spec.add_dependency 'faraday', '~> 1.3'
|
32
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
if ENV['LOCAL_ITLY_GEM']
|
4
|
+
lib = File.expand_path('../../../sdk/lib', File.dirname(__FILE__))
|
5
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
6
|
+
end
|
7
|
+
|
8
|
+
require_relative 'plugin/iteratively/iteratively'
|
9
|
+
require_relative 'plugin/iteratively/options'
|
10
|
+
require_relative 'plugin/iteratively/track_type'
|
11
|
+
require_relative 'plugin/iteratively/track_model'
|
12
|
+
require_relative 'plugin/iteratively/client'
|
13
|
+
require_relative 'plugin/iteratively/version'
|
@@ -0,0 +1,163 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'concurrent'
|
4
|
+
require 'faraday'
|
5
|
+
require 'itly-sdk'
|
6
|
+
|
7
|
+
class Itly
|
8
|
+
class Plugin
|
9
|
+
class Iteratively
|
10
|
+
##
|
11
|
+
# HTTP client for the plugin requests
|
12
|
+
#
|
13
|
+
class Client
|
14
|
+
attr_reader :api_key, :url, :logger, :flush_queue_size, :batch_size, :flush_interval_ms, :max_retries,
|
15
|
+
:retry_delay_min, :retry_delay_max, :omit_values, :branch, :version
|
16
|
+
|
17
|
+
def initialize(
|
18
|
+
url:, api_key:, logger:, flush_queue_size:, batch_size:, flush_interval_ms:, max_retries:,
|
19
|
+
retry_delay_min:, retry_delay_max:, omit_values:, branch:, version:
|
20
|
+
)
|
21
|
+
@buffer = ::Concurrent::Array.new
|
22
|
+
@runner = @scheduler = nil
|
23
|
+
|
24
|
+
@api_key = api_key
|
25
|
+
@url = url
|
26
|
+
@logger = logger
|
27
|
+
@flush_queue_size = flush_queue_size
|
28
|
+
@batch_size = batch_size
|
29
|
+
@flush_interval_ms = flush_interval_ms
|
30
|
+
@max_retries = max_retries
|
31
|
+
@retry_delay_min = retry_delay_min
|
32
|
+
@retry_delay_max = retry_delay_max
|
33
|
+
@omit_values = omit_values
|
34
|
+
@branch = branch
|
35
|
+
@version = version
|
36
|
+
|
37
|
+
# Start the scheduler
|
38
|
+
start_scheduler
|
39
|
+
end
|
40
|
+
|
41
|
+
def track(type:, event:, properties:, validation:)
|
42
|
+
@buffer << ::Itly::Plugin::Iteratively::TrackModel.new(
|
43
|
+
omit_values: omit_values, type: type, event: event, properties: properties, validation: validation
|
44
|
+
)
|
45
|
+
|
46
|
+
flush if buffer_full?
|
47
|
+
end
|
48
|
+
|
49
|
+
def flush
|
50
|
+
# Case: the runner is on, cannot call flush again
|
51
|
+
return unless runner_complete?
|
52
|
+
|
53
|
+
# Exit if there is nothing to do
|
54
|
+
return if @buffer.empty?
|
55
|
+
|
56
|
+
# Extract the current content of the buffer for processing
|
57
|
+
processing = @buffer.each_slice(@batch_size).to_a
|
58
|
+
@buffer.clear
|
59
|
+
|
60
|
+
# Run in the background
|
61
|
+
@runner = Concurrent::Future.new do
|
62
|
+
processing.each do |batch|
|
63
|
+
# Initialization before the loop starts
|
64
|
+
tries = 0
|
65
|
+
|
66
|
+
loop do
|
67
|
+
# Count the number of tries
|
68
|
+
tries += 1
|
69
|
+
|
70
|
+
# Case: successfully sent
|
71
|
+
break if post_models batch
|
72
|
+
|
73
|
+
# Case: could not sent and reached maximum number of allowed tries
|
74
|
+
if tries >= @max_retries
|
75
|
+
# Log
|
76
|
+
logger&.error 'Iteratively::Client: flush() reached maximum number of tries. '\
|
77
|
+
"#{batch.count} events won't be sent to the server"
|
78
|
+
|
79
|
+
# Discard the list of event in the batch queue
|
80
|
+
break
|
81
|
+
|
82
|
+
# Case: could not sent and wait before retrying
|
83
|
+
else
|
84
|
+
sleep delay_before_next_try(tries)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
@runner.execute
|
91
|
+
end
|
92
|
+
|
93
|
+
def shutdown(force: false)
|
94
|
+
@scheduler&.cancel
|
95
|
+
|
96
|
+
if force
|
97
|
+
@runner&.cancel
|
98
|
+
return
|
99
|
+
end
|
100
|
+
|
101
|
+
@max_retries = 0
|
102
|
+
flush
|
103
|
+
@runner&.wait_or_cancel @retry_delay_min
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
def buffer_full?
|
109
|
+
@buffer.length >= @flush_queue_size
|
110
|
+
end
|
111
|
+
|
112
|
+
def post_models(models)
|
113
|
+
data = {
|
114
|
+
branchName: @branch,
|
115
|
+
trackingPlanVersion: @version,
|
116
|
+
objects: models
|
117
|
+
}.to_json
|
118
|
+
headers = {
|
119
|
+
'Content-Type' => 'application/json',
|
120
|
+
'authorization' => "Bearer #{@api_key}"
|
121
|
+
}
|
122
|
+
resp = Faraday.post(@url, data, headers)
|
123
|
+
|
124
|
+
# Case: HTTP response 2xx is a Success
|
125
|
+
return true if (200...300).include? resp.status
|
126
|
+
|
127
|
+
# Case: Error
|
128
|
+
logger&.error "Iteratively::Client: post_models() unexpected response. Url: #{url} "\
|
129
|
+
"Data: #{data} Response status: #{resp.status} Response headers: #{resp.headers} "\
|
130
|
+
"Response body: #{resp.body}"
|
131
|
+
false
|
132
|
+
rescue StandardError => e
|
133
|
+
logger&.error "Iteratively::Client: post_models() exception #{e.class.name}: #{e.message}"
|
134
|
+
false
|
135
|
+
end
|
136
|
+
|
137
|
+
def runner_complete?
|
138
|
+
@runner.nil? || @runner.complete?
|
139
|
+
end
|
140
|
+
|
141
|
+
# Generates progressively increasing values to wait between client calls
|
142
|
+
# For max_retries: 25, retry_delay_min: 10.0, retry_delay_max: 3600.0, generated values are:
|
143
|
+
# 10, 18, 41, 79, 132, 201, 283, 380, 491, 615, 752, 901, 1061, 1233, 1415, 1606,
|
144
|
+
# 1805, 2012, 2226, 2446, 2671, 2900, 3131, 3365, 3600
|
145
|
+
def delay_before_next_try(nbr_tries)
|
146
|
+
percent = (nbr_tries - 1).to_f / (@max_retries - 1)
|
147
|
+
rad = percent * Math::PI / 2
|
148
|
+
delta = (Math.cos(rad) - 1).abs
|
149
|
+
|
150
|
+
retry_delay_min + delta * (@retry_delay_max - @retry_delay_min)
|
151
|
+
end
|
152
|
+
|
153
|
+
def start_scheduler
|
154
|
+
@scheduler = Concurrent::ScheduledTask.new(@flush_interval_ms / 1000.0) do
|
155
|
+
flush unless runner_complete?
|
156
|
+
start_scheduler
|
157
|
+
end
|
158
|
+
@scheduler.execute
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'itly-sdk'
|
4
|
+
|
5
|
+
class Itly
|
6
|
+
class Plugin
|
7
|
+
##
|
8
|
+
# Iteratively plugin class for Itly SDK
|
9
|
+
#
|
10
|
+
# Automatically loaded at runtime in any new +Itly+ object
|
11
|
+
#
|
12
|
+
class Iteratively < Plugin
|
13
|
+
attr_reader :logger, :disabled, :client, :url, :api_key
|
14
|
+
|
15
|
+
##
|
16
|
+
# Instantiate a new Plugin::Iteratively
|
17
|
+
#
|
18
|
+
# @param [String] api_key: specify the api key
|
19
|
+
# @param [Itly::Plugin::Iteratively::Options] options: options object. See +Itly::Plugin::Iteratively::Options+
|
20
|
+
#
|
21
|
+
def initialize(api_key:, options:)
|
22
|
+
super()
|
23
|
+
@api_key = api_key
|
24
|
+
@url = options.url
|
25
|
+
@disabled = options.disabled
|
26
|
+
|
27
|
+
@client_options = {
|
28
|
+
flush_queue_size: options.flush_queue_size,
|
29
|
+
batch_size: options.batch_size,
|
30
|
+
flush_interval_ms: options.flush_interval_ms,
|
31
|
+
max_retries: options.max_retries,
|
32
|
+
retry_delay_min: options.retry_delay_min,
|
33
|
+
retry_delay_max: options.retry_delay_max,
|
34
|
+
omit_values: options.omit_values,
|
35
|
+
branch: options.branch,
|
36
|
+
version: options.version
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
##
|
41
|
+
# Initialize IterativelyApi client
|
42
|
+
#
|
43
|
+
# The plugin is automatically disabled in Production
|
44
|
+
#
|
45
|
+
# @param [Itly::PluginOptions] options: plugin options
|
46
|
+
#
|
47
|
+
def load(options:)
|
48
|
+
super
|
49
|
+
# Get options
|
50
|
+
@logger = options.logger
|
51
|
+
|
52
|
+
# Log
|
53
|
+
logger&.info "#{id}: load()"
|
54
|
+
|
55
|
+
# Disabled
|
56
|
+
@disabled = options.environment == Itly::Options::Environment::PRODUCTION if @disabled.nil?
|
57
|
+
|
58
|
+
if @disabled
|
59
|
+
logger&.info "#{id}: plugin is disabled!"
|
60
|
+
return
|
61
|
+
end
|
62
|
+
|
63
|
+
# Client
|
64
|
+
@client_options.merge! url: @url, api_key: @api_key, logger: @logger
|
65
|
+
@client = Itly::Plugin::Iteratively::Client.new(**@client_options)
|
66
|
+
end
|
67
|
+
|
68
|
+
def post_identify(user_id:, properties:, validation_results:)
|
69
|
+
super
|
70
|
+
return unless enabled?
|
71
|
+
|
72
|
+
# Log
|
73
|
+
log = Itly::Loggers.vars_to_log user_id: user_id, properties: properties, validation_results: validation_results
|
74
|
+
logger&.info "#{id}: post_identify(#{log})"
|
75
|
+
|
76
|
+
client_track Itly::Plugin::Iteratively::TrackType::IDENTIFY, properties, validation_results
|
77
|
+
end
|
78
|
+
|
79
|
+
def post_group(user_id:, group_id:, properties:, validation_results:)
|
80
|
+
super
|
81
|
+
return unless enabled?
|
82
|
+
|
83
|
+
# Log
|
84
|
+
log = Itly::Loggers.vars_to_log(
|
85
|
+
user_id: user_id, group_id: group_id, properties: properties, validation_results: validation_results
|
86
|
+
)
|
87
|
+
logger&.info "#{id}: post_group(#{log})"
|
88
|
+
|
89
|
+
client_track Itly::Plugin::Iteratively::TrackType::GROUP, properties, validation_results
|
90
|
+
end
|
91
|
+
|
92
|
+
def post_track(user_id:, event:, validation_results:)
|
93
|
+
super
|
94
|
+
return unless enabled?
|
95
|
+
|
96
|
+
# Log
|
97
|
+
log = Itly::Loggers.vars_to_log user_id: user_id, event: event, validation_results: validation_results
|
98
|
+
logger&.info "#{id}: post_track(#{log})"
|
99
|
+
|
100
|
+
client_track Itly::Plugin::Iteratively::TrackType::TRACK, event, validation_results
|
101
|
+
end
|
102
|
+
|
103
|
+
def flush
|
104
|
+
@client.flush
|
105
|
+
end
|
106
|
+
|
107
|
+
def shutdown(force: false)
|
108
|
+
@client.shutdown force: force
|
109
|
+
end
|
110
|
+
|
111
|
+
##
|
112
|
+
# Get the plugin ID
|
113
|
+
#
|
114
|
+
# @return [String] plugin id
|
115
|
+
#
|
116
|
+
def id
|
117
|
+
'iteratively'
|
118
|
+
end
|
119
|
+
|
120
|
+
private
|
121
|
+
|
122
|
+
def enabled?
|
123
|
+
!@disabled
|
124
|
+
end
|
125
|
+
|
126
|
+
def client_track(type, event_or_properties, validations)
|
127
|
+
event = event_or_properties.is_a?(Itly::Event) ? event_or_properties : nil
|
128
|
+
properties = event_or_properties.is_a?(Hash) ? event_or_properties : nil
|
129
|
+
validation = (validations || []).reject(&:valid).first
|
130
|
+
@client.track type: type, event: event, properties: properties, validation: validation
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'itly-sdk'
|
4
|
+
|
5
|
+
class Itly
|
6
|
+
class Plugin
|
7
|
+
class Iteratively
|
8
|
+
##
|
9
|
+
# Options for the Iteratively plugin class
|
10
|
+
#
|
11
|
+
class Options
|
12
|
+
DEFAULT_URL = 'https://data.us-east-2.iterative.ly/t'
|
13
|
+
|
14
|
+
attr_reader :url, :disabled, :flush_queue_size, :batch_size, :flush_interval_ms, :max_retries,
|
15
|
+
:retry_delay_min, :retry_delay_max, :omit_values, :branch, :version
|
16
|
+
|
17
|
+
##
|
18
|
+
# Instantiate a new Options
|
19
|
+
#
|
20
|
+
# @param [String] url (optional): specify the url to push events to.
|
21
|
+
# Default to https://data.us-east-2.iterative.ly/t
|
22
|
+
# @param [TrueClass/FalseClass] disabled: set to true to disable the Iteratively plugin.
|
23
|
+
# Default to +true+ in production environment, to +false+ otherwise
|
24
|
+
# @param [Integer] flush_queue_size (optional): Number of event in the buffer before
|
25
|
+
# a flush is triggered. Default: 10
|
26
|
+
# @param [Integer] batch_size (optional): Maximum number of events to send to the server at once. Default: 100
|
27
|
+
# @param [Integer] flush_interval_ms (optional): Delay in milliseconds between each automatic
|
28
|
+
# flush. Default: 1_000
|
29
|
+
# @param [Integer] max_retries (optional): Number of retries for pushing
|
30
|
+
# events to the server. Default: 25
|
31
|
+
# @param [Float] retry_delay_min: Minimum delay between retries in seconds. Default: 10.0
|
32
|
+
# @param [Float] retry_delay_max: Maximum delay between retries in seconds. Default: 3600.0 (1 hour)
|
33
|
+
# @param [TrueClass/FalseClass] omit_values: set to true to send empty data. Default to false
|
34
|
+
# @param [String] branch: Tracking plan branch name (e.g. feature/demo)
|
35
|
+
# @param [String] version: Tracking plan version number (e.g. 1.0.0)
|
36
|
+
#
|
37
|
+
def initialize(
|
38
|
+
url: DEFAULT_URL, disabled: nil, flush_queue_size: 10, batch_size: 100, flush_interval_ms: 1_000,
|
39
|
+
max_retries: 25, retry_delay_min: 10.0, retry_delay_max: 3600.0, omit_values: false, branch: nil, version: nil
|
40
|
+
)
|
41
|
+
super()
|
42
|
+
@url = url
|
43
|
+
@disabled = disabled
|
44
|
+
@flush_queue_size = flush_queue_size
|
45
|
+
@batch_size = batch_size
|
46
|
+
@flush_interval_ms = flush_interval_ms
|
47
|
+
@max_retries = max_retries
|
48
|
+
@retry_delay_min = retry_delay_min
|
49
|
+
@retry_delay_max = retry_delay_max
|
50
|
+
@omit_values = omit_values
|
51
|
+
@branch = branch
|
52
|
+
@version = version
|
53
|
+
end
|
54
|
+
|
55
|
+
##
|
56
|
+
# Returns a copy of this Options with any provided arguments used as overrides
|
57
|
+
#
|
58
|
+
def with_overrides(
|
59
|
+
url: nil, disabled: nil, flush_queue_size: nil, batch_size: nil, flush_interval_ms: nil,
|
60
|
+
max_retries: nil, retry_delay_min: nil, retry_delay_max: nil, omit_values: nil, branch: nil, version: nil
|
61
|
+
)
|
62
|
+
Itly::Plugin::Iteratively::Options.new(
|
63
|
+
url: url.nil? ? @url : url,
|
64
|
+
disabled: disabled.nil? ? @disabled : disabled,
|
65
|
+
flush_queue_size: flush_queue_size.nil? ? @flush_queue_size : flush_queue_size,
|
66
|
+
batch_size: batch_size.nil? ? @batch_size : batch_size,
|
67
|
+
flush_interval_ms: flush_interval_ms.nil? ? @flush_interval_ms : flush_interval_ms,
|
68
|
+
max_retries: max_retries.nil? ? @max_retries : max_retries,
|
69
|
+
retry_delay_min: retry_delay_min.nil? ? @retry_delay_min : retry_delay_min,
|
70
|
+
retry_delay_max: retry_delay_max.nil? ? @retry_delay_max : retry_delay_max,
|
71
|
+
omit_values: omit_values.nil? ? @omit_values : omit_values,
|
72
|
+
branch: branch.nil? ? @branch : branch,
|
73
|
+
version: version.nil? ? @version : version
|
74
|
+
)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'time'
|
4
|
+
require 'json'
|
5
|
+
require 'itly-sdk'
|
6
|
+
|
7
|
+
class Itly
|
8
|
+
class Plugin
|
9
|
+
class Iteratively
|
10
|
+
##
|
11
|
+
# Data model for HTTP client buffering
|
12
|
+
#
|
13
|
+
class TrackModel
|
14
|
+
attr_reader :type, :date_sent, :event_id, :event_schema_version, :event_name,
|
15
|
+
:properties, :valid, :validation
|
16
|
+
|
17
|
+
def initialize(type:, event:, properties:, validation: nil, omit_values: false)
|
18
|
+
@omit_values = omit_values
|
19
|
+
@type = type
|
20
|
+
@date_sent = Time.now.utc.iso8601
|
21
|
+
@event_id = event&.id
|
22
|
+
@event_schema_version = event&.version
|
23
|
+
@event_name = event&.name
|
24
|
+
@properties = event&.properties || properties
|
25
|
+
@valid = validation ? validation.valid : true
|
26
|
+
@validation = { details: validation ? validation.message : '' }
|
27
|
+
|
28
|
+
@properties = @properties.transform_values { |_| '' } if @omit_values
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_json(*_)
|
32
|
+
{
|
33
|
+
type: @type,
|
34
|
+
dateSent: @date_sent,
|
35
|
+
eventId: @event_id,
|
36
|
+
eventSchemaVersion: @event_schema_version,
|
37
|
+
eventName: @event_name,
|
38
|
+
properties: @properties,
|
39
|
+
valid: @valid,
|
40
|
+
validation: @validation
|
41
|
+
}.to_json
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_s
|
45
|
+
"#<#{self.class.name}: type: #{@type} date_sent: #{@date_sent} event_id: #{@event_id} "\
|
46
|
+
"event_schema_version: #{@event_schema_version} event_name: #{@event_name} "\
|
47
|
+
"properties: #{@properties} valid: #{@valid} validation: #{@validation}>"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Itly
|
4
|
+
class Plugin
|
5
|
+
class Iteratively
|
6
|
+
##
|
7
|
+
# This module contains values for the +type+ of tracked events by the Client
|
8
|
+
#
|
9
|
+
module TrackType
|
10
|
+
GROUP = 'group'
|
11
|
+
IDENTIFY = 'identify'
|
12
|
+
TRACK = 'track'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/sig/client.rbs
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
class Itly
|
2
|
+
class Plugin
|
3
|
+
class Iteratively
|
4
|
+
class Client
|
5
|
+
attr_reader api_key: String
|
6
|
+
attr_reader url: String
|
7
|
+
attr_reader logger: Logger?
|
8
|
+
attr_reader flush_queue_size: Integer
|
9
|
+
attr_reader batch_size: Integer
|
10
|
+
attr_reader flush_interval_ms: Integer
|
11
|
+
attr_reader max_retries: Integer
|
12
|
+
attr_reader retry_delay_min: Float
|
13
|
+
attr_reader retry_delay_max: Float
|
14
|
+
attr_reader branch: String?
|
15
|
+
attr_reader version: String?
|
16
|
+
|
17
|
+
def track: (type: String `type`, event: Itly::Event? event, properties: propertiesHash? properties, validation: Itly::ValidationResponse? validation) -> void
|
18
|
+
def flush: () -> void
|
19
|
+
def shutdown: (?force: bool force) -> void
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def initialize: (url: String url, api_key: String api_key, logger: Logger? logger, flush_queue_size: Integer flush_queue_size, batch_size: Integer batch_size, flush_interval_ms: Integer flush_interval_ms, max_retries: Integer max_retries, retry_delay_min: Float retry_delay_min, retry_delay_max: Float retry_delay_max, omit_values: bool omit_values, branch: String? branch, version: String? version) -> void
|
24
|
+
def buffer_full?: () -> bool
|
25
|
+
def post_models: (Array[Itly::Plugin::Iteratively::TrackModel] model) -> bool
|
26
|
+
def runner_complete?: () -> bool
|
27
|
+
def delay_before_next_try: (Integer nbr_tries) -> Float
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/sig/iteratively.rbs
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
class Itly
|
2
|
+
class Plugin
|
3
|
+
class Iteratively < Plugin
|
4
|
+
VERSION: String
|
5
|
+
|
6
|
+
attr_reader logger: Logger?
|
7
|
+
attr_reader disabled: bool?
|
8
|
+
attr_reader client: Itly::Plugin::Iteratively::Client?
|
9
|
+
attr_reader url: String
|
10
|
+
attr_reader api_key: String
|
11
|
+
|
12
|
+
def load: (options: Itly::PluginOptions options) -> void
|
13
|
+
def post_identify: (user_id: String user_id, properties: propertiesHash properties, validation_results: Array[Itly::ValidationResponse] validation_results) -> void
|
14
|
+
def post_group: (user_id: String user_id, group_id: String group_id, properties: propertiesHash properties, validation_results: Array[Itly::ValidationResponse] validation_results) -> void
|
15
|
+
def post_track: (user_id: String user_id, event: Itly::Event event, validation_results: Array[Itly::ValidationResponse] validation_results) -> void
|
16
|
+
def flush: () -> void
|
17
|
+
def shutdown: (?force: bool force) -> void
|
18
|
+
def id: () -> String
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def initialize: (api_key: String api_key, options: Itly::Plugin::Iteratively::Options options) -> void
|
23
|
+
def enabled?: () -> bool
|
24
|
+
def client_track: (String `type`, Itly::Event|propertiesHash event_or_properties, Array[Itly::ValidationResponse]? validations) -> void
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/sig/options.rbs
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
class Itly
|
2
|
+
class Plugin
|
3
|
+
class Iteratively
|
4
|
+
class Options
|
5
|
+
DEFAULT_URL: String
|
6
|
+
|
7
|
+
attr_reader url: String
|
8
|
+
attr_reader disabled: bool?
|
9
|
+
attr_reader flush_queue_size: Integer
|
10
|
+
attr_reader batch_size: Integer
|
11
|
+
attr_reader flush_interval_ms: Integer
|
12
|
+
attr_reader max_retries: Integer
|
13
|
+
attr_reader retry_delay_min: Float
|
14
|
+
attr_reader retry_delay_max: Float
|
15
|
+
attr_reader omit_values: bool
|
16
|
+
attr_reader branch: String?
|
17
|
+
attr_reader version: String?
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def initialize: (?url: String url, ?disabled: bool? disabled, ?flush_queue_size: Integer flush_queue_size, ?batch_size: Integer batch_size, ?flush_interval_ms: Integer flush_interval_ms, ?max_retries: Integer max_retries, ?retry_delay_min: Float retry_delay_min, ?retry_delay_max: Float retry_delay_max, ?omit_values: bool omit_values, ?branch: String? branch, ?version: String? version) -> void
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/sig/track_model.rbs
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
class Itly
|
2
|
+
class Plugin
|
3
|
+
class Iteratively
|
4
|
+
class TrackModel
|
5
|
+
attr_reader type: String
|
6
|
+
attr_reader date_sent: String
|
7
|
+
attr_reader event_id: String
|
8
|
+
attr_reader event_schema_version: String
|
9
|
+
attr_reader event_name: String
|
10
|
+
attr_reader properties: propertiesHash
|
11
|
+
attr_reader valid: bool?
|
12
|
+
attr_reader validation: Itly::ValidationResponse?
|
13
|
+
|
14
|
+
def to_json: (*untyped _) -> String
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def initialize: (type: String `type`, event: Itly::Event? event, properties: propertiesHash? properties, ?validation: Itly::ValidationResponse? validation, omit_values: bool omit_values) -> void
|
19
|
+
def to_s: () -> String
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/sig/track_type.rbs
ADDED
metadata
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: itly-plugin-iteratively
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Iteratively
|
8
|
+
- Benjamin Bouchet
|
9
|
+
- Justin Fiedler
|
10
|
+
- Andrey Sokolov
|
11
|
+
autorequire:
|
12
|
+
bindir: bin
|
13
|
+
cert_chain: []
|
14
|
+
date: 2021-06-15 00:00:00.000000000 Z
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: concurrent-ruby
|
18
|
+
requirement: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - "~>"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '1.1'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.1'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: faraday
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
requirements:
|
34
|
+
- - "~>"
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '1.3'
|
37
|
+
type: :runtime
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - "~>"
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '1.3'
|
44
|
+
description: Track and validate analytics with a unified, extensible interface that
|
45
|
+
works with all your 3rd party analytics providers.
|
46
|
+
email:
|
47
|
+
- support@iterative.ly
|
48
|
+
executables: []
|
49
|
+
extensions: []
|
50
|
+
extra_rdoc_files: []
|
51
|
+
files:
|
52
|
+
- ".rspec"
|
53
|
+
- Gemfile
|
54
|
+
- Steepfile
|
55
|
+
- bin/console
|
56
|
+
- bin/rspec
|
57
|
+
- bin/setup
|
58
|
+
- itly-plugin-iteratively.gemspec
|
59
|
+
- lib/itly/plugin-iteratively.rb
|
60
|
+
- lib/itly/plugin/iteratively/client.rb
|
61
|
+
- lib/itly/plugin/iteratively/iteratively.rb
|
62
|
+
- lib/itly/plugin/iteratively/options.rb
|
63
|
+
- lib/itly/plugin/iteratively/track_model.rb
|
64
|
+
- lib/itly/plugin/iteratively/track_type.rb
|
65
|
+
- lib/itly/plugin/iteratively/version.rb
|
66
|
+
- sig/client.rbs
|
67
|
+
- sig/iteratively.rbs
|
68
|
+
- sig/options.rbs
|
69
|
+
- sig/track_model.rbs
|
70
|
+
- sig/track_type.rbs
|
71
|
+
homepage: https://github.com/iterativelyhq/itly-sdk-ruby
|
72
|
+
licenses:
|
73
|
+
- MIT
|
74
|
+
metadata:
|
75
|
+
allowed_push_host: https://rubygems.org/
|
76
|
+
homepage_uri: https://github.com/iterativelyhq/itly-sdk-ruby
|
77
|
+
source_code_uri: https://github.com/iterativelyhq/itly-sdk-ruby/plugin-iteratively
|
78
|
+
post_install_message:
|
79
|
+
rdoc_options: []
|
80
|
+
require_paths:
|
81
|
+
- lib
|
82
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: 2.6.0
|
87
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
92
|
+
requirements: []
|
93
|
+
rubygems_version: 3.0.3.1
|
94
|
+
signing_key:
|
95
|
+
specification_version: 4
|
96
|
+
summary: Iteratively plugin for Iteratively SDK for Ruby
|
97
|
+
test_files: []
|