thinkingdata-ruby 1.2.1 → 2.0.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cdd6d7eb248bfbddc35fdc947a9323ff6a1a16d10c2e396b5cd3f80dd272f866
4
- data.tar.gz: e6ee651f3d35226a5f640f0c57868964abe0eba5841335249b262a81b264a018
3
+ metadata.gz: ba7de0dac467fe8c90747854c7701e0af035463b9b48b4708308e4c28d242c90
4
+ data.tar.gz: fa29bd005cbe4b32cceecd85d726e79b7b0e0fb4e51346b649f25d7b44affcca
5
5
  SHA512:
6
- metadata.gz: 442a30338ce592df0f6c9e3dd505255390e8797d405326009064531f45637bd2c86f1bbca10efd14a8e6dd8b12ebbfe183be0795c8e029fcec19362627024033
7
- data.tar.gz: 605e8773859e0147486ed023c7ab187cd308aaf4e810cc1f633d9e72810cbadfd01fe19b45bebd1042e8741b1ac0e791d8662c36c5097e6d94694d5b051d0a0d
6
+ metadata.gz: e73fadf565e9143fd67ad1c99e1472ee027d7eda707a4b2452705b620d05d1f223b71e99d61b84c0bbb353792f2f1f62212c7d2c04e670c736ee5e94db74291e
7
+ data.tar.gz: 39fce15278418ba6d92dface6276acee8760953954ff5521fb115f91c81bf83807e063e7caf6a59db0fd8e388407f74a7a0748d02b99086d3de91c8f2b0ffd31
data/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ### v2.0.1
2
+ **Date:** 2026/05/13
3
+
4
+ **Notes:**
5
+
6
+ * Supports multi-threaded invocation
7
+
8
+ ### v2.0.0
9
+ **Date:** 2023/09/20
10
+
11
+ **Notes:**
12
+
13
+ * Modified module name, incompatible with older versions
14
+
1
15
  ### v1.2.1
2
16
  **Date:** 2023/03/20
3
17
 
@@ -6,7 +20,6 @@
6
20
  * Compatible ruby 3
7
21
  * Supports a different '#app_id' for each event
8
22
 
9
-
10
23
  ### v1.2.0
11
24
  **Date:** 2020/08/28
12
25
 
data/README.md CHANGED
@@ -1,5 +1,6 @@
1
1
  # ThinkingData SDK for Ruby
2
- ![output](https://user-images.githubusercontent.com/53337625/205621683-ed9b97ef-6a52-4903-a2c0-a955dddebb7d.png)
2
+
3
+ <img src="https://user-images.githubusercontent.com/53337625/205621683-ed9b97ef-6a52-4903-a2c0-a955dddebb7d.png" alt="logo" width="50%"/>
3
4
 
4
5
  This is the [ThinkingData](https://www.thinkingdata.cn)™ SDK for Ruby. Documentation is available on our help center in the following languages:
5
6
 
data/demo/demo.rb CHANGED
@@ -4,38 +4,38 @@ require 'thinkingdata-ruby'
4
4
  require 'time'
5
5
 
6
6
  if __FILE__ == $0
7
- DEMO_APPID = 'app id'
8
- SERVER_URL = 'server url'
9
- DEMO_ACCOUNT_ID = '123'
10
- DEMO_DISTINCT_ID = 'aaa'
11
7
 
12
- class MyErrorHandler < TDAnalytics::ErrorHandler
8
+ class MyErrorHandler < ThinkingData::TDErrorHandler
13
9
  def handle(error)
14
10
  puts error
15
11
  raise error
16
12
  end
17
13
  end
18
- my_error_handler = MyErrorHandler.new
19
14
 
20
- TDAnalytics::set_stringent(false)
21
- TDAnalytics::set_enable_log(true)
22
-
23
- consumer = nil
24
- $ARGV = 0
25
- case $ARGV
26
- when 0
27
- consumer = TDAnalytics::LoggerConsumer.new './log', 'hourly'
28
- when 1
29
- consumer = TDAnalytics::DebugConsumer.new(SERVER_URL, DEMO_APPID, device_id: "123456789")
30
- # consumer = TDAnalytics::DebugConsumer.new(SERVER_URL, DEMO_APPID,false)
31
- when 2
32
- consumer = TDAnalytics::BatchConsumer.new(SERVER_URL, DEMO_APPID, 30)
33
- #consumer._set_compress(false)
34
- else
35
- consumer = TDAnalytics::LoggerConsumer.new
15
+ def logger_consumer
16
+ ThinkingData::TDLoggerConsumer.new('./log', 'hourly')
17
+ end
18
+
19
+ def debug_consumer
20
+ ThinkingData::TDDebugConsumer.new("serverUrl", "appId", device_id: "123456789")
21
+ end
22
+
23
+ def batch_consumer
24
+ consumer = ThinkingData::TDBatchConsumer.new("serverUrl", "appId", 50)
25
+ consumer._set_compress(false)
26
+ consumer
36
27
  end
37
28
 
38
- ta = TDAnalytics::Tracker.new(consumer, my_error_handler, uuid: true)
29
+ ThinkingData::set_stringent(false)
30
+ ThinkingData::set_enable_log(true)
31
+ my_error_handler = MyErrorHandler.new
32
+
33
+ td_sdk = ThinkingData::TDAnalytics.new(logger_consumer, my_error_handler, uuid: false)
34
+ # td_sdk = ThinkingData::TDAnalytics.new(debug_consumer, my_error_handler, uuid: true)
35
+ # td_sdk = ThinkingData::TDAnalytics.new(batch_consumer, my_error_handler, uuid: true)
36
+
37
+ DEMO_ACCOUNT_ID = '123'
38
+ DEMO_DISTINCT_ID = 'aaa'
39
39
 
40
40
  super_properties = {
41
41
  super_string: 'super_string',
@@ -45,7 +45,7 @@ if __FILE__ == $0
45
45
  '#app_id': "123123123123123"
46
46
  }
47
47
 
48
- ta.set_super_properties(super_properties)
48
+ td_sdk.set_super_properties(super_properties)
49
49
 
50
50
  properties = {
51
51
  array: ["str1", "11", Time.now, "2020-02-11 17:02:52.415"],
@@ -54,19 +54,18 @@ if __FILE__ == $0
54
54
  prop_string: 'hello world',
55
55
  prop_bool: true,
56
56
  '#ip': '123.123.123.123',
57
- '#uuid': 'aaabbbccc',
58
57
  }
59
58
 
60
- ta.set_dynamic_super_properties do
59
+ td_sdk.set_dynamic_super_properties do
61
60
  {:dynamic_time => Time.now}
62
61
  end
63
62
 
64
- ta.track(event_name: 'test_event', distinct_id: DEMO_DISTINCT_ID, account_id: DEMO_ACCOUNT_ID, properties: properties)
63
+ td_sdk.track(event_name: 'test_event', distinct_id: DEMO_DISTINCT_ID, account_id: DEMO_ACCOUNT_ID, properties: properties)
65
64
 
66
- ta.clear_dynamic_super_properties
67
- ta.clear_super_properties
65
+ td_sdk.clear_dynamic_super_properties
66
+ td_sdk.clear_super_properties
68
67
 
69
- ta.track(event_name: 'test_event', distinct_id: DEMO_DISTINCT_ID, account_id: DEMO_ACCOUNT_ID, properties: properties)
68
+ td_sdk.track(event_name: 'test_event', distinct_id: DEMO_DISTINCT_ID, account_id: DEMO_ACCOUNT_ID, properties: properties)
70
69
 
71
70
  user_data = {
72
71
  array: ["str1", 11, 22.22],
@@ -75,31 +74,31 @@ if __FILE__ == $0
75
74
  prop_string: 'hello',
76
75
  prop_int: 666,
77
76
  }
78
- ta.user_set(distinct_id: DEMO_DISTINCT_ID, account_id: DEMO_ACCOUNT_ID, properties: user_data)
77
+ td_sdk.user_set(distinct_id: DEMO_DISTINCT_ID, account_id: DEMO_ACCOUNT_ID, properties: user_data)
79
78
 
80
79
  user_append_data = {
81
80
  array: %w[33 44]
82
81
  }
83
- ta.user_append(distinct_id: DEMO_DISTINCT_ID, account_id: DEMO_ACCOUNT_ID, properties: user_append_data)
82
+ td_sdk.user_append(distinct_id: DEMO_DISTINCT_ID, account_id: DEMO_ACCOUNT_ID, properties: user_append_data)
84
83
 
85
84
  user_uniq_append_data = {
86
85
  array: %w[44 55]
87
86
  }
88
- ta.user_uniq_append(distinct_id: DEMO_DISTINCT_ID, account_id: DEMO_ACCOUNT_ID, properties: user_uniq_append_data)
87
+ td_sdk.user_uniq_append(distinct_id: DEMO_DISTINCT_ID, account_id: DEMO_ACCOUNT_ID, properties: user_uniq_append_data)
89
88
 
90
89
  user_set_once_data = {
91
90
  prop_int_new: 888,
92
91
  }
93
- ta.user_set_once(distinct_id: DEMO_DISTINCT_ID, account_id: DEMO_ACCOUNT_ID, properties: user_set_once_data)
92
+ td_sdk.user_set_once(distinct_id: DEMO_DISTINCT_ID, account_id: DEMO_ACCOUNT_ID, properties: user_set_once_data)
94
93
 
95
- ta.user_add(distinct_id: DEMO_DISTINCT_ID, properties: {prop_int: 10, prop_double: 15.88})
94
+ td_sdk.user_add(distinct_id: DEMO_DISTINCT_ID, properties: {prop_int: 10, prop_double: 15.88})
96
95
 
97
- ta.user_unset(distinct_id: DEMO_DISTINCT_ID, property: [:prop_string, :prop_int])
96
+ td_sdk.user_unset(distinct_id: DEMO_DISTINCT_ID, property: [:prop_string, :prop_int])
98
97
 
99
- ta.user_del(distinct_id: DEMO_DISTINCT_ID)
98
+ td_sdk.user_del(distinct_id: DEMO_DISTINCT_ID)
100
99
 
101
- ta.flush
100
+ td_sdk.flush
102
101
 
103
- ta.close
102
+ td_sdk.close
104
103
  end
105
104
 
@@ -1,11 +1,16 @@
1
1
  require 'securerandom'
2
- require 'thinkingdata-ruby/errors'
3
- require 'thinkingdata-ruby/version'
2
+ require 'thinkingdata-ruby/td_errors'
3
+ require 'thinkingdata-ruby/td_version'
4
4
 
5
- module TDAnalytics
5
+ ##
6
+ # ThinkingData module
7
+ module ThinkingData
6
8
  @is_enable_log = false
7
9
  @is_stringent = false
8
10
 
11
+ ##
12
+ # Enable SDK log or not
13
+ # @param enable [Boolean] true or false
9
14
  def self.set_enable_log(enable)
10
15
  unless [true, false].include? enable
11
16
  enable = false
@@ -13,10 +18,16 @@ module TDAnalytics
13
18
  @is_enable_log = enable
14
19
  end
15
20
 
21
+ ##
22
+ # Get log status
23
+ # @return [Boolean] enable or not
16
24
  def self.get_enable_log
17
25
  @is_enable_log
18
26
  end
19
27
 
28
+ ##
29
+ # Check or not parameter
30
+ # @param enable [Boolean] check or not
20
31
  def self.set_stringent(enable)
21
32
  unless [true, false].include? enable
22
33
  enable = false
@@ -24,53 +35,81 @@ module TDAnalytics
24
35
  @is_stringent = enable
25
36
  end
26
37
 
38
+ ##
39
+ # Get parameter check status of SDK
40
+ # @return [Boolean] check or not
27
41
  def self.get_stringent
28
42
  @is_stringent
29
43
  end
30
44
 
31
- class Tracker
45
+ ##
46
+ # Analytics class。 Provides the function of tracking data
47
+ class TDAnalytics
32
48
  LIB_PROPERTIES = {
33
49
  '#lib' => 'ruby',
34
- '#lib_version' => TDAnalytics::VERSION,
50
+ '#lib_version' => ThinkingData::VERSION,
35
51
  }
36
52
 
37
- @@dynamic_block = nil
53
+ @dynamic_block = nil
38
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
39
60
  def initialize(consumer, error_handler = nil, uuid: false)
40
- @error_handler = error_handler || ErrorHandler.new
61
+ @error_handler = error_handler || TDErrorHandler.new
41
62
  @consumer = consumer
42
63
  @super_properties = {}
43
- @uuid = uuid
64
+ @uuid_enable = uuid
65
+ @mutex = Mutex.new
66
+ TDLog.info("SDK init success.")
44
67
  end
45
68
 
46
- # set common properties
69
+ ##
70
+ # Set common properties
47
71
  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
72
+ @mutex.synchronize do
73
+ unless ThinkingData::get_stringent == false || skip_local_check || _check_properties(:track, properties)
74
+ @error_handler.handle(IllegalParameterError.new("Invalid super properties"))
75
+ return false
76
+ end
77
+ properties.each do |k, v|
78
+ if v.is_a?(Time)
79
+ @super_properties[k] = _format_time(v)
80
+ else
81
+ @super_properties[k] = v
82
+ end
57
83
  end
58
84
  end
59
85
  end
60
86
 
87
+ ##
88
+ # Clear super properties
61
89
  def clear_super_properties
62
- @super_properties = {}
90
+ @mutex.synchronize do
91
+ @super_properties = {}
92
+ end
63
93
  end
64
94
 
95
+ ##
96
+ # Set dynamic super properties
65
97
  def set_dynamic_super_properties(&block)
66
- @@dynamic_block = block
98
+ @mutex.synchronize do
99
+ @dynamic_block = block
100
+ end
67
101
  end
68
102
 
103
+ ##
104
+ # Clear dynamic super properties
69
105
  def clear_dynamic_super_properties
70
- @@dynamic_block = nil
106
+ @mutex.synchronize do
107
+ @dynamic_block = nil
108
+ end
71
109
  end
72
110
 
73
- # report ordinary event
111
+ ##
112
+ # Report ordinary event
74
113
  # event_name: (require) A string of 50 letters and digits that starts with '#' or a letter
75
114
  # distinct_id: (optional) distinct ID
76
115
  # account_id: (optional) account ID. distinct_id, account_id can't both be empty.
@@ -94,7 +133,16 @@ module TDAnalytics
94
133
  _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
134
  end
96
135
 
97
- # report overridable event
136
+ ##
137
+ # Report overridable event
138
+ # event_name: (require) A string of 50 letters and digits that starts with '#' or a letter
139
+ # event_id: (require) string
140
+ # distinct_id: (optional) distinct ID
141
+ # account_id: (optional) account ID. distinct_id, account_id can't both be empty.
142
+ # properties: (optional) string、number、Time、boolean
143
+ # time: (optional)Time
144
+ # ip: (optional) ip
145
+ # skip_local_check: (optional) check data or not
98
146
  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
147
  begin
100
148
  _check_name event_name
@@ -111,7 +159,16 @@ module TDAnalytics
111
159
  _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
160
  end
113
161
 
114
- # report updatable event
162
+ ##
163
+ # Report updatable event
164
+ # event_name: (require) A string of 50 letters and digits that starts with '#' or a letter
165
+ # event_id: (require) string
166
+ # distinct_id: (optional) distinct ID
167
+ # account_id: (optional) account ID. distinct_id, account_id can't both be empty.
168
+ # properties: (optional) string、number、Time、boolean
169
+ # time: (optional)Time
170
+ # ip: (optional) ip
171
+ # skip_local_check: (optional) check data or not
115
172
  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
173
  begin
117
174
  _check_name event_name
@@ -128,7 +185,12 @@ module TDAnalytics
128
185
  _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
186
  end
130
187
 
131
- # set user properties. would overwrite existing names.
188
+ ##
189
+ # Set user properties. would overwrite existing names
190
+ # distinct_id: (optional) distinct ID
191
+ # account_id: (optional) account ID. distinct_id, account_id can't both be empty.
192
+ # properties: (optional) string、number、Time、boolean
193
+ # ip: (optional) ip
132
194
  def user_set(distinct_id: nil, account_id: nil, properties: {}, ip: nil)
133
195
  begin
134
196
  _check_id(distinct_id, account_id)
@@ -141,7 +203,12 @@ module TDAnalytics
141
203
  _internal_track(:user_set, distinct_id: distinct_id, account_id: account_id, properties: properties, ip: ip)
142
204
  end
143
205
 
144
- # set user properties, If such property had been set before, this message would be neglected.
206
+ ##
207
+ # Set user properties, If such property had been set before, this message would be neglected
208
+ # distinct_id: (optional) distinct ID
209
+ # account_id: (optional) account ID. distinct_id, account_id can't both be empty.
210
+ # properties: (optional) string、number、Time、boolean
211
+ # ip: (optional) ip
145
212
  def user_set_once(distinct_id: nil, account_id: nil, properties: {}, ip: nil)
146
213
  begin
147
214
  _check_id(distinct_id, account_id)
@@ -159,7 +226,11 @@ module TDAnalytics
159
226
  )
160
227
  end
161
228
 
162
- # to add user properties of array type.
229
+ ##
230
+ # To append user properties of array type
231
+ # distinct_id: (optional) distinct ID
232
+ # account_id: (optional) account ID. distinct_id, account_id can't both be empty.
233
+ # properties: (optional) string、number、Time、boolean
163
234
  def user_append(distinct_id: nil, account_id: nil, properties: {})
164
235
  begin
165
236
  _check_id(distinct_id, account_id)
@@ -176,6 +247,11 @@ module TDAnalytics
176
247
  )
177
248
  end
178
249
 
250
+ ##
251
+ # To append user properties of array type. It filters out duplicate values
252
+ # distinct_id: (optional) distinct ID
253
+ # account_id: (optional) account ID. distinct_id, account_id can't both be empty.
254
+ # properties: (optional) string、number、Time、boolean
179
255
  def user_uniq_append(distinct_id: nil, account_id: nil, properties: {})
180
256
  begin
181
257
  _check_id(distinct_id, account_id)
@@ -192,7 +268,11 @@ module TDAnalytics
192
268
  )
193
269
  end
194
270
 
195
- # clear the user properties of users.
271
+ ##
272
+ # Clear the user properties of users
273
+ # distinct_id: (optional) distinct ID
274
+ # account_id: (optional) account ID. distinct_id, account_id can't both be empty.
275
+ # properties: (optional) string、number、Time、boolean
196
276
  def user_unset(distinct_id: nil, account_id: nil, property: nil)
197
277
  properties = {}
198
278
  if property.is_a?(Array)
@@ -218,7 +298,11 @@ module TDAnalytics
218
298
  )
219
299
  end
220
300
 
221
- # to accumulate operations against the property.
301
+ ##
302
+ # To accumulate operations against the property
303
+ # distinct_id: (optional) distinct ID
304
+ # account_id: (optional) account ID. distinct_id, account_id can't both be empty.
305
+ # properties: (optional) string、number、Time、boolean
222
306
  def user_add(distinct_id: nil, account_id: nil, properties: {})
223
307
  begin
224
308
  _check_id(distinct_id, account_id)
@@ -235,7 +319,10 @@ module TDAnalytics
235
319
  )
236
320
  end
237
321
 
238
- # delete a user, This operation cannot be undone.
322
+ ##
323
+ # Delete a user, This operation cannot be undone
324
+ # distinct_id: (optional) distinct ID
325
+ # account_id: (optional) account ID. distinct_id, account_id can't both be empty.
239
326
  def user_del(distinct_id: nil, account_id: nil)
240
327
  begin
241
328
  _check_id(distinct_id, account_id)
@@ -250,8 +337,10 @@ module TDAnalytics
250
337
  )
251
338
  end
252
339
 
253
- # report data immediately.
340
+ ##
341
+ # Report data immediately
254
342
  def flush
343
+ TDLog.info("SDK flush data.")
255
344
  return true unless defined? @consumer.flush
256
345
  ret = true
257
346
  begin
@@ -263,25 +352,35 @@ module TDAnalytics
263
352
  ret
264
353
  end
265
354
 
355
+ ##
266
356
  # Close and exit sdk
267
357
  def close
268
358
  return true unless defined? @consumer.close
269
359
  ret = true
360
+ # Consumer 自身已有锁保护,无需在此加锁
270
361
  begin
271
362
  @consumer.close
272
363
  rescue TDAnalyticsError => e
273
364
  @error_handler.handle(e)
274
365
  ret = false
275
366
  end
367
+
368
+ TDLog.info("SDK close.")
369
+
276
370
  ret
277
371
  end
278
372
 
279
373
  private
280
374
 
281
375
  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)
376
+ ret = true
377
+
378
+ # 只在访问共享状态时加锁
282
379
  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)
380
+ @mutex.synchronize do
381
+ dynamic_properties = @dynamic_block.respond_to?(:call) ? @dynamic_block.call : {}
382
+ properties = LIB_PROPERTIES.merge(@super_properties).merge(dynamic_properties).merge(properties)
383
+ end
285
384
  end
286
385
 
287
386
  data = {
@@ -310,9 +409,8 @@ module TDAnalytics
310
409
  data['#distinct_id'] = distinct_id if distinct_id
311
410
  data['#ip'] = ip if ip
312
411
  data['#first_check_id'] = first_check_id if first_check_id
313
- data[:'#uuid'] = SecureRandom.uuid if @uuid and data[:'#uuid'] == nil
412
+ data[:'#uuid'] = SecureRandom.uuid if @uuid_enable and data[:'#uuid'] == nil
314
413
 
315
- ret = true
316
414
  begin
317
415
  @consumer.add(data)
318
416
  rescue TDAnalyticsError => e
@@ -328,7 +426,7 @@ module TDAnalytics
328
426
  end
329
427
 
330
428
  def _check_event_id(event_id)
331
- if TDAnalytics::get_stringent == false
429
+ if ThinkingData::get_stringent == false
332
430
  return true
333
431
  end
334
432
 
@@ -337,7 +435,7 @@ module TDAnalytics
337
435
  end
338
436
 
339
437
  def _check_name(name)
340
- if TDAnalytics::get_stringent == false
438
+ if ThinkingData::get_stringent == false
341
439
  return true
342
440
  end
343
441
 
@@ -350,7 +448,7 @@ module TDAnalytics
350
448
  end
351
449
 
352
450
  def _check_properties(type, properties)
353
- if TDAnalytics::get_stringent == false
451
+ if ThinkingData::get_stringent == false
354
452
  return true
355
453
  end
356
454
 
@@ -380,7 +478,7 @@ module TDAnalytics
380
478
  end
381
479
 
382
480
  def _check_id(distinct_id, account_id)
383
- if TDAnalytics::get_stringent == false
481
+ if ThinkingData::get_stringent == false
384
482
  return true
385
483
  end
386
484
 
@@ -398,10 +496,12 @@ module TDAnalytics
398
496
  end
399
497
  end
400
498
 
401
- class TELog
499
+ ##
500
+ # SDK log module
501
+ class TDLog
402
502
  def self.info(*msg)
403
- if TDAnalytics::get_enable_log
404
- print("[ThinkingEngine][#{Time.now}][info]-")
503
+ if ThinkingData::get_enable_log
504
+ print("[ThinkingData][#{Time.now}] ")
405
505
  puts(msg)
406
506
  end
407
507
  end
@@ -1,13 +1,18 @@
1
1
  require 'json'
2
2
  require 'net/http'
3
+ require 'stringio'
3
4
 
4
- module TDAnalytics
5
- class BatchConsumer
5
+ module ThinkingData
6
+ ##
7
+ # Upload data by http
8
+ class TDBatchConsumer
6
9
 
7
10
  # buffer count
8
11
  DEFAULT_LENGTH = 20
9
12
  MAX_LENGTH = 2000
10
13
 
14
+ ##
15
+ # Init batch consumer
11
16
  def initialize(server_url, app_id, max_buffer_length = DEFAULT_LENGTH)
12
17
  @server_uri = URI.parse(server_url)
13
18
  @server_uri.path = '/sync_server'
@@ -15,24 +20,52 @@ module TDAnalytics
15
20
  @compress = true
16
21
  @max_length = [max_buffer_length, MAX_LENGTH].min
17
22
  @buffers = []
23
+ @mutex = Mutex.new
24
+ TDLog.info("TDBatchConsumer init success. ServerUrl: #{server_url}, appId: #{app_id}")
18
25
  end
19
26
 
27
+ ##
28
+ # http request compress
29
+ # @param compress [Boolean] compress or not
30
+ # @deprecated please use: set_compress
20
31
  def _set_compress(compress)
21
32
  @compress = compress
22
33
  end
23
34
 
35
+ ##
36
+ # http request compress
37
+ # @param compress [Boolean] compress or not
38
+ def set_compress(compress)
39
+ @compress = compress
40
+ end
41
+
24
42
  def add(message)
25
- @buffers << message
26
- flush if @buffers.length >= @max_length
43
+ TDLog.info("Enqueue data to buffer. buffer size: #{@buffers.length}, data: #{message}")
44
+ need_flush = false
45
+ @mutex.synchronize do
46
+ @buffers << message
47
+ need_flush = @buffers.length >= @max_length
48
+ end
49
+ flush if need_flush
27
50
  end
28
51
 
29
52
  def close
30
53
  flush
54
+ TDLog.info("TDBatchConsumer close.")
31
55
  end
32
56
 
33
57
  def flush
58
+ TDLog.info("TDBatchConsumer flush data.")
59
+ data_to_send = nil
60
+ @mutex.synchronize do
61
+ data_to_send = @buffers.dup
62
+ @buffers = []
63
+ end
64
+
65
+ return if data_to_send.empty?
66
+
34
67
  begin
35
- @buffers.each_slice(@max_length) do |chunk|
68
+ data_to_send.each_slice(@max_length) do |chunk|
36
69
  if @compress
37
70
  wio = StringIO.new("w")
38
71
  gzip_io = Zlib::GzipWriter.new(wio)
@@ -46,17 +79,19 @@ module TDAnalytics
46
79
  headers = {'Content-Type' => 'application/plaintext',
47
80
  'appid' => @app_id,
48
81
  'compress' => compress_type,
49
- 'TA-Integration-Type'=>'Ruby',
50
- 'TA-Integration-Version'=>TDAnalytics::VERSION,
51
- 'TA-Integration-Count'=>@buffers.count,
82
+ 'TE-Integration-Type'=>'Ruby',
83
+ 'TE-Integration-Version'=>ThinkingData::VERSION,
84
+ 'TE-Integration-Count'=>data_to_send.count,
52
85
  'TA_Integration-Extra'=>'batch'}
53
86
  request = CaseSensitivePost.new(@server_uri.request_uri, headers)
54
87
  request.body = data
55
88
 
89
+ TDLog.info("Send data, request: #{data}")
56
90
  begin
57
91
  response_code, response_body = _request(@server_uri, request)
92
+ TDLog.info("Send data, response: #{response_body}")
58
93
  rescue => e
59
- raise ConnectionError.new("Could not connect to TA server, with error \"#{e.message}\".")
94
+ raise ConnectionError.new("Could not connect to TE server, with error \"#{e.message}\".")
60
95
  end
61
96
 
62
97
  result = {}
@@ -64,18 +99,17 @@ module TDAnalytics
64
99
  begin
65
100
  result = JSON.parse(response_body.to_s)
66
101
  rescue JSON::JSONError
67
- raise ServerError.new("Could not interpret TA server response: '#{response_body}'")
102
+ raise ServerError.new("Could not interpret TE server response: '#{response_body}'")
68
103
  end
69
104
  end
70
105
 
71
106
  if result['code'] != 0
72
- raise ServerError.new("Could not write to TA, server responded with #{response_code} returning: '#{response_body}'")
107
+ raise ServerError.new("Could not write to TE, server responded with #{response_code} returning: '#{response_body}'")
73
108
  end
74
109
  end
75
110
  rescue
76
111
  raise
77
112
  end
78
- @buffers = []
79
113
  end
80
114
 
81
115
  private
@@ -92,6 +126,8 @@ module TDAnalytics
92
126
  end
93
127
  end
94
128
 
129
+ ##
130
+ # Private class. Send data tools
95
131
  class CaseSensitivePost < Net::HTTP::Post
96
132
  def initialize_http_header(headers)
97
133
  @header = {}
@@ -1,37 +1,43 @@
1
1
  require 'json'
2
2
  require 'net/http'
3
3
 
4
- module TDAnalytics
4
+ module ThinkingData
5
+ ##
5
6
  # The data is reported one by one, and when an error occurs, the log will be printed on the console.
6
- class DebugConsumer
7
-
8
- def test
9
-
10
- end
7
+ class TDDebugConsumer
11
8
 
9
+ ##
10
+ # Init debug consumer
11
+ # @param server_url: server url
12
+ # @param app_id: app id
13
+ # @param write_data: is write data to TE
14
+ # @param device_id: device id
12
15
  def initialize(server_url, app_id, write_data = true, device_id: nil)
13
16
  @server_uri = URI.parse(server_url)
14
17
  @server_uri.path = '/data_debug'
15
18
  @app_id = app_id
16
19
  @write_data = write_data
17
20
  @device_id = device_id
21
+ TDLog.info("TDDebugConsumer init success. ServerUrl: #{server_url}, appId: #{app_id}, deviceId: #{device_id}")
18
22
  end
19
23
 
20
24
  def add(message)
21
- puts message.to_json
25
+ msg_json_str = message.to_json
26
+ TDLog.info("Send data, request: #{msg_json_str}")
22
27
  headers = {
23
- 'TA-Integration-Type'=>'Ruby',
24
- 'TA-Integration-Version'=>TDAnalytics::VERSION,
25
- 'TA-Integration-Count'=>'1',
28
+ 'TE-Integration-Type'=>'Ruby',
29
+ 'TE-Integration-Version'=>ThinkingData::VERSION,
30
+ 'TE-Integration-Count'=>'1',
26
31
  'TA_Integration-Extra'=>'debug'
27
32
  }
28
- form_data = {"data" => message.to_json, "appid" => @app_id, "dryRun" => @write_data ? "0" : "1", "source" => "server"}
33
+ form_data = {"data" => msg_json_str, "appid" => @app_id, "dryRun" => @write_data ? "0" : "1", "source" => "server"}
29
34
  @device_id.is_a?(String) ? form_data["deviceId"] = @device_id : nil
30
35
 
31
36
  begin
32
37
  response_code, response_body = request(@server_uri, form_data,headers)
38
+ TDLog.info("Send data, response: #{response_body}")
33
39
  rescue => e
34
- raise ConnectionError.new("Could not connect to TA server, with error \"#{e.message}\".")
40
+ raise ConnectionError.new("Could not connect to TE server, with error \"#{e.message}\".")
35
41
  end
36
42
 
37
43
  result = {}
@@ -39,17 +45,17 @@ module TDAnalytics
39
45
  begin
40
46
  result = JSON.parse(response_body.to_s)
41
47
  rescue JSON::JSONError
42
- raise ServerError.new("Could not interpret TA server response: '#{response_body}'")
48
+ raise ServerError.new("Could not interpret TE server response: '#{response_body}'")
43
49
  end
44
50
  end
45
51
 
46
52
  if result['errorLevel'] != 0
47
- raise ServerError.new("Could not write to TA, server responded with #{response_code} returning: '#{response_body}'")
53
+ raise ServerError.new("Could not write to TE, server responded with #{response_code} returning: '#{response_body}'")
48
54
  end
49
55
  end
50
56
 
51
57
  def request(uri, form_data,headers)
52
- request = Net::HTTP::Post.new(uri.request_uri,headers)
58
+ request = Net::HTTP::Post.new(uri.request_uri, headers)
53
59
  request.set_form_data(form_data)
54
60
 
55
61
  client = Net::HTTP.new(uri.host, uri.port)
@@ -1,17 +1,25 @@
1
- module TDAnalytics
2
-
1
+ module ThinkingData
2
+ ##
3
+ # SDK error
3
4
  TDAnalyticsError = Class.new(StandardError)
4
5
 
6
+ ##
7
+ # SDK error: illegal parameter
5
8
  IllegalParameterError = Class.new(TDAnalyticsError)
6
-
9
+
10
+ ##
11
+ # SDK error: connection error
7
12
  ConnectionError = Class.new(TDAnalyticsError)
8
-
9
- ServerError = Class.new(TDAnalyticsError)
10
13
 
14
+ ##
15
+ # SDK error: server error
16
+ ServerError = Class.new(TDAnalyticsError)
11
17
 
12
- # use example:
18
+ ##
19
+ # Error handler
13
20
  #
14
- # class MyErrorHandler < TDAnalytics::ErrorHandler
21
+ # e.g.
22
+ # class MyErrorHandler < ThinkingData::ErrorHandler
15
23
  # def handle(error)
16
24
  # puts error
17
25
  # raise error
@@ -19,9 +27,9 @@ module TDAnalytics
19
27
  # end
20
28
  #
21
29
  # my_error_handler = MyErrorHandler.new
22
- # tracker = TDAnalytics::Tracker.new(consumer, my_error_handler)
23
- class ErrorHandler
24
-
30
+ # tracker = ThinkingData::TDAnalytics.new(consumer, my_error_handler)
31
+ class TDErrorHandler
32
+ ##
25
33
  # Override #handle to customize error handling
26
34
  def handle(error)
27
35
  false
@@ -1,12 +1,13 @@
1
1
  require 'logger'
2
- require 'thinkingdata-ruby/errors'
2
+ require 'thinkingdata-ruby/td_errors'
3
3
 
4
- module TDAnalytics
4
+ module ThinkingData
5
5
 
6
- # dismantle the header and save it under another name
6
+ ##
7
+ # Dismantle the header and save it under another name
7
8
  class HeadlessLogger < Logger
8
9
  def initialize(logdev, shift_age = 0, shift_size = 1048576)
9
- super(nil )
10
+ super(nil)
10
11
  if logdev
11
12
  @logdev = HeadlessLogger::LogDevice.new(logdev, shift_age: shift_age, shift_size: shift_size)
12
13
  end
@@ -17,9 +18,15 @@ module TDAnalytics
17
18
  end
18
19
  end
19
20
 
20
- # write data to file, it works with LogBus
21
- class LoggerConsumer
21
+ ##
22
+ # Write data to file, it works with LogBus
23
+ class TDLoggerConsumer
22
24
 
25
+ ##
26
+ # Init logger consumer
27
+ # @param log_path: log file's path
28
+ # @param mode: file rotate mode
29
+ # @param prefix: file prefix
23
30
  def initialize(log_path='.', mode='daily', prefix:'te.log')
24
31
  case mode
25
32
  when 'hourly'
@@ -35,20 +42,34 @@ module TDAnalytics
35
42
  @current_suffix = Time.now.strftime(@suffix_mode)
36
43
  @log_path = log_path
37
44
  @full_prefix = "#{log_path}/#{prefix}"
45
+ @mutex = Mutex.new
46
+ TDLog.info("TDLoggerConsumer init success. LogPath: #{log_path}")
38
47
  _reset
39
48
  end
40
49
 
41
50
  def add(msg)
42
- unless Time.now.strftime(@suffix_mode) == @current_suffix
43
- @logger.close
44
- @current_suffix = Time.now.strftime(@suffix_mode)
45
- _reset
51
+ @mutex.synchronize do
52
+ unless Time.now.strftime(@suffix_mode) == @current_suffix
53
+ @logger.close
54
+ @current_suffix = Time.now.strftime(@suffix_mode)
55
+ _reset
56
+ end
57
+ msg_json_str = msg.to_json
58
+ TDLog.info("Write data to file: #{msg_json_str}")
59
+ @logger.info(msg_json_str)
46
60
  end
47
- @logger.info(msg.to_json)
48
61
  end
49
62
 
63
+ def flush
64
+ # Logger writes immediately on each call, no explicit flush needed
65
+ TDLog.info("TDLoggerConsumer flush.")
66
+ end
67
+
50
68
  def close
51
- @logger.close
69
+ @mutex.synchronize do
70
+ @logger.close
71
+ end
72
+ TDLog.info("TDLoggerConsumer close.")
52
73
  end
53
74
 
54
75
  private
@@ -0,0 +1,3 @@
1
+ module ThinkingData
2
+ VERSION = '2.0.1'
3
+ end
@@ -1,5 +1,5 @@
1
- require 'thinkingdata-ruby/logger_consumer'
2
- require 'thinkingdata-ruby/debug_consumer'
3
- require 'thinkingdata-ruby/batch_consumer'
4
- require 'thinkingdata-ruby/tracker'
5
- require 'thinkingdata-ruby/errors'
1
+ require 'thinkingdata-ruby/td_logger_consumer'
2
+ require 'thinkingdata-ruby/td_debug_consumer'
3
+ require 'thinkingdata-ruby/td_batch_consumer'
4
+ require 'thinkingdata-ruby/td_analytics'
5
+ require 'thinkingdata-ruby/td_errors'
@@ -1,8 +1,8 @@
1
- require File.join(File.dirname(__FILE__), 'lib/thinkingdata-ruby/version.rb')
1
+ require File.join(File.dirname(__FILE__), 'lib/thinkingdata-ruby/td_version.rb')
2
2
 
3
3
  spec = Gem::Specification.new do |spec|
4
4
  spec.name = 'thinkingdata-ruby'
5
- spec.version = TDAnalytics::VERSION
5
+ spec.version = ThinkingData::VERSION
6
6
  spec.files = Dir.glob(`git ls-files`.split("\n"))
7
7
  spec.require_paths = ['lib']
8
8
  spec.summary = 'Official ThinkingData Analytics API for ruby'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: thinkingdata-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - ThinkingData
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-03-21 00:00:00.000000000 Z
11
+ date: 2026-05-14 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: The official ThinkingData Analytics API for ruby
14
14
  email: sdk@thinkingdata.cn
@@ -23,12 +23,12 @@ files:
23
23
  - README.md
24
24
  - demo/demo.rb
25
25
  - lib/thinkingdata-ruby.rb
26
- - lib/thinkingdata-ruby/batch_consumer.rb
27
- - lib/thinkingdata-ruby/debug_consumer.rb
28
- - lib/thinkingdata-ruby/errors.rb
29
- - lib/thinkingdata-ruby/logger_consumer.rb
30
- - lib/thinkingdata-ruby/tracker.rb
31
- - lib/thinkingdata-ruby/version.rb
26
+ - lib/thinkingdata-ruby/td_analytics.rb
27
+ - lib/thinkingdata-ruby/td_batch_consumer.rb
28
+ - lib/thinkingdata-ruby/td_debug_consumer.rb
29
+ - lib/thinkingdata-ruby/td_errors.rb
30
+ - lib/thinkingdata-ruby/td_logger_consumer.rb
31
+ - lib/thinkingdata-ruby/td_version.rb
32
32
  - thinkingdata-ruby.gemspec
33
33
  homepage: https://github.com/ThinkingDataAnalytics/ruby-sdk
34
34
  licenses:
@@ -49,7 +49,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
49
49
  - !ruby/object:Gem::Version
50
50
  version: '0'
51
51
  requirements: []
52
- rubygems_version: 3.0.9
52
+ rubygems_version: 3.0.3.1
53
53
  signing_key:
54
54
  specification_version: 4
55
55
  summary: Official ThinkingData Analytics API for ruby
@@ -1,3 +0,0 @@
1
- module TDAnalytics
2
- VERSION = '1.2.1'
3
- end