thinkingdata-ruby 1.2.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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'