itly-sdk 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +1 -0
- data/Gemfile +12 -0
- data/Steepfile +9 -0
- data/bin/console +15 -0
- data/bin/rspec +18 -0
- data/bin/setup +8 -0
- data/itly-sdk.gemspec +29 -0
- data/lib/itly-sdk.rb +15 -0
- data/lib/itly/event.rb +58 -0
- data/lib/itly/exceptions.rb +10 -0
- data/lib/itly/itly.rb +404 -0
- data/lib/itly/loggers.rb +55 -0
- data/lib/itly/options.rb +114 -0
- data/lib/itly/options/environment.rb +24 -0
- data/lib/itly/options/validation.rb +17 -0
- data/lib/itly/plugin.rb +116 -0
- data/lib/itly/plugin_call_options.rb +18 -0
- data/lib/itly/plugin_options.rb +22 -0
- data/lib/itly/plugins.rb +25 -0
- data/lib/itly/validation_response.rb +41 -0
- data/lib/itly/version.rb +6 -0
- data/sig/aliases.rbs +3 -0
- data/sig/event.rbs +16 -0
- data/sig/exceptions.rbs +11 -0
- data/sig/itly.rbs +32 -0
- data/sig/lib/monitor_mixin.rbs +3 -0
- data/sig/loggers.rbs +8 -0
- data/sig/options.rbs +18 -0
- data/sig/options/environment.rbs +8 -0
- data/sig/options/validation.rbs +10 -0
- data/sig/plugin.rbs +21 -0
- data/sig/plugin_call_options.rbs +4 -0
- data/sig/plugin_options.rbs +10 -0
- data/sig/plugins.rbs +4 -0
- data/sig/validation_response.rbs +13 -0
- metadata +85 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f956ac42d9761509feed18e020c4c5afee5cfa5928f099e1895b982e59dd5d10
|
4
|
+
data.tar.gz: e980e7b80fab1c12ce52ec928afbd264221a1d0ba9d1ba9570c69c849e9a42a9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 85ab4bfde5fc16accc2629d83417ca697dfbdd6511ad26b95bfdde8cdff39346f76034897ae028916d452ed1a37afe8a37e4a2a406cf19187dbfbfd9352cd20e
|
7
|
+
data.tar.gz: 5b90b6d14135f194aa63c1b3d0cd09119a11d1b84cae7b3f93d84455220a97c7236f51606250c7aadd2309aef085df334c6e1cfbd72e8d7dd9ac476b148a1777
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--require spec_helper
|
data/Gemfile
ADDED
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-sdk'
|
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::*, AcceptancePlugin, AcceptancePluginCallOptions, FakeCallOptions'
|
7
|
+
ENV['RBS_TEST_LOGLEVEL'] = 'warn'
|
8
|
+
ENV['RBS_TEST_DOUBLE_SUITE'] = 'rspec'
|
9
|
+
ENV['RBS_TEST_OPT'] = '-I./sig -I./spec/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
data/itly-sdk.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'lib/itly/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'itly-sdk'
|
7
|
+
spec.version = Itly::VERSION
|
8
|
+
spec.authors = ['Iteratively', 'Benjamin Bouchet', 'Justin Fiedler', 'Andrey Sokolov']
|
9
|
+
spec.email = ['support@iterative.ly']
|
10
|
+
|
11
|
+
spec.summary = '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/sdk'
|
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
|
+
end
|
data/lib/itly-sdk.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'itly/version'
|
4
|
+
require_relative 'itly/options/environment'
|
5
|
+
require_relative 'itly/options/validation'
|
6
|
+
require_relative 'itly/exceptions'
|
7
|
+
require_relative 'itly/validation_response'
|
8
|
+
require_relative 'itly/plugin_call_options'
|
9
|
+
require_relative 'itly/plugin_options'
|
10
|
+
require_relative 'itly/plugins'
|
11
|
+
require_relative 'itly/plugin'
|
12
|
+
require_relative 'itly/options'
|
13
|
+
require_relative 'itly/event'
|
14
|
+
require_relative 'itly/itly'
|
15
|
+
require_relative 'itly/loggers'
|
data/lib/itly/event.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Itly
|
4
|
+
##
|
5
|
+
# Event object used to communicate data between Itly core SDK and its plugins
|
6
|
+
#
|
7
|
+
# Properties:
|
8
|
+
# +name+: The event's name.
|
9
|
+
# +properties+: The event's properties.
|
10
|
+
# +id+: The event's unique ID in Iteratively.
|
11
|
+
# +version+: The event's version, e.g. 2.0.1.
|
12
|
+
# +plugins+: Granular Event Destinations: to control to which plugin to forward this event to
|
13
|
+
#
|
14
|
+
class Event
|
15
|
+
attr_reader :name, :properties, :id, :version, :plugins
|
16
|
+
|
17
|
+
##
|
18
|
+
# Create a new Event object
|
19
|
+
#
|
20
|
+
# @param [String] name: The event's name.
|
21
|
+
# @param [Hash] properties: The event's properties.
|
22
|
+
# @param [String] id: The event's unique ID in Iteratively.
|
23
|
+
# @param [String] version: The event's version, e.g. 2.0.1.
|
24
|
+
# @param [Hash] plugins: Granular Event Destinations: to control to which plugin to forward this event to
|
25
|
+
#
|
26
|
+
def initialize(name:, properties: {}, id: nil, version: nil, plugins: {})
|
27
|
+
@name = name
|
28
|
+
@properties = properties
|
29
|
+
@id = id
|
30
|
+
@version = version
|
31
|
+
@plugins = plugins.transform_keys(&:to_s)
|
32
|
+
end
|
33
|
+
|
34
|
+
##
|
35
|
+
# Describe the object
|
36
|
+
#
|
37
|
+
# @return [String] the object description
|
38
|
+
#
|
39
|
+
def to_s
|
40
|
+
str = "#<#{self.class.name}: name: #{name}, "
|
41
|
+
str += "id: #{id}, " unless id.nil?
|
42
|
+
str += "version: #{version}, " unless version.nil?
|
43
|
+
str + "properties: #{properties}>"
|
44
|
+
end
|
45
|
+
|
46
|
+
##
|
47
|
+
# Compare the object to another
|
48
|
+
#
|
49
|
+
# @param [Object] other: the object to compare to
|
50
|
+
#
|
51
|
+
# @return [True/False] are the objects similar
|
52
|
+
#
|
53
|
+
def ==(other)
|
54
|
+
other.class == self.class && [name, properties, id, version] ==
|
55
|
+
[other.name, other.properties, other.id, other.version]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/lib/itly/itly.rb
ADDED
@@ -0,0 +1,404 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
##
|
4
|
+
# Itly main class
|
5
|
+
#
|
6
|
+
class Itly
|
7
|
+
include Itly::Plugins
|
8
|
+
|
9
|
+
##
|
10
|
+
# Create a new Itly object.
|
11
|
+
#
|
12
|
+
# The +is_initialized+ instance variable is a True/False flag indicating
|
13
|
+
# if the +load+ method was called on the object.
|
14
|
+
#
|
15
|
+
def initialize
|
16
|
+
@is_initialized = false
|
17
|
+
end
|
18
|
+
|
19
|
+
##
|
20
|
+
# Load options ans the plugins. It must be called only once on an object.
|
21
|
+
#
|
22
|
+
# Accept an optional block to define the options. The variable yielded in
|
23
|
+
# the block is of type `Itly::Options`.
|
24
|
+
#
|
25
|
+
# Calls the +load+ method of each plugin passing the +options+ object as an argument.
|
26
|
+
#
|
27
|
+
# @param [Hash, nil] context: to assign to the "context" Event object. Default to nil
|
28
|
+
#
|
29
|
+
def load(context: nil)
|
30
|
+
# Ensure #load was not already called on this object
|
31
|
+
raise InitializationError, 'Itly is already initialized.' if @is_initialized
|
32
|
+
|
33
|
+
# Create a new Options object and yield it is a block is provided
|
34
|
+
@options = Itly::Options.new
|
35
|
+
yield @options if block_given?
|
36
|
+
|
37
|
+
# Create the context event
|
38
|
+
@context = context.nil? ? nil : Itly::Event.new(name: 'context', properties: context)
|
39
|
+
|
40
|
+
# Log
|
41
|
+
logger&.info 'load()'
|
42
|
+
logger&.info 'Itly is disabled!' unless enabled?
|
43
|
+
logger&.warn 'No plugin enabled!' if options.plugins.empty?
|
44
|
+
|
45
|
+
# pass options to plugins
|
46
|
+
run_on_plugins { |plugin| plugin.load options: options.for_plugin } if enabled?
|
47
|
+
|
48
|
+
# Mark that the #load method was called on this object
|
49
|
+
@is_initialized = true
|
50
|
+
end
|
51
|
+
|
52
|
+
##
|
53
|
+
# Identify a user in your application and associate all future events with
|
54
|
+
# their identity, or to set their traits.
|
55
|
+
#
|
56
|
+
# Validates the +properties+ with all registered plugins first.
|
57
|
+
# Raises a Itly::ValidationError if one of the validations failed and
|
58
|
+
# if your set the +options.validation+ value to +ERROR_ON_INVALID+.
|
59
|
+
#
|
60
|
+
# Call +identify+ on all plugins and call +post_identify+ on all plugins.
|
61
|
+
#
|
62
|
+
# Example:
|
63
|
+
#
|
64
|
+
# itly.identify user_id: 'MyUser123', role: 'admin'
|
65
|
+
#
|
66
|
+
# @param [String] user_id: the id of the user in your application
|
67
|
+
# @param [Hash] properties: the user's traits to pass to your application
|
68
|
+
# @param [Hash] options: plugin specific option. The keys must correspond
|
69
|
+
# to a plugin id, and the values will be passed only to the plugin identified by the key.
|
70
|
+
#
|
71
|
+
def identify(user_id:, properties: {}, options: {})
|
72
|
+
# Run only if the object is enabled and was initialized
|
73
|
+
return unless was_initialized? && enabled?
|
74
|
+
|
75
|
+
# Log
|
76
|
+
log = Itly::Loggers.vars_to_log user_id: user_id, properties: properties, options: options
|
77
|
+
logger&.info "identify(#{log})"
|
78
|
+
|
79
|
+
# Validate and run on all plugins
|
80
|
+
event = Event.new name: 'identify', properties: properties
|
81
|
+
|
82
|
+
action = ->(plugin, combined_event) {
|
83
|
+
plugin.identify(
|
84
|
+
user_id: user_id, properties: combined_event.properties, options: options[plugin.id]
|
85
|
+
)
|
86
|
+
}
|
87
|
+
|
88
|
+
post_action = ->(plugin, combined_event, validation_results) {
|
89
|
+
plugin.post_identify(
|
90
|
+
user_id: user_id, properties: combined_event.properties, validation_results: validation_results
|
91
|
+
)
|
92
|
+
}
|
93
|
+
|
94
|
+
validate_and_send_to_plugins event: event, action: action, post_action: post_action
|
95
|
+
end
|
96
|
+
|
97
|
+
##
|
98
|
+
# Associate a user with their group (for example, their department or company),
|
99
|
+
# or to set the group's traits.
|
100
|
+
#
|
101
|
+
# Validates the +properties+ with all registered plugins first.
|
102
|
+
# Raises a Itly::ValidationError if one of the validations failed and
|
103
|
+
# if your set the +options.validation+ value to +ERROR_ON_INVALID+.
|
104
|
+
#
|
105
|
+
# Call +group+ on all plugins and call +post_group+ on all plugins.
|
106
|
+
#
|
107
|
+
# Example:
|
108
|
+
#
|
109
|
+
# itly.group user_id: 'MyUser123', group_id: 'MyGroup456', name: 'Iteratively, Inc.'
|
110
|
+
#
|
111
|
+
# @param [String] user_id: the id of the user in your application
|
112
|
+
# @param [String] group_id: the id of the group in your application
|
113
|
+
# @param [Hash] properties: The list of properties to pass to your application
|
114
|
+
# @param [Hash] options: plugin specific option. The keys must correspond
|
115
|
+
# to a plugin id, and the values will be passed only to the plugin identified by the key.
|
116
|
+
#
|
117
|
+
def group(user_id:, group_id:, properties: {}, options: {})
|
118
|
+
# Run only if the object is enabled and was initialized
|
119
|
+
return unless was_initialized? && enabled?
|
120
|
+
|
121
|
+
# Log
|
122
|
+
log = Itly::Loggers.vars_to_log user_id: user_id, group_id: group_id, properties: properties, options: options
|
123
|
+
logger&.info "group(#{log})"
|
124
|
+
|
125
|
+
# Validate and run on all plugins
|
126
|
+
event = Event.new name: 'group', properties: properties
|
127
|
+
|
128
|
+
action = ->(plugin, combined_event) {
|
129
|
+
plugin.group(
|
130
|
+
user_id: user_id, group_id: group_id, properties: combined_event.properties,
|
131
|
+
options: options[plugin.id]
|
132
|
+
)
|
133
|
+
}
|
134
|
+
|
135
|
+
post_action = ->(plugin, combined_event, validation_results) {
|
136
|
+
plugin.post_group(
|
137
|
+
user_id: user_id, group_id: group_id, properties: combined_event.properties,
|
138
|
+
validation_results: validation_results
|
139
|
+
)
|
140
|
+
}
|
141
|
+
|
142
|
+
validate_and_send_to_plugins event: event, action: action, post_action: post_action
|
143
|
+
end
|
144
|
+
|
145
|
+
##
|
146
|
+
# The Page method lets you record page views, along with optional extra information about
|
147
|
+
# the page viewed by the user.
|
148
|
+
#
|
149
|
+
# Validates the +properties+ with all registered plugins first.
|
150
|
+
# Raises a Itly::ValidationError if one of the validations failed and
|
151
|
+
# if your set the +options.validation+ value to +ERROR_ON_INVALID+.
|
152
|
+
#
|
153
|
+
# Call +page+ on all plugins and call +post_page+ on all plugins.
|
154
|
+
#
|
155
|
+
# Example:
|
156
|
+
#
|
157
|
+
# itly.page user_id: 'MyUser123', category: 'Products', name: 'MyPage456', name: 'Iteratively, Inc.'
|
158
|
+
#
|
159
|
+
# @param [String] user_id: the id of the user in your application
|
160
|
+
# @param [String] category: the category of the page
|
161
|
+
# @param [String] name: the name of the page.
|
162
|
+
# @param [Hash] properties: The list of properties to pass to your application
|
163
|
+
# @param [Hash] options: plugin specific option. The keys must correspond
|
164
|
+
# to a plugin id, and the values will be passed only to the plugin identified by the key.
|
165
|
+
#
|
166
|
+
def page(user_id:, category: nil, name: nil, properties: {}, options: {})
|
167
|
+
# Run only if the object is enabled and was initialized
|
168
|
+
return unless was_initialized? && enabled?
|
169
|
+
|
170
|
+
# Log
|
171
|
+
log = Itly::Loggers.vars_to_log(
|
172
|
+
user_id: user_id, category: category, name: name, properties: properties, options: options
|
173
|
+
)
|
174
|
+
logger&.info "page(#{log})"
|
175
|
+
|
176
|
+
# Validate and run on all plugins
|
177
|
+
event = Event.new name: 'page', properties: properties
|
178
|
+
|
179
|
+
action = ->(plugin, combined_event) {
|
180
|
+
plugin.page(
|
181
|
+
user_id: user_id, category: category, name: name, properties: combined_event.properties,
|
182
|
+
options: options[plugin.id]
|
183
|
+
)
|
184
|
+
}
|
185
|
+
|
186
|
+
post_action = ->(plugin, combined_event, validation_results) {
|
187
|
+
plugin.post_page(
|
188
|
+
user_id: user_id, category: category, name: name, properties: combined_event.properties,
|
189
|
+
validation_results: validation_results
|
190
|
+
)
|
191
|
+
}
|
192
|
+
|
193
|
+
validate_and_send_to_plugins event: event, action: action, post_action: post_action
|
194
|
+
end
|
195
|
+
|
196
|
+
##
|
197
|
+
# Track an event, call the event's corresponding function on plugins.
|
198
|
+
#
|
199
|
+
# Validates the +properties+ of the +Event+ object passed as parameter
|
200
|
+
# with all registered plugins first.
|
201
|
+
# Raises a Itly::ValidationError if one of the validations failed and
|
202
|
+
# if your set the +options.validation+ value to +ERROR_ON_INVALID+.
|
203
|
+
#
|
204
|
+
# The properties of the +context+ instance attribute passed when called #load
|
205
|
+
# are merged with the +event+ parameter before validation and calling the event
|
206
|
+
# on your application.
|
207
|
+
#
|
208
|
+
# Call +track+ on all plugins and call +post_track+ on all plugins.
|
209
|
+
#
|
210
|
+
# Example:
|
211
|
+
#
|
212
|
+
# event = Itly::Event.new name: 'watched_video', properties: {'video_id' => 'MyVider123', watch_time: '123456'}
|
213
|
+
# itly.track user_id: 'MyUser123', event: event
|
214
|
+
#
|
215
|
+
# @param [String] user_id: the id of the user in your application
|
216
|
+
# @param [Event] event: the Event object to pass to your application
|
217
|
+
# @param [Hash] options: plugin specific option. The keys must correspond
|
218
|
+
# to a plugin id, and the values will be passed only to the plugin identified by the key.
|
219
|
+
#
|
220
|
+
def track(user_id:, event:, options: {})
|
221
|
+
# Run only if the object is enabled and was initialized
|
222
|
+
return unless was_initialized? && enabled?
|
223
|
+
|
224
|
+
# Log
|
225
|
+
log = Itly::Loggers.vars_to_log(
|
226
|
+
user_id: user_id, event: event&.name, properties: event&.properties, options: options
|
227
|
+
)
|
228
|
+
logger&.info "track(#{log})"
|
229
|
+
|
230
|
+
# Validate and run on all plugins
|
231
|
+
action = ->(plugin, combined_event) {
|
232
|
+
plugin.track user_id: user_id, event: combined_event, options: options[plugin.id]
|
233
|
+
}
|
234
|
+
|
235
|
+
post_action = ->(plugin, combined_event, validation_results) {
|
236
|
+
plugin.post_track user_id: user_id, event: combined_event, validation_results: validation_results
|
237
|
+
}
|
238
|
+
|
239
|
+
validate_and_send_to_plugins event: event, context: @context, action: action, post_action: post_action
|
240
|
+
end
|
241
|
+
|
242
|
+
##
|
243
|
+
# Associate one user ID with another (typically a known user ID with an anonymous one).
|
244
|
+
#
|
245
|
+
# Call +alias+ on all plugins and call +post_alias+ on all plugins.
|
246
|
+
#
|
247
|
+
# @param [String] user_id: The ID that the user will be identified by going forward. This is
|
248
|
+
# typically the user's database ID (as opposed to an anonymous ID), or their updated ID
|
249
|
+
# (for example, if the ID is an email address which the user just updated).
|
250
|
+
# @param [String] previous_id: The ID the user has been identified by so far.
|
251
|
+
# @param [Hash] options: plugin specific option. The keys must correspond
|
252
|
+
# to a plugin id, and the values will be passed only to the plugin identified by the key.
|
253
|
+
#
|
254
|
+
def alias(user_id:, previous_id:, options: {})
|
255
|
+
# Run only if the object is enabled and was initialized
|
256
|
+
return unless was_initialized? && enabled?
|
257
|
+
|
258
|
+
# Log
|
259
|
+
log = Itly::Loggers.vars_to_log user_id: user_id, previous_id: previous_id, options: options
|
260
|
+
logger&.info "alias(#{log})"
|
261
|
+
|
262
|
+
# Run on all plugins
|
263
|
+
run_on_plugins do |plugin|
|
264
|
+
plugin.alias user_id: user_id, previous_id: previous_id, options: options[plugin.id]
|
265
|
+
end
|
266
|
+
run_on_plugins do |plugin|
|
267
|
+
plugin.post_alias user_id: user_id, previous_id: previous_id
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
##
|
272
|
+
# Send +flush+ to your plugins.
|
273
|
+
#
|
274
|
+
# Call +flush+ on all plugins.
|
275
|
+
#
|
276
|
+
def flush
|
277
|
+
# Run only if the object is enabled and was initialized
|
278
|
+
return unless was_initialized? && enabled?
|
279
|
+
|
280
|
+
# Log
|
281
|
+
logger&.info 'flush()'
|
282
|
+
|
283
|
+
# Run on all plugins
|
284
|
+
run_on_plugins(&:flush)
|
285
|
+
end
|
286
|
+
|
287
|
+
##
|
288
|
+
# Send +shutdown+ to your plugins.
|
289
|
+
#
|
290
|
+
# Call +shutdown+ on all plugins.
|
291
|
+
#
|
292
|
+
def shutdown
|
293
|
+
# Run only if the object is enabled and was initialized
|
294
|
+
return unless was_initialized? && enabled?
|
295
|
+
|
296
|
+
# Log
|
297
|
+
logger&.info 'shutdown()'
|
298
|
+
|
299
|
+
# Run on all plugins
|
300
|
+
run_on_plugins(&:shutdown)
|
301
|
+
end
|
302
|
+
|
303
|
+
##
|
304
|
+
# Reset the SDK's (and all plugins') state. This method is usually called when a user logs out.
|
305
|
+
#
|
306
|
+
# Call +reset+ on all plugins.
|
307
|
+
#
|
308
|
+
def reset
|
309
|
+
# Run only if the object is enabled and was initialized
|
310
|
+
return unless was_initialized? && enabled?
|
311
|
+
|
312
|
+
# Log
|
313
|
+
logger&.info 'reset()'
|
314
|
+
|
315
|
+
# Run on all plugins
|
316
|
+
run_on_plugins(&:reset)
|
317
|
+
end
|
318
|
+
|
319
|
+
##
|
320
|
+
# Validate an Event
|
321
|
+
#
|
322
|
+
# Call +event+ on all plugins and collect their return values.
|
323
|
+
#
|
324
|
+
# @param [Event] event: the event to validate
|
325
|
+
#
|
326
|
+
# @return [Array] array of Itly::ValidationResponse objects that were generated by the plugins
|
327
|
+
#
|
328
|
+
def validate(event:)
|
329
|
+
return unless was_initialized? && validation_enabled?
|
330
|
+
|
331
|
+
# Log
|
332
|
+
log = Itly::Loggers.vars_to_log event: event
|
333
|
+
logger&.info "validate(#{log})"
|
334
|
+
|
335
|
+
# Run on all plugins
|
336
|
+
run_on_plugins { |plugin| plugin.validate event: event }
|
337
|
+
end
|
338
|
+
|
339
|
+
def is_loaded?
|
340
|
+
!!@is_initialized
|
341
|
+
end
|
342
|
+
|
343
|
+
private
|
344
|
+
|
345
|
+
def was_initialized?
|
346
|
+
@is_initialized ? true : raise(InitializationError, 'Itly is not initialized. Call #load { |options| ... }')
|
347
|
+
end
|
348
|
+
|
349
|
+
def validate_and_send_to_plugins(action:, post_action:, event:, context: nil)
|
350
|
+
# Perform validation on the context and the event
|
351
|
+
context_validations, event_validations, is_valid = validate_context_and_event context, event
|
352
|
+
validations = context_validations + event_validations
|
353
|
+
|
354
|
+
# Call the action on all plugins
|
355
|
+
event.properties.merge! context.properties if context
|
356
|
+
|
357
|
+
if is_valid || @options.validation == Itly::Options::Validation::TRACK_INVALID
|
358
|
+
run_on_plugins do |plugin|
|
359
|
+
action.call(plugin, event) unless event.plugins[plugin.id].is_a?(FalseClass)
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
# Log all errors
|
364
|
+
log_validation_errors validations, event
|
365
|
+
|
366
|
+
# Call the post_action on all plugins
|
367
|
+
run_on_plugins do |plugin|
|
368
|
+
post_action.call(plugin, event, validations) unless event.plugins[plugin.id].is_a?(FalseClass)
|
369
|
+
end
|
370
|
+
|
371
|
+
# Throw an exception if requested
|
372
|
+
raise_validation_errors is_valid, validations, event
|
373
|
+
end
|
374
|
+
|
375
|
+
def validate_context_and_event(context, event)
|
376
|
+
# Validate the context
|
377
|
+
context_validations = (validate event: context if context) || []
|
378
|
+
|
379
|
+
# Validate the event
|
380
|
+
event_validations = validate(event: event) || []
|
381
|
+
|
382
|
+
# Check if all validation succeeded
|
383
|
+
is_valid = (context_validations + event_validations).all?(&:valid)
|
384
|
+
|
385
|
+
[context_validations, event_validations, is_valid]
|
386
|
+
end
|
387
|
+
|
388
|
+
def log_validation_errors(validations, event)
|
389
|
+
validations.reject(&:valid).each do |response|
|
390
|
+
@options.logger&.error %(Validation error for "#{event.name}" )\
|
391
|
+
"in #{response.plugin_id}. Message: #{response.message}"
|
392
|
+
end
|
393
|
+
end
|
394
|
+
|
395
|
+
def raise_validation_errors(is_valid, validations, event)
|
396
|
+
return unless !is_valid && @options.validation == Itly::Options::Validation::ERROR_ON_INVALID
|
397
|
+
|
398
|
+
messages = validations.reject(&:valid).collect(&:message)
|
399
|
+
messages = messages.select { |m| !m.nil? && m.length.positive? }
|
400
|
+
messages << "Unknown error validating #{event.name}" if messages.empty?
|
401
|
+
|
402
|
+
raise ValidationError, messages.join('. ')
|
403
|
+
end
|
404
|
+
end
|