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,118 +1,142 @@
1
- require 'json'
2
- require 'net/http'
3
-
4
- module TDAnalytics
5
- class BatchConsumer
6
-
7
- # buffer count
8
- DEFAULT_LENGTH = 20
9
- MAX_LENGTH = 2000
10
-
11
- def initialize(server_url, app_id, max_buffer_length = DEFAULT_LENGTH)
12
- @server_uri = URI.parse(server_url)
13
- @server_uri.path = '/sync_server'
14
- @app_id = app_id
15
- @compress = true
16
- @max_length = [max_buffer_length, MAX_LENGTH].min
17
- @buffers = []
18
- end
19
-
20
- def _set_compress(compress)
21
- @compress = compress
22
- end
23
-
24
- def add(message)
25
- @buffers << message
26
- flush if @buffers.length >= @max_length
27
- end
28
-
29
- def close
30
- flush
31
- end
32
-
33
- def flush
34
- begin
35
- @buffers.each_slice(@max_length) do |chunk|
36
- if @compress
37
- wio = StringIO.new("w")
38
- gzip_io = Zlib::GzipWriter.new(wio)
39
- gzip_io.write(chunk.to_json)
40
- gzip_io.close
41
- data = wio.string
42
- else
43
- data = chunk.to_json
44
- end
45
- compress_type = @compress ? 'gzip' : 'none'
46
- headers = {'Content-Type' => 'application/plaintext',
47
- 'appid' => @app_id,
48
- 'compress' => compress_type,
49
- 'TA-Integration-Type'=>'Ruby',
50
- 'TA-Integration-Version'=>TDAnalytics::VERSION,
51
- 'TA-Integration-Count'=>@buffers.count,
52
- 'TA_Integration-Extra'=>'batch'}
53
- request = CaseSensitivePost.new(@server_uri.request_uri, headers)
54
- request.body = data
55
-
56
- begin
57
- response_code, response_body = _request(@server_uri, request)
58
- rescue => e
59
- raise ConnectionError.new("Could not connect to TA server, with error \"#{e.message}\".")
60
- end
61
-
62
- result = {}
63
- if response_code.to_i == 200
64
- begin
65
- result = JSON.parse(response_body.to_s)
66
- rescue JSON::JSONError
67
- raise ServerError.new("Could not interpret TA server response: '#{response_body}'")
68
- end
69
- end
70
-
71
- if result['code'] != 0
72
- raise ServerError.new("Could not write to TA, server responded with #{response_code} returning: '#{response_body}'")
73
- end
74
- end
75
- rescue
76
- raise
77
- end
78
- @buffers = []
79
- end
80
-
81
- private
82
- def _request(uri, request)
83
- client = Net::HTTP.new(uri.host, uri.port)
84
- client.use_ssl = uri.scheme === 'https' ? true : false
85
- client.open_timeout = 10
86
- client.continue_timeout = 10
87
- client.read_timeout = 10
88
- client.ssl_timeout = 10
89
-
90
- response = client.request(request)
91
- [response.code, response.body]
92
- end
93
- end
94
-
95
- class CaseSensitivePost < Net::HTTP::Post
96
- def initialize_http_header(headers)
97
- @header = {}
98
- headers.each{|k,v| @header[k.to_s] = [v] }
99
- end
100
-
101
- def [](name)
102
- @header[name.to_s]
103
- end
104
-
105
- def []=(name, val)
106
- if val
107
- @header[name.to_s] = [val]
108
- else
109
- @header.delete(name.to_s)
110
- end
111
- end
112
-
113
- def capitalize(name)
114
- name
115
- end
116
- end
117
-
118
- end
1
+ require 'json'
2
+ require 'net/http'
3
+ require 'stringio'
4
+
5
+ module ThinkingData
6
+ ##
7
+ # Upload data by http
8
+ class TDBatchConsumer
9
+
10
+ # buffer count
11
+ DEFAULT_LENGTH = 20
12
+ MAX_LENGTH = 2000
13
+
14
+ ##
15
+ # Init batch consumer
16
+ def initialize(server_url, app_id, max_buffer_length = DEFAULT_LENGTH)
17
+ @server_uri = URI.parse(server_url)
18
+ @server_uri.path = '/sync_server'
19
+ @app_id = app_id
20
+ @compress = true
21
+ @max_length = [max_buffer_length, MAX_LENGTH].min
22
+ @buffers = []
23
+ TDLog.info("TDBatchConsumer init success. ServerUrl: #{server_url}, appId: #{app_id}")
24
+ end
25
+
26
+ ##
27
+ # http request compress
28
+ # @param compress [Boolean] compress or not
29
+ # @deprecated please use: set_compress
30
+ def _set_compress(compress)
31
+ @compress = compress
32
+ end
33
+
34
+ ##
35
+ # http request compress
36
+ # @param compress [Boolean] compress or not
37
+ def set_compress(compress)
38
+ @compress = compress
39
+ end
40
+
41
+ def add(message)
42
+ TDLog.info("Enqueue data to buffer. buffer size: #{@buffers.length}, data: #{message}")
43
+ @buffers << message
44
+ flush if @buffers.length >= @max_length
45
+ end
46
+
47
+ def close
48
+ flush
49
+ TDLog.info("TDBatchConsumer close.")
50
+ end
51
+
52
+ def flush
53
+ TDLog.info("TDBatchConsumer flush data.")
54
+ begin
55
+ @buffers.each_slice(@max_length) do |chunk|
56
+ if @compress
57
+ wio = StringIO.new("w")
58
+ gzip_io = Zlib::GzipWriter.new(wio)
59
+ gzip_io.write(chunk.to_json)
60
+ gzip_io.close
61
+ data = wio.string
62
+ else
63
+ data = chunk.to_json
64
+ end
65
+ compress_type = @compress ? 'gzip' : 'none'
66
+ headers = {'Content-Type' => 'application/plaintext',
67
+ 'appid' => @app_id,
68
+ 'compress' => compress_type,
69
+ 'TE-Integration-Type'=>'Ruby',
70
+ 'TE-Integration-Version'=>ThinkingData::VERSION,
71
+ 'TE-Integration-Count'=>@buffers.count,
72
+ 'TA_Integration-Extra'=>'batch'}
73
+ request = CaseSensitivePost.new(@server_uri.request_uri, headers)
74
+ request.body = data
75
+
76
+ TDLog.info("Send data, request: #{data}")
77
+ begin
78
+ response_code, response_body = _request(@server_uri, request)
79
+ TDLog.info("Send data, response: #{response_body}")
80
+ rescue => e
81
+ raise ConnectionError.new("Could not connect to TE server, with error \"#{e.message}\".")
82
+ end
83
+
84
+ result = {}
85
+ if response_code.to_i == 200
86
+ begin
87
+ result = JSON.parse(response_body.to_s)
88
+ rescue JSON::JSONError
89
+ raise ServerError.new("Could not interpret TE server response: '#{response_body}'")
90
+ end
91
+ end
92
+
93
+ if result['code'] != 0
94
+ raise ServerError.new("Could not write to TE, server responded with #{response_code} returning: '#{response_body}'")
95
+ end
96
+ end
97
+ rescue
98
+ raise
99
+ end
100
+ @buffers = []
101
+ end
102
+
103
+ private
104
+ def _request(uri, request)
105
+ client = Net::HTTP.new(uri.host, uri.port)
106
+ client.use_ssl = uri.scheme === 'https' ? true : false
107
+ client.open_timeout = 10
108
+ client.continue_timeout = 10
109
+ client.read_timeout = 10
110
+ client.ssl_timeout = 10
111
+
112
+ response = client.request(request)
113
+ [response.code, response.body]
114
+ end
115
+ end
116
+
117
+ ##
118
+ # Private class. Send data tools
119
+ class CaseSensitivePost < Net::HTTP::Post
120
+ def initialize_http_header(headers)
121
+ @header = {}
122
+ headers.each{|k,v| @header[k.to_s] = [v] }
123
+ end
124
+
125
+ def [](name)
126
+ @header[name.to_s]
127
+ end
128
+
129
+ def []=(name, val)
130
+ if val
131
+ @header[name.to_s] = [val]
132
+ else
133
+ @header.delete(name.to_s)
134
+ end
135
+ end
136
+
137
+ def capitalize(name)
138
+ name
139
+ end
140
+ end
141
+
142
+ end
@@ -1,67 +1,73 @@
1
- require 'json'
2
- require 'net/http'
3
-
4
- module TDAnalytics
5
- # 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
11
-
12
- def initialize(server_url, app_id, write_data = true, device_id: nil)
13
- @server_uri = URI.parse(server_url)
14
- @server_uri.path = '/data_debug'
15
- @app_id = app_id
16
- @write_data = write_data
17
- @device_id = device_id
18
- end
19
-
20
- def add(message)
21
- puts message.to_json
22
- headers = {
23
- 'TA-Integration-Type'=>'Ruby',
24
- 'TA-Integration-Version'=>TDAnalytics::VERSION,
25
- 'TA-Integration-Count'=>'1',
26
- 'TA_Integration-Extra'=>'debug'
27
- }
28
- form_data = {"data" => message.to_json, "appid" => @app_id, "dryRun" => @write_data ? "0" : "1", "source" => "server"}
29
- @device_id.is_a?(String) ? form_data["deviceId"] = @device_id : nil
30
-
31
- begin
32
- response_code, response_body = request(@server_uri, form_data,headers)
33
- rescue => e
34
- raise ConnectionError.new("Could not connect to TA server, with error \"#{e.message}\".")
35
- end
36
-
37
- result = {}
38
- if response_code.to_i == 200
39
- begin
40
- result = JSON.parse(response_body.to_s)
41
- rescue JSON::JSONError
42
- raise ServerError.new("Could not interpret TA server response: '#{response_body}'")
43
- end
44
- end
45
-
46
- if result['errorLevel'] != 0
47
- raise ServerError.new("Could not write to TA, server responded with #{response_code} returning: '#{response_body}'")
48
- end
49
- end
50
-
51
- def request(uri, form_data,headers)
52
- request = Net::HTTP::Post.new(uri.request_uri,headers)
53
- request.set_form_data(form_data)
54
-
55
- client = Net::HTTP.new(uri.host, uri.port)
56
- client.use_ssl = uri.scheme === 'https' ? true : false
57
- client.open_timeout = 10
58
- client.continue_timeout = 10
59
- client.read_timeout = 10
60
- client.ssl_timeout = 10
61
-
62
- response = client.request(request)
63
- [response.code, response.body]
64
- end
65
- end
66
-
67
- end
1
+ require 'json'
2
+ require 'net/http'
3
+
4
+ module ThinkingData
5
+ ##
6
+ # The data is reported one by one, and when an error occurs, the log will be printed on the console.
7
+ class TDDebugConsumer
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
15
+ def initialize(server_url, app_id, write_data = true, device_id: nil)
16
+ @server_uri = URI.parse(server_url)
17
+ @server_uri.path = '/data_debug'
18
+ @app_id = app_id
19
+ @write_data = write_data
20
+ @device_id = device_id
21
+ TDLog.info("TDDebugConsumer init success. ServerUrl: #{server_url}, appId: #{app_id}, deviceId: #{device_id}")
22
+ end
23
+
24
+ def add(message)
25
+ msg_json_str = message.to_json
26
+ TDLog.info("Send data, request: #{msg_json_str}")
27
+ headers = {
28
+ 'TE-Integration-Type'=>'Ruby',
29
+ 'TE-Integration-Version'=>ThinkingData::VERSION,
30
+ 'TE-Integration-Count'=>'1',
31
+ 'TA_Integration-Extra'=>'debug'
32
+ }
33
+ form_data = {"data" => msg_json_str, "appid" => @app_id, "dryRun" => @write_data ? "0" : "1", "source" => "server"}
34
+ @device_id.is_a?(String) ? form_data["deviceId"] = @device_id : nil
35
+
36
+ begin
37
+ response_code, response_body = request(@server_uri, form_data,headers)
38
+ TDLog.info("Send data, response: #{response_body}")
39
+ rescue => e
40
+ raise ConnectionError.new("Could not connect to TE server, with error \"#{e.message}\".")
41
+ end
42
+
43
+ result = {}
44
+ if response_code.to_i == 200
45
+ begin
46
+ result = JSON.parse(response_body.to_s)
47
+ rescue JSON::JSONError
48
+ raise ServerError.new("Could not interpret TE server response: '#{response_body}'")
49
+ end
50
+ end
51
+
52
+ if result['errorLevel'] != 0
53
+ raise ServerError.new("Could not write to TE, server responded with #{response_code} returning: '#{response_body}'")
54
+ end
55
+ end
56
+
57
+ def request(uri, form_data,headers)
58
+ request = Net::HTTP::Post.new(uri.request_uri, headers)
59
+ request.set_form_data(form_data)
60
+
61
+ client = Net::HTTP.new(uri.host, uri.port)
62
+ client.use_ssl = uri.scheme === 'https' ? true : false
63
+ client.open_timeout = 10
64
+ client.continue_timeout = 10
65
+ client.read_timeout = 10
66
+ client.ssl_timeout = 10
67
+
68
+ response = client.request(request)
69
+ [response.code, response.body]
70
+ end
71
+ end
72
+
73
+ end
@@ -1,30 +1,38 @@
1
- module TDAnalytics
2
-
3
- TDAnalyticsError = Class.new(StandardError)
4
-
5
- IllegalParameterError = Class.new(TDAnalyticsError)
6
-
7
- ConnectionError = Class.new(TDAnalyticsError)
8
-
9
- ServerError = Class.new(TDAnalyticsError)
10
-
11
-
12
- # use example:
13
- #
14
- # class MyErrorHandler < TDAnalytics::ErrorHandler
15
- # def handle(error)
16
- # puts error
17
- # raise error
18
- # end
19
- # end
20
- #
21
- # my_error_handler = MyErrorHandler.new
22
- # tracker = TDAnalytics::Tracker.new(consumer, my_error_handler)
23
- class ErrorHandler
24
-
25
- # Override #handle to customize error handling
26
- def handle(error)
27
- false
28
- end
29
- end
1
+ module ThinkingData
2
+ ##
3
+ # SDK error
4
+ TDAnalyticsError = Class.new(StandardError)
5
+
6
+ ##
7
+ # SDK error: illegal parameter
8
+ IllegalParameterError = Class.new(TDAnalyticsError)
9
+
10
+ ##
11
+ # SDK error: connection error
12
+ ConnectionError = Class.new(TDAnalyticsError)
13
+
14
+ ##
15
+ # SDK error: server error
16
+ ServerError = Class.new(TDAnalyticsError)
17
+
18
+ ##
19
+ # Error handler
20
+ #
21
+ # e.g.
22
+ # class MyErrorHandler < ThinkingData::ErrorHandler
23
+ # def handle(error)
24
+ # puts error
25
+ # raise error
26
+ # end
27
+ # end
28
+ #
29
+ # my_error_handler = MyErrorHandler.new
30
+ # tracker = ThinkingData::TDAnalytics.new(consumer, my_error_handler)
31
+ class TDErrorHandler
32
+ ##
33
+ # Override #handle to customize error handling
34
+ def handle(error)
35
+ false
36
+ end
37
+ end
30
38
  end
@@ -1,66 +1,77 @@
1
- require 'logger'
2
- require 'thinkingdata-ruby/errors'
3
-
4
- module TDAnalytics
5
-
6
- # dismantle the header and save it under another name
7
- class HeadlessLogger < Logger
8
- def initialize(logdev, shift_age = 0, shift_size = 1048576)
9
- super(nil )
10
- if logdev
11
- @logdev = HeadlessLogger::LogDevice.new(logdev, shift_age: shift_age, shift_size: shift_size)
12
- end
13
- end
14
-
15
- class LogDevice < ::Logger::LogDevice
16
- def add_log_header(file); end
17
- end
18
- end
19
-
20
- # write data to file, it works with LogBus
21
- class LoggerConsumer
22
-
23
- def initialize(log_path='.', mode='daily', prefix:'te.log')
24
- case mode
25
- when 'hourly'
26
- @suffix_mode = '%Y-%m-%d-%H'
27
- when 'daily'
28
- @suffix_mode = '%Y-%m-%d'
29
- else
30
- raise IllegalParameterError.new("#{mode} is unsupported for LoggerConsumer. Replaced it by daily or hourly")
31
- end
32
-
33
- raise IllegalParameterError.new("prefix couldn't be empty") if prefix.nil? || prefix.length == 0
34
-
35
- @current_suffix = Time.now.strftime(@suffix_mode)
36
- @log_path = log_path
37
- @full_prefix = "#{log_path}/#{prefix}"
38
- _reset
39
- end
40
-
41
- 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
46
- end
47
- @logger.info(msg.to_json)
48
- end
49
-
50
- def close
51
- @logger.close
52
- end
53
-
54
- private
55
-
56
- def _reset
57
- Dir::mkdir(@log_path) unless Dir::exist?(@log_path)
58
- @logger = HeadlessLogger.new("#{@full_prefix}.#{@current_suffix}")
59
- @logger.level = HeadlessLogger::INFO
60
- @logger.formatter = proc do |severity, datetime, progname, msg|
61
- "#{msg}\n"
62
- end
63
- end
64
-
65
- end
1
+ require 'logger'
2
+ require 'thinkingdata-ruby/td_errors'
3
+
4
+ module ThinkingData
5
+
6
+ ##
7
+ # Dismantle the header and save it under another name
8
+ class HeadlessLogger < Logger
9
+ def initialize(logdev, shift_age = 0, shift_size = 1048576)
10
+ super(nil)
11
+ if logdev
12
+ @logdev = HeadlessLogger::LogDevice.new(logdev, shift_age: shift_age, shift_size: shift_size)
13
+ end
14
+ end
15
+
16
+ class LogDevice < ::Logger::LogDevice
17
+ def add_log_header(file); end
18
+ end
19
+ end
20
+
21
+ ##
22
+ # Write data to file, it works with LogBus
23
+ class TDLoggerConsumer
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
30
+ def initialize(log_path='.', mode='daily', prefix:'te.log')
31
+ case mode
32
+ when 'hourly'
33
+ @suffix_mode = '%Y-%m-%d-%H'
34
+ when 'daily'
35
+ @suffix_mode = '%Y-%m-%d'
36
+ else
37
+ raise IllegalParameterError.new("#{mode} is unsupported for LoggerConsumer. Replaced it by daily or hourly")
38
+ end
39
+
40
+ raise IllegalParameterError.new("prefix couldn't be empty") if prefix.nil? || prefix.length == 0
41
+
42
+ @current_suffix = Time.now.strftime(@suffix_mode)
43
+ @log_path = log_path
44
+ @full_prefix = "#{log_path}/#{prefix}"
45
+ TDLog.info("TDLoggerConsumer init success. LogPath: #{log_path}")
46
+ _reset
47
+ end
48
+
49
+ def add(msg)
50
+ unless Time.now.strftime(@suffix_mode) == @current_suffix
51
+ @logger.close
52
+ @current_suffix = Time.now.strftime(@suffix_mode)
53
+ _reset
54
+ end
55
+ msg_json_str = msg.to_json
56
+ TDLog.info("Write data to file: #{msg_json_str}")
57
+ @logger.info(msg_json_str)
58
+ end
59
+
60
+ def close
61
+ @logger.close
62
+ TDLog.info("TDLoggerConsumer close.")
63
+ end
64
+
65
+ private
66
+
67
+ def _reset
68
+ Dir::mkdir(@log_path) unless Dir::exist?(@log_path)
69
+ @logger = HeadlessLogger.new("#{@full_prefix}.#{@current_suffix}")
70
+ @logger.level = HeadlessLogger::INFO
71
+ @logger.formatter = proc do |severity, datetime, progname, msg|
72
+ "#{msg}\n"
73
+ end
74
+ end
75
+
76
+ end
66
77
  end
@@ -0,0 +1,3 @@
1
+ module ThinkingData
2
+ VERSION = '2.0.0'
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'