thinkingdata-ruby 1.2.1 → 2.0.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.
@@ -1,409 +1,495 @@
1
- require 'securerandom'
2
- require 'thinkingdata-ruby/errors'
3
- require 'thinkingdata-ruby/version'
4
-
5
- module TDAnalytics
6
- @is_enable_log = false
7
- @is_stringent = false
8
-
9
- def self.set_enable_log(enable)
10
- unless [true, false].include? enable
11
- enable = false
12
- end
13
- @is_enable_log = enable
14
- end
15
-
16
- def self.get_enable_log
17
- @is_enable_log
18
- end
19
-
20
- def self.set_stringent(enable)
21
- unless [true, false].include? enable
22
- enable = false
23
- end
24
- @is_stringent = enable
25
- end
26
-
27
- def self.get_stringent
28
- @is_stringent
29
- end
30
-
31
- class Tracker
32
- LIB_PROPERTIES = {
33
- '#lib' => 'ruby',
34
- '#lib_version' => TDAnalytics::VERSION,
35
- }
36
-
37
- @@dynamic_block = nil
38
-
39
- def initialize(consumer, error_handler = nil, uuid: false)
40
- @error_handler = error_handler || ErrorHandler.new
41
- @consumer = consumer
42
- @super_properties = {}
43
- @uuid = uuid
44
- end
45
-
46
- # set common properties
47
- def set_super_properties(properties, skip_local_check = false)
48
- unless TDAnalytics::get_stringent == false || skip_local_check || _check_properties(:track, properties)
49
- @error_handler.handle(IllegalParameterError.new("Invalid super properties"))
50
- return false
51
- end
52
- properties.each do |k, v|
53
- if v.is_a?(Time)
54
- @super_properties[k] = _format_time(v)
55
- else
56
- @super_properties[k] = v
57
- end
58
- end
59
- end
60
-
61
- def clear_super_properties
62
- @super_properties = {}
63
- end
64
-
65
- def set_dynamic_super_properties(&block)
66
- @@dynamic_block = block
67
- end
68
-
69
- def clear_dynamic_super_properties
70
- @@dynamic_block = nil
71
- end
72
-
73
- # report ordinary event
74
- # event_name: (require) A string of 50 letters and digits that starts with '#' or a letter
75
- # distinct_id: (optional) distinct ID
76
- # account_id: (optional) account ID. distinct_id, account_id can't both be empty.
77
- # properties: (optional) string、number、Time、boolean
78
- # time: (optional)Time
79
- # ip: (optional) ip
80
- # first_check_id: (optional) The value cannot be null for the first event
81
- # skip_local_check: (optional) check data or not
82
- def track(event_name: nil, distinct_id: nil, account_id: nil, properties: {}, time: nil, ip: nil,first_check_id:nil, skip_local_check: false)
83
- begin
84
- _check_name event_name
85
- _check_id(distinct_id, account_id)
86
- unless skip_local_check
87
- _check_properties(:track, properties)
88
- end
89
- rescue TDAnalyticsError => e
90
- @error_handler.handle(e)
91
- return false
92
- end
93
-
94
- _internal_track(:track, event_name: event_name, distinct_id: distinct_id, account_id: account_id, properties: properties, time: time, ip: ip, first_check_id: first_check_id)
95
- end
96
-
97
- # report overridable event
98
- def track_overwrite(event_name: nil,event_id: nil, distinct_id: nil, account_id: nil, properties: {}, time: nil, ip: nil, skip_local_check: false)
99
- begin
100
- _check_name event_name
101
- _check_event_id event_id
102
- _check_id(distinct_id, account_id)
103
- unless skip_local_check
104
- _check_properties(:track_overwrite, properties)
105
- end
106
- rescue TDAnalyticsError => e
107
- @error_handler.handle(e)
108
- return false
109
- end
110
-
111
- _internal_track(:track_overwrite, event_name: event_name, event_id: event_id, distinct_id: distinct_id, account_id: account_id, properties: properties, time: time, ip: ip)
112
- end
113
-
114
- # report updatable event
115
- def track_update(event_name: nil,event_id: nil, distinct_id: nil, account_id: nil, properties: {}, time: nil, ip: nil, skip_local_check: false)
116
- begin
117
- _check_name event_name
118
- _check_event_id event_id
119
- _check_id(distinct_id, account_id)
120
- unless skip_local_check
121
- _check_properties(:track_update, properties)
122
- end
123
- rescue TDAnalyticsError => e
124
- @error_handler.handle(e)
125
- return false
126
- end
127
-
128
- _internal_track(:track_update, event_name: event_name, event_id: event_id, distinct_id: distinct_id, account_id: account_id, properties: properties, time: time, ip: ip)
129
- end
130
-
131
- # set user properties. would overwrite existing names.
132
- def user_set(distinct_id: nil, account_id: nil, properties: {}, ip: nil)
133
- begin
134
- _check_id(distinct_id, account_id)
135
- _check_properties(:user_set, properties)
136
- rescue TDAnalyticsError => e
137
- @error_handler.handle(e)
138
- return false
139
- end
140
-
141
- _internal_track(:user_set, distinct_id: distinct_id, account_id: account_id, properties: properties, ip: ip)
142
- end
143
-
144
- # set user properties, If such property had been set before, this message would be neglected.
145
- def user_set_once(distinct_id: nil, account_id: nil, properties: {}, ip: nil)
146
- begin
147
- _check_id(distinct_id, account_id)
148
- _check_properties(:user_setOnce, properties)
149
- rescue TDAnalyticsError => e
150
- @error_handler.handle(e)
151
- return false
152
- end
153
-
154
- _internal_track(:user_setOnce,
155
- distinct_id: distinct_id,
156
- account_id: account_id,
157
- properties: properties,
158
- ip: ip,
159
- )
160
- end
161
-
162
- # to add user properties of array type.
163
- def user_append(distinct_id: nil, account_id: nil, properties: {})
164
- begin
165
- _check_id(distinct_id, account_id)
166
- _check_properties(:user_append, properties)
167
- rescue TDAnalyticsError => e
168
- @error_handler.handle(e)
169
- return false
170
- end
171
-
172
- _internal_track(:user_append,
173
- distinct_id: distinct_id,
174
- account_id: account_id,
175
- properties: properties,
176
- )
177
- end
178
-
179
- def user_uniq_append(distinct_id: nil, account_id: nil, properties: {})
180
- begin
181
- _check_id(distinct_id, account_id)
182
- _check_properties(:user_uniq_append, properties)
183
- rescue TDAnalyticsError => e
184
- @error_handler.handle(e)
185
- return false
186
- end
187
-
188
- _internal_track(:user_uniq_append,
189
- distinct_id: distinct_id,
190
- account_id: account_id,
191
- properties: properties,
192
- )
193
- end
194
-
195
- # clear the user properties of users.
196
- def user_unset(distinct_id: nil, account_id: nil, property: nil)
197
- properties = {}
198
- if property.is_a?(Array)
199
- property.each do |k|
200
- properties[k] = 0
201
- end
202
- else
203
- properties[property] = 0
204
- end
205
-
206
- begin
207
- _check_id(distinct_id, account_id)
208
- _check_properties(:user_unset, properties)
209
- rescue TDAnalyticsError => e
210
- @error_handler.handle(e)
211
- return false
212
- end
213
-
214
- _internal_track(:user_unset,
215
- distinct_id: distinct_id,
216
- account_id: account_id,
217
- properties: properties,
218
- )
219
- end
220
-
221
- # to accumulate operations against the property.
222
- def user_add(distinct_id: nil, account_id: nil, properties: {})
223
- begin
224
- _check_id(distinct_id, account_id)
225
- _check_properties(:user_add, properties)
226
- rescue TDAnalyticsError => e
227
- @error_handler.handle(e)
228
- return false
229
- end
230
-
231
- _internal_track(:user_add,
232
- distinct_id: distinct_id,
233
- account_id: account_id,
234
- properties: properties,
235
- )
236
- end
237
-
238
- # delete a user, This operation cannot be undone.
239
- def user_del(distinct_id: nil, account_id: nil)
240
- begin
241
- _check_id(distinct_id, account_id)
242
- rescue TDAnalyticsError => e
243
- @error_handler.handle(e)
244
- return false
245
- end
246
-
247
- _internal_track(:user_del,
248
- distinct_id: distinct_id,
249
- account_id: account_id,
250
- )
251
- end
252
-
253
- # report data immediately.
254
- def flush
255
- return true unless defined? @consumer.flush
256
- ret = true
257
- begin
258
- @consumer.flush
259
- rescue TDAnalyticsError => e
260
- @error_handler.handle(e)
261
- ret = false
262
- end
263
- ret
264
- end
265
-
266
- # Close and exit sdk
267
- def close
268
- return true unless defined? @consumer.close
269
- ret = true
270
- begin
271
- @consumer.close
272
- rescue TDAnalyticsError => e
273
- @error_handler.handle(e)
274
- ret = false
275
- end
276
- ret
277
- end
278
-
279
- private
280
-
281
- def _internal_track(type, properties: {}, event_name: nil, event_id:nil, account_id: nil, distinct_id: nil, ip: nil,first_check_id: nil, time: nil)
282
- if type == :track || type == :track_update || type == :track_overwrite
283
- dynamic_properties = @@dynamic_block.respond_to?(:call) ? @@dynamic_block.call : {}
284
- properties = LIB_PROPERTIES.merge(@super_properties).merge(dynamic_properties).merge(properties)
285
- end
286
-
287
- data = {
288
- '#type' => type,
289
- }
290
-
291
- properties.each do |k, v|
292
- if v.is_a?(Time)
293
- properties[k] = _format_time(v)
294
- end
295
- end
296
-
297
- _move_preset_properties([:'#ip', :"#time", :"#app_id", :"#uuid"], data, properties: properties)
298
-
299
- if data[:'#time'] == nil
300
- if time == nil
301
- time = Time.now
302
- end
303
- data[:'#time'] = _format_time(time)
304
- end
305
-
306
- data['properties'] = properties
307
- data['#event_name'] = event_name if (type == :track || type == :track_update || type == :track_overwrite)
308
- data['#event_id'] = event_id if (type == :track_update || type == :track_overwrite)
309
- data['#account_id'] = account_id if account_id
310
- data['#distinct_id'] = distinct_id if distinct_id
311
- data['#ip'] = ip if ip
312
- data['#first_check_id'] = first_check_id if first_check_id
313
- data[:'#uuid'] = SecureRandom.uuid if @uuid and data[:'#uuid'] == nil
314
-
315
- ret = true
316
- begin
317
- @consumer.add(data)
318
- rescue TDAnalyticsError => e
319
- @error_handler.handle(e)
320
- ret = false
321
- end
322
-
323
- ret
324
- end
325
-
326
- def _format_time(time)
327
- time.strftime("%Y-%m-%d %H:%M:%S.#{((time.to_f * 1000.0).to_i % 1000).to_s.rjust(3, "0")}")
328
- end
329
-
330
- def _check_event_id(event_id)
331
- if TDAnalytics::get_stringent == false
332
- return true
333
- end
334
-
335
- raise IllegalParameterError.new("the event_id or property cannot be nil") if event_id.nil?
336
- true
337
- end
338
-
339
- def _check_name(name)
340
- if TDAnalytics::get_stringent == false
341
- return true
342
- end
343
-
344
- raise IllegalParameterError.new("the name of event or property cannot be nil") if name.nil?
345
-
346
- unless name.instance_of?(String) || name.instance_of?(Symbol)
347
- raise IllegalParameterError.new("#{name} is invalid. It must be String or Symbol")
348
- end
349
- true
350
- end
351
-
352
- def _check_properties(type, properties)
353
- if TDAnalytics::get_stringent == false
354
- return true
355
- end
356
-
357
- unless properties.instance_of? Hash
358
- return false
359
- end
360
-
361
- properties.each do |k, v|
362
- _check_name k
363
- next if v.nil?
364
- unless v.is_a?(Integer) || v.is_a?(Float) || v.is_a?(Symbol) || v.is_a?(String) || v.is_a?(Time) || !!v == v || v.is_a?(Array)
365
- raise IllegalParameterError.new("The value of properties must be type in Integer, Float, Symbol, String, Array,and Time")
366
- end
367
-
368
- if type == :user_add
369
- raise IllegalParameterError.new("Property value for user add must be numbers") unless v.is_a?(Integer) || v.is_a?(Float)
370
- end
371
- if v.is_a?(Array)
372
- v.each_index do |i|
373
- if v[i].is_a?(Time)
374
- v[i] = _format_time(v[i])
375
- end
376
- end
377
- end
378
- end
379
- true
380
- end
381
-
382
- def _check_id(distinct_id, account_id)
383
- if TDAnalytics::get_stringent == false
384
- return true
385
- end
386
-
387
- raise IllegalParameterError.new("account id or distinct id must be provided.") if distinct_id.nil? && account_id.nil?
388
- end
389
-
390
- def _move_preset_properties(keys, data, properties: {})
391
- property_keys = properties.keys
392
- keys.each { |k|
393
- if property_keys.include? k
394
- data[k] = properties[k]
395
- properties.delete(k)
396
- end
397
- }
398
- end
399
- end
400
-
401
- class TELog
402
- def self.info(*msg)
403
- if TDAnalytics::get_enable_log
404
- print("[ThinkingEngine][#{Time.now}][info]-")
405
- puts(msg)
406
- end
407
- end
408
- end
409
- end
1
+ require 'securerandom'
2
+ require 'thinkingdata-ruby/td_errors'
3
+ require 'thinkingdata-ruby/td_version'
4
+
5
+ ##
6
+ # ThinkingData module
7
+ module ThinkingData
8
+ @is_enable_log = false
9
+ @is_stringent = false
10
+
11
+ ##
12
+ # Enable SDK log or not
13
+ # @param enable [Boolean] true or false
14
+ def self.set_enable_log(enable)
15
+ unless [true, false].include? enable
16
+ enable = false
17
+ end
18
+ @is_enable_log = enable
19
+ end
20
+
21
+ ##
22
+ # Get log status
23
+ # @return [Boolean] enable or not
24
+ def self.get_enable_log
25
+ @is_enable_log
26
+ end
27
+
28
+ ##
29
+ # Check or not parameter
30
+ # @param enable [Boolean] check or not
31
+ def self.set_stringent(enable)
32
+ unless [true, false].include? enable
33
+ enable = false
34
+ end
35
+ @is_stringent = enable
36
+ end
37
+
38
+ ##
39
+ # Get parameter check status of SDK
40
+ # @return [Boolean] check or not
41
+ def self.get_stringent
42
+ @is_stringent
43
+ end
44
+
45
+ ##
46
+ # Analytics class。 Provides the function of tracking data
47
+ class TDAnalytics
48
+ LIB_PROPERTIES = {
49
+ '#lib' => 'ruby',
50
+ '#lib_version' => ThinkingData::VERSION,
51
+ }
52
+
53
+ @dynamic_block = nil
54
+
55
+ ##
56
+ # Init function
57
+ # @param consumer [consumer] data consumer: TDLoggerConsumer | TDDebugConsumer | TDBatchConsumer
58
+ # @param error_handler [TDErrorHandler] custom error handler, process SDK error. It could be nil
59
+ # @param uuid [Boolean] Whether to automatically add uuid
60
+ def initialize(consumer, error_handler = nil, uuid: false)
61
+ @error_handler = error_handler || TDErrorHandler.new
62
+ @consumer = consumer
63
+ @super_properties = {}
64
+ @uuid_enable = uuid
65
+ TDLog.info("SDK init success.")
66
+ end
67
+
68
+ ##
69
+ # Set common properties
70
+ def set_super_properties(properties, skip_local_check = false)
71
+ unless ThinkingData::get_stringent == false || skip_local_check || _check_properties(:track, properties)
72
+ @error_handler.handle(IllegalParameterError.new("Invalid super properties"))
73
+ return false
74
+ end
75
+ properties.each do |k, v|
76
+ if v.is_a?(Time)
77
+ @super_properties[k] = _format_time(v)
78
+ else
79
+ @super_properties[k] = v
80
+ end
81
+ end
82
+ end
83
+
84
+ ##
85
+ # Clear super properties
86
+ def clear_super_properties
87
+ @super_properties = {}
88
+ end
89
+
90
+ ##
91
+ # Set dynamic super properties
92
+ def set_dynamic_super_properties(&block)
93
+ @dynamic_block = block
94
+ end
95
+
96
+ ##
97
+ # Clear dynamic super properties
98
+ def clear_dynamic_super_properties
99
+ @dynamic_block = nil
100
+ end
101
+
102
+ ##
103
+ # Report ordinary event
104
+ # event_name: (require) A string of 50 letters and digits that starts with '#' or a letter
105
+ # distinct_id: (optional) distinct ID
106
+ # account_id: (optional) account ID. distinct_id, account_id can't both be empty.
107
+ # properties: (optional) string、number、Time、boolean
108
+ # time: (optional)Time
109
+ # ip: (optional) ip
110
+ # first_check_id: (optional) The value cannot be null for the first event
111
+ # skip_local_check: (optional) check data or not
112
+ def track(event_name: nil, distinct_id: nil, account_id: nil, properties: {}, time: nil, ip: nil,first_check_id:nil, skip_local_check: false)
113
+ begin
114
+ _check_name event_name
115
+ _check_id(distinct_id, account_id)
116
+ unless skip_local_check
117
+ _check_properties(:track, properties)
118
+ end
119
+ rescue TDAnalyticsError => e
120
+ @error_handler.handle(e)
121
+ return false
122
+ end
123
+
124
+ _internal_track(:track, event_name: event_name, distinct_id: distinct_id, account_id: account_id, properties: properties, time: time, ip: ip, first_check_id: first_check_id)
125
+ end
126
+
127
+ ##
128
+ # Report overridable event
129
+ # event_name: (require) A string of 50 letters and digits that starts with '#' or a letter
130
+ # event_id: (require) string
131
+ # distinct_id: (optional) distinct ID
132
+ # account_id: (optional) account ID. distinct_id, account_id can't both be empty.
133
+ # properties: (optional) string、number、Time、boolean
134
+ # time: (optional)Time
135
+ # ip: (optional) ip
136
+ # skip_local_check: (optional) check data or not
137
+ def track_overwrite(event_name: nil,event_id: nil, distinct_id: nil, account_id: nil, properties: {}, time: nil, ip: nil, skip_local_check: false)
138
+ begin
139
+ _check_name event_name
140
+ _check_event_id event_id
141
+ _check_id(distinct_id, account_id)
142
+ unless skip_local_check
143
+ _check_properties(:track_overwrite, properties)
144
+ end
145
+ rescue TDAnalyticsError => e
146
+ @error_handler.handle(e)
147
+ return false
148
+ end
149
+
150
+ _internal_track(:track_overwrite, event_name: event_name, event_id: event_id, distinct_id: distinct_id, account_id: account_id, properties: properties, time: time, ip: ip)
151
+ end
152
+
153
+ ##
154
+ # Report updatable event
155
+ # event_name: (require) A string of 50 letters and digits that starts with '#' or a letter
156
+ # event_id: (require) string
157
+ # distinct_id: (optional) distinct ID
158
+ # account_id: (optional) account ID. distinct_id, account_id can't both be empty.
159
+ # properties: (optional) string、number、Time、boolean
160
+ # time: (optional)Time
161
+ # ip: (optional) ip
162
+ # skip_local_check: (optional) check data or not
163
+ def track_update(event_name: nil,event_id: nil, distinct_id: nil, account_id: nil, properties: {}, time: nil, ip: nil, skip_local_check: false)
164
+ begin
165
+ _check_name event_name
166
+ _check_event_id event_id
167
+ _check_id(distinct_id, account_id)
168
+ unless skip_local_check
169
+ _check_properties(:track_update, properties)
170
+ end
171
+ rescue TDAnalyticsError => e
172
+ @error_handler.handle(e)
173
+ return false
174
+ end
175
+
176
+ _internal_track(:track_update, event_name: event_name, event_id: event_id, distinct_id: distinct_id, account_id: account_id, properties: properties, time: time, ip: ip)
177
+ end
178
+
179
+ ##
180
+ # Set user properties. would overwrite existing names
181
+ # distinct_id: (optional) distinct ID
182
+ # account_id: (optional) account ID. distinct_id, account_id can't both be empty.
183
+ # properties: (optional) string、number、Time、boolean
184
+ # ip: (optional) ip
185
+ def user_set(distinct_id: nil, account_id: nil, properties: {}, ip: nil)
186
+ begin
187
+ _check_id(distinct_id, account_id)
188
+ _check_properties(:user_set, properties)
189
+ rescue TDAnalyticsError => e
190
+ @error_handler.handle(e)
191
+ return false
192
+ end
193
+
194
+ _internal_track(:user_set, distinct_id: distinct_id, account_id: account_id, properties: properties, ip: ip)
195
+ end
196
+
197
+ ##
198
+ # Set user properties, If such property had been set before, this message would be neglected
199
+ # distinct_id: (optional) distinct ID
200
+ # account_id: (optional) account ID. distinct_id, account_id can't both be empty.
201
+ # properties: (optional) string、number、Time、boolean
202
+ # ip: (optional) ip
203
+ def user_set_once(distinct_id: nil, account_id: nil, properties: {}, ip: nil)
204
+ begin
205
+ _check_id(distinct_id, account_id)
206
+ _check_properties(:user_setOnce, properties)
207
+ rescue TDAnalyticsError => e
208
+ @error_handler.handle(e)
209
+ return false
210
+ end
211
+
212
+ _internal_track(:user_setOnce,
213
+ distinct_id: distinct_id,
214
+ account_id: account_id,
215
+ properties: properties,
216
+ ip: ip,
217
+ )
218
+ end
219
+
220
+ ##
221
+ # To append user properties of array type
222
+ # distinct_id: (optional) distinct ID
223
+ # account_id: (optional) account ID. distinct_id, account_id can't both be empty.
224
+ # properties: (optional) string、number、Time、boolean
225
+ def user_append(distinct_id: nil, account_id: nil, properties: {})
226
+ begin
227
+ _check_id(distinct_id, account_id)
228
+ _check_properties(:user_append, properties)
229
+ rescue TDAnalyticsError => e
230
+ @error_handler.handle(e)
231
+ return false
232
+ end
233
+
234
+ _internal_track(:user_append,
235
+ distinct_id: distinct_id,
236
+ account_id: account_id,
237
+ properties: properties,
238
+ )
239
+ end
240
+
241
+ ##
242
+ # To append user properties of array type. It filters out duplicate values
243
+ # distinct_id: (optional) distinct ID
244
+ # account_id: (optional) account ID. distinct_id, account_id can't both be empty.
245
+ # properties: (optional) string、number、Time、boolean
246
+ def user_uniq_append(distinct_id: nil, account_id: nil, properties: {})
247
+ begin
248
+ _check_id(distinct_id, account_id)
249
+ _check_properties(:user_uniq_append, properties)
250
+ rescue TDAnalyticsError => e
251
+ @error_handler.handle(e)
252
+ return false
253
+ end
254
+
255
+ _internal_track(:user_uniq_append,
256
+ distinct_id: distinct_id,
257
+ account_id: account_id,
258
+ properties: properties,
259
+ )
260
+ end
261
+
262
+ ##
263
+ # Clear the user properties of users
264
+ # distinct_id: (optional) distinct ID
265
+ # account_id: (optional) account ID. distinct_id, account_id can't both be empty.
266
+ # properties: (optional) string、number、Time、boolean
267
+ def user_unset(distinct_id: nil, account_id: nil, property: nil)
268
+ properties = {}
269
+ if property.is_a?(Array)
270
+ property.each do |k|
271
+ properties[k] = 0
272
+ end
273
+ else
274
+ properties[property] = 0
275
+ end
276
+
277
+ begin
278
+ _check_id(distinct_id, account_id)
279
+ _check_properties(:user_unset, properties)
280
+ rescue TDAnalyticsError => e
281
+ @error_handler.handle(e)
282
+ return false
283
+ end
284
+
285
+ _internal_track(:user_unset,
286
+ distinct_id: distinct_id,
287
+ account_id: account_id,
288
+ properties: properties,
289
+ )
290
+ end
291
+
292
+ ##
293
+ # To accumulate operations against the property
294
+ # distinct_id: (optional) distinct ID
295
+ # account_id: (optional) account ID. distinct_id, account_id can't both be empty.
296
+ # properties: (optional) string、number、Time、boolean
297
+ def user_add(distinct_id: nil, account_id: nil, properties: {})
298
+ begin
299
+ _check_id(distinct_id, account_id)
300
+ _check_properties(:user_add, properties)
301
+ rescue TDAnalyticsError => e
302
+ @error_handler.handle(e)
303
+ return false
304
+ end
305
+
306
+ _internal_track(:user_add,
307
+ distinct_id: distinct_id,
308
+ account_id: account_id,
309
+ properties: properties,
310
+ )
311
+ end
312
+
313
+ ##
314
+ # Delete a user, This operation cannot be undone
315
+ # distinct_id: (optional) distinct ID
316
+ # account_id: (optional) account ID. distinct_id, account_id can't both be empty.
317
+ def user_del(distinct_id: nil, account_id: nil)
318
+ begin
319
+ _check_id(distinct_id, account_id)
320
+ rescue TDAnalyticsError => e
321
+ @error_handler.handle(e)
322
+ return false
323
+ end
324
+
325
+ _internal_track(:user_del,
326
+ distinct_id: distinct_id,
327
+ account_id: account_id,
328
+ )
329
+ end
330
+
331
+ ##
332
+ # Report data immediately
333
+ def flush
334
+ TDLog.info("SDK flush data.")
335
+ return true unless defined? @consumer.flush
336
+ ret = true
337
+ begin
338
+ @consumer.flush
339
+ rescue TDAnalyticsError => e
340
+ @error_handler.handle(e)
341
+ ret = false
342
+ end
343
+ ret
344
+ end
345
+
346
+ ##
347
+ # Close and exit sdk
348
+ def close
349
+ return true unless defined? @consumer.close
350
+ ret = true
351
+ begin
352
+ @consumer.close
353
+ rescue TDAnalyticsError => e
354
+ @error_handler.handle(e)
355
+ ret = false
356
+ end
357
+
358
+ TDLog.info("SDK close.")
359
+
360
+ ret
361
+ end
362
+
363
+ private
364
+
365
+ def _internal_track(type, properties: {}, event_name: nil, event_id:nil, account_id: nil, distinct_id: nil, ip: nil,first_check_id: nil, time: nil)
366
+ if type == :track || type == :track_update || type == :track_overwrite
367
+ dynamic_properties = @dynamic_block.respond_to?(:call) ? @dynamic_block.call : {}
368
+ properties = LIB_PROPERTIES.merge(@super_properties).merge(dynamic_properties).merge(properties)
369
+ end
370
+
371
+ data = {
372
+ '#type' => type,
373
+ }
374
+
375
+ properties.each do |k, v|
376
+ if v.is_a?(Time)
377
+ properties[k] = _format_time(v)
378
+ end
379
+ end
380
+
381
+ _move_preset_properties([:'#ip', :"#time", :"#app_id", :"#uuid"], data, properties: properties)
382
+
383
+ if data[:'#time'] == nil
384
+ if time == nil
385
+ time = Time.now
386
+ end
387
+ data[:'#time'] = _format_time(time)
388
+ end
389
+
390
+ data['properties'] = properties
391
+ data['#event_name'] = event_name if (type == :track || type == :track_update || type == :track_overwrite)
392
+ data['#event_id'] = event_id if (type == :track_update || type == :track_overwrite)
393
+ data['#account_id'] = account_id if account_id
394
+ data['#distinct_id'] = distinct_id if distinct_id
395
+ data['#ip'] = ip if ip
396
+ data['#first_check_id'] = first_check_id if first_check_id
397
+ data[:'#uuid'] = SecureRandom.uuid if @uuid_enable and data[:'#uuid'] == nil
398
+
399
+ ret = true
400
+ begin
401
+ @consumer.add(data)
402
+ rescue TDAnalyticsError => e
403
+ @error_handler.handle(e)
404
+ ret = false
405
+ end
406
+
407
+ ret
408
+ end
409
+
410
+ def _format_time(time)
411
+ time.strftime("%Y-%m-%d %H:%M:%S.#{((time.to_f * 1000.0).to_i % 1000).to_s.rjust(3, "0")}")
412
+ end
413
+
414
+ def _check_event_id(event_id)
415
+ if ThinkingData::get_stringent == false
416
+ return true
417
+ end
418
+
419
+ raise IllegalParameterError.new("the event_id or property cannot be nil") if event_id.nil?
420
+ true
421
+ end
422
+
423
+ def _check_name(name)
424
+ if ThinkingData::get_stringent == false
425
+ return true
426
+ end
427
+
428
+ raise IllegalParameterError.new("the name of event or property cannot be nil") if name.nil?
429
+
430
+ unless name.instance_of?(String) || name.instance_of?(Symbol)
431
+ raise IllegalParameterError.new("#{name} is invalid. It must be String or Symbol")
432
+ end
433
+ true
434
+ end
435
+
436
+ def _check_properties(type, properties)
437
+ if ThinkingData::get_stringent == false
438
+ return true
439
+ end
440
+
441
+ unless properties.instance_of? Hash
442
+ return false
443
+ end
444
+
445
+ properties.each do |k, v|
446
+ _check_name k
447
+ next if v.nil?
448
+ unless v.is_a?(Integer) || v.is_a?(Float) || v.is_a?(Symbol) || v.is_a?(String) || v.is_a?(Time) || !!v == v || v.is_a?(Array)
449
+ raise IllegalParameterError.new("The value of properties must be type in Integer, Float, Symbol, String, Array,and Time")
450
+ end
451
+
452
+ if type == :user_add
453
+ raise IllegalParameterError.new("Property value for user add must be numbers") unless v.is_a?(Integer) || v.is_a?(Float)
454
+ end
455
+ if v.is_a?(Array)
456
+ v.each_index do |i|
457
+ if v[i].is_a?(Time)
458
+ v[i] = _format_time(v[i])
459
+ end
460
+ end
461
+ end
462
+ end
463
+ true
464
+ end
465
+
466
+ def _check_id(distinct_id, account_id)
467
+ if ThinkingData::get_stringent == false
468
+ return true
469
+ end
470
+
471
+ raise IllegalParameterError.new("account id or distinct id must be provided.") if distinct_id.nil? && account_id.nil?
472
+ end
473
+
474
+ def _move_preset_properties(keys, data, properties: {})
475
+ property_keys = properties.keys
476
+ keys.each { |k|
477
+ if property_keys.include? k
478
+ data[k] = properties[k]
479
+ properties.delete(k)
480
+ end
481
+ }
482
+ end
483
+ end
484
+
485
+ ##
486
+ # SDK log module
487
+ class TDLog
488
+ def self.info(*msg)
489
+ if ThinkingData::get_enable_log
490
+ print("[ThinkingData][#{Time.now}] ")
491
+ puts(msg)
492
+ end
493
+ end
494
+ end
495
+ end