aliyun-log 0.1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 0af7f849c9e5e9e6d59647f4b184c994977407f5b970f5d867505062401621c7
4
+ data.tar.gz: bfd3fafdac4839ac11d428638d44d15a4126d283195ddd6e5b033238f3e7b034
5
+ SHA512:
6
+ metadata.gz: 033ae7fd59ab6e49b40c071942f289623226ca9a506f88cec0eafdce2edabcc56c5b2daecd7f7c8a6e27df39c11ebf62deab06c3d11b175c4b1f7eeef5284f5f
7
+ data.tar.gz: f31dc59e00955ecc7b0f6682356005b7ea2b872527818ea352418a99ddd81a8d3b0fd4d66f7fbda9c92073d9e8d51eca38b7af11364f2bf2d359ad565ac0299b
@@ -0,0 +1,18 @@
1
+ #
2
+ require_relative 'log/common'
3
+ require_relative 'log/client'
4
+ require_relative 'log/config'
5
+ require_relative 'log/logstore'
6
+ require_relative 'log/project'
7
+ require_relative 'log/protobuf'
8
+ require_relative 'log/protocol'
9
+ require_relative 'log/request'
10
+ require_relative 'log/server_error'
11
+
12
+ module Aliyun
13
+ module Log
14
+ def self.configure
15
+ block_given? ? yield(Config) : Config
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,30 @@
1
+ module Aliyun
2
+ module Log
3
+ class Client
4
+ def initialize(config = {})
5
+ @config = Config.new(config)
6
+ @protocol = Protocol.new(@config)
7
+ end
8
+
9
+ def list_projects(size = nil, offset = nil)
10
+ @protocol.list_projects(size, offset)
11
+ end
12
+
13
+ def get_project(name)
14
+ @protocol.get_project(name)
15
+ end
16
+
17
+ def create_project(name, desc)
18
+ @protocol.create_project(name, desc)
19
+ end
20
+
21
+ def update_project(name, desc)
22
+ @protocol.update_project(name, desc)
23
+ end
24
+
25
+ def delete_project(name)
26
+ @protocol.delete_project(name)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,3 @@
1
+ #
2
+ require_relative 'common/attr_struct'
3
+ require_relative 'common/logging'
@@ -0,0 +1,32 @@
1
+ module Aliyun
2
+ module Log
3
+ module Common
4
+ class AttrStruct
5
+ module AttrHelper
6
+ def attrs(*name)
7
+ define_method(:attrs) { name }
8
+ attr_reader(*name)
9
+ end
10
+ end
11
+
12
+ extend AttrHelper
13
+
14
+ def initialize(opts = {})
15
+ extra_keys = opts.keys - attrs
16
+ raise "Unexpected extra keys: #{extra_keys.join(', ')}" unless extra_keys.empty?
17
+
18
+ attrs.each do |attr|
19
+ instance_variable_set("@#{attr}", opts[attr])
20
+ end
21
+ end
22
+
23
+ def to_s
24
+ attrs.map do |attr|
25
+ v = instance_variable_get("@#{attr}")
26
+ "#{attr}: #{v}"
27
+ end.join(', ')
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,33 @@
1
+ require 'logger'
2
+
3
+ module Aliyun
4
+ module Log
5
+ module Common
6
+ module Logging
7
+ # DEFAULT_LOG_FILE = './log/aliyun_log.log'.freeze
8
+ DEFAULT_LOG_FILE = STDOUT
9
+ MAX_NUM_LOG = 100
10
+ ROTATE_SIZE = 10 * 1024 * 1024
11
+
12
+ def logger
13
+ Logging.logger
14
+ end
15
+
16
+ # level = Logger::DEBUG | Logger::INFO | Logger::ERROR | Logger::FATAL
17
+ def self.log_level=(level)
18
+ Logging.logger.level = level
19
+ end
20
+
21
+ def self.logger
22
+ unless @logger
23
+ @logger = Logger.new(
24
+ @log_file ||= DEFAULT_LOG_FILE, MAX_NUM_LOG, ROTATE_SIZE
25
+ )
26
+ @logger.level = Logger::DEBUG
27
+ end
28
+ @logger
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,43 @@
1
+ module Aliyun
2
+ module Log
3
+ class Config < Common::AttrStruct
4
+ @endpoint = 'https://cn-beijing.log.aliyuncs.com'
5
+ @open_timeout = 10
6
+ @read_timeout = 120
7
+ class << self
8
+ attr_accessor :endpoint, :access_key_id, :access_key_secret,
9
+ :open_timeout, :read_timeout
10
+
11
+ def configure
12
+ yield self
13
+ end
14
+ end
15
+
16
+ attrs :endpoint, :access_key_id, :access_key_secret,
17
+ :open_timeout, :read_timeout
18
+
19
+ def initialize(opts = {})
20
+ super(opts)
21
+ @open_timeout ||= self.class.open_timeout
22
+ @read_timeout ||= self.class.read_timeout
23
+ @access_key_id ||= self.class.access_key_id
24
+ @access_key_secret ||= self.class.access_key_secret
25
+ @endpoint ||= self.class.endpoint
26
+ normalize_endpoint
27
+ end
28
+
29
+ private
30
+
31
+ def normalize_endpoint
32
+ uri = URI.parse(endpoint)
33
+ uri = URI.parse("http://#{endpoint}") unless uri.scheme
34
+
35
+ if (uri.scheme != 'http') && (uri.scheme != 'https')
36
+ raise 'Only HTTP and HTTPS endpoint are accepted.'
37
+ end
38
+
39
+ @endpoint = uri.to_s
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,74 @@
1
+ module Aliyun
2
+ module Log
3
+ class Logstore < Common::AttrStruct
4
+
5
+ attrs :name, :project_name, :ttl, :shared_count, :enable_tracking,
6
+ :auto_split, :max_split_shard, :create_time, :last_modify_time
7
+
8
+ def initialize(opts, protocol)
9
+ super(opts)
10
+ @protocol = protocol
11
+ end
12
+
13
+ def self.from_json(attrs, protocol)
14
+ new({
15
+ name: attrs['logstoreName'],
16
+ project_name: attrs['projectName'],
17
+ ttl: attrs['ttl'],
18
+ shared_count: attrs['shardCount'],
19
+ enable_tracking: attrs['enable_tracking'],
20
+ auto_split: attrs['autoSplit'],
21
+ max_split_shard: attrs['maxSplitShard'],
22
+ create_time: attrs['createTime'],
23
+ last_modify_time: attrs['lastModifyTime']
24
+ }, protocol)
25
+ end
26
+
27
+ def put_logs(content)
28
+ @protocol.put_logs(project_name, name, content)
29
+ end
30
+
31
+ def put_log(attributes)
32
+ contents = attributes.map { |k, v| { key: k.to_s, value: v.to_s } }
33
+ log = Aliyun::Log::Protobuf::Log.new(
34
+ time: Time.now.to_i,
35
+ contents: contents
36
+ )
37
+ log_group = Aliyun::Log::Protobuf::LogGroup.new(logs: [log])
38
+ put_logs(log_group)
39
+ end
40
+
41
+ def get_logs(opts = {})
42
+ @protocol.get_logs(project_name, name, opts)
43
+ end
44
+
45
+ def get_histograms(opts = {})
46
+ @protocol.get_histograms(project_name, name, opts)
47
+ end
48
+
49
+ def list_topics(opts = {})
50
+ @protocol.list_topics(project_name, name, opts)
51
+ end
52
+
53
+ def get_index
54
+ @protocol.get_index(project_name, name)
55
+ end
56
+
57
+ def create_index_line(token = nil)
58
+ @protocol.create_index_line(project_name, name, token)
59
+ end
60
+
61
+ def create_index(fields)
62
+ @protocol.create_index(project_name, name, fields)
63
+ end
64
+
65
+ def update_index(fields)
66
+ @protocol.update_index(project_name, name, fields)
67
+ end
68
+
69
+ def delete_index
70
+ @protocol.delete_index(project_name, name)
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,45 @@
1
+ module Aliyun
2
+ module Log
3
+ class Project < Common::AttrStruct
4
+ attrs :create_time, :description, :last_modify_time,
5
+ :owner, :name, :region, :status
6
+
7
+ def initialize(opts, protocol)
8
+ super(opts)
9
+ @protocol = protocol
10
+ end
11
+
12
+ def self.from_json(attrs, protocol)
13
+ new({
14
+ create_time: attrs['createTime'],
15
+ description: attrs['description'],
16
+ last_modify_time: attrs['lastModifyTime'],
17
+ owner: attrs['owner'],
18
+ name: attrs['projectName'],
19
+ region: attrs['region'],
20
+ status: attrs['status']
21
+ }, protocol)
22
+ end
23
+
24
+ def list_logstores(size = nil, offset = nil)
25
+ @protocol.list_logstores(name, size, offset)
26
+ end
27
+
28
+ def get_logstore(logstore_name)
29
+ @protocol.get_logstore(name, logstore_name)
30
+ end
31
+
32
+ def create_logstore(logstore_name, opt = {})
33
+ @protocol.create_logstore(name, logstore_name, opt)
34
+ end
35
+
36
+ def update_logstore(logstore_name)
37
+ @protocol.update_logstore(name, logstore_name)
38
+ end
39
+
40
+ def delete_logstore(logstore_name)
41
+ @protocol.delete_logstore(name, logstore_name)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,25 @@
1
+ require 'protobuf'
2
+
3
+ module Aliyun
4
+ module Log
5
+ module Protobuf
6
+ class Log < ::Protobuf::Message
7
+ required :uint32, :time, 1
8
+
9
+ class Content < ::Protobuf::Message
10
+ required :string, :key, 1
11
+ required :string, :value, 2
12
+ end
13
+
14
+ repeated Content, :contents, 2
15
+ end
16
+
17
+ class LogGroup < ::Protobuf::Message
18
+ repeated Log, :logs, 1
19
+ optional :string, :reserved, 2
20
+ optional :string, :topic, 3
21
+ optional :string, :source, 4
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,203 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module Aliyun
6
+ module Log
7
+ class Protocol
8
+ def initialize(config)
9
+ @http = Request.new(config)
10
+ end
11
+
12
+ def list_projects(size = nil, offset = nil)
13
+ query = {
14
+ offset: offset,
15
+ size: size
16
+ }.compact
17
+ data = @http.get(nil, query)
18
+ data = JSON.parse(data)
19
+ data['projects'] = data['projects'].map do |attrs|
20
+ Project.from_json(attrs, self)
21
+ end
22
+ data
23
+ end
24
+
25
+ def get_project(project_name)
26
+ query = { projectName: project_name }
27
+ attrs = @http.get({ project: project_name }, query)
28
+ attrs = JSON.parse(attrs)
29
+ Project.from_json(attrs, self)
30
+ end
31
+
32
+ def create_project(project_name, desc)
33
+ body = {
34
+ projectName: project_name,
35
+ description: desc
36
+ }
37
+ @http.post({ project: project_name }, body.to_json)
38
+ end
39
+
40
+ def update_project(project_name, desc)
41
+ body = {
42
+ projectName: project_name,
43
+ description: desc
44
+ }
45
+ @http.put({ project: project_name }, body.to_json)
46
+ end
47
+
48
+ def delete_project(project_name)
49
+ body = { projectName: project_name }
50
+ @http.delete({ project: project_name }, body.to_json)
51
+ end
52
+
53
+ def list_logstores(project_name, size = nil, offset = nil)
54
+ query = {
55
+ offset: offset,
56
+ size: size
57
+ }.compact
58
+ data = @http.get({ project: project_name, logstore: '' }, query)
59
+ JSON.parse(data)
60
+ end
61
+
62
+ def create_logstore(project_name, logstore_name, opt = {})
63
+ body = {
64
+ logstore_name: logstore_name,
65
+ ttl: opt[:ttl] || 365,
66
+ shardCount: opt[:shard_count] || 2,
67
+ autoSplit: opt[:auto_split].nil? ? false : opt[:auto_split],
68
+ maxSplitShard: opt[:max_split_shard],
69
+ enable_tracking: opt[:enable_tracking].nil? ? false : opt[:enable_tracking]
70
+ }.compact
71
+ @http.post({ project: project_name, logstore: '' }, body.to_json)
72
+ end
73
+
74
+ def update_logstore(project_name, logstore_name, opt = {})
75
+ body = {
76
+ logstore_name: logstore_name,
77
+ ttl: opt[:ttl] || 365,
78
+ shardCount: opt[:shard_count] || 2,
79
+ autoSplit: opt[:auto_split].nil? ? false : opt[:auto_split],
80
+ maxSplitShard: opt[:max_split_shard],
81
+ enable_tracking: opt[:enable_tracking].nil? ? false : opt[:enable_tracking]
82
+ }.compact
83
+ @http.put({ project: project_name, logstore: logstore_name }, body.to_json)
84
+ end
85
+
86
+ def delete_logstore(project_name, logstore_name)
87
+ body = { logstore_name: logstore_name }
88
+ @http.delete({ project: project_name, logstore: logstore_name }, body.to_json)
89
+ end
90
+
91
+ def get_logstore(project_name, logstore_name)
92
+ query = { logstore_name: logstore_name }
93
+ attrs = @http.get({ project: project_name, logstore: logstore_name }, query)
94
+ attrs = JSON.parse(attrs)
95
+ attrs['projectName'] = project_name
96
+ Logstore.from_json(attrs, self)
97
+ end
98
+
99
+ def put_logs(project_name, logstore_name, content)
100
+ @http.post({ project: project_name, logstore: logstore_name, is_pb: true }, content)
101
+ end
102
+
103
+ def put_log(project_name, logstore_name, log_attr)
104
+ contents = log_attr.compact.map { |k, v| { key: k, value: v } }
105
+ log_pb = Protobuf::Log.new(time: Time.now.to_i, contents: contents)
106
+ lg_pb = Protobuf::LogGroup.new(logs: [log_pb])
107
+ @http.post({ project: project_name, logstore: logstore_name, is_pb: true }, lg_pb)
108
+ end
109
+
110
+ DEFAULT_LOG_TIME_SHIFT = 900
111
+
112
+ def get_logs(project_name, logstore_name, opt = {})
113
+ from = opt[:from] || (Time.now - DEFAULT_LOG_TIME_SHIFT).to_i
114
+ to = opt[:to] || Time.now.to_i
115
+ query = {
116
+ type: 'log',
117
+ from: from,
118
+ to: to,
119
+ line: opt[:line],
120
+ offset: opt[:offset],
121
+ reverse: opt[:reverse],
122
+ query: opt[:query],
123
+ topic: opt[:topic]
124
+ }.compact
125
+ @http.get({ project: project_name, logstore: logstore_name }, query)
126
+ end
127
+
128
+ def get_histograms(project_name, logstore_name, opt = {})
129
+ from = opt[:from] || (Time.now - DEFAULT_LOG_TIME_SHIFT).to_i
130
+ to = opt[:to] || Time.now.to_i
131
+ query = {
132
+ type: 'histogram',
133
+ from: from,
134
+ to: to,
135
+ query: opt[:query],
136
+ topic: opt[:topic]
137
+ }.compact
138
+ @http.get({ project: project_name, logstore: logstore_name }, query)
139
+ end
140
+
141
+ def list_topics(project_name, logstore_name, opt = {})
142
+ query = {
143
+ type: 'topic',
144
+ line: opt[:line] || 100
145
+ }
146
+ @http.get({ project: project_name, logstore: logstore_name }, query)
147
+ end
148
+
149
+ def get_index(project_name, logstore_name)
150
+ query = { logstore_name: logstore_name }
151
+ @http.get({ project: project_name, logstore: logstore_name, action: 'index' }, query)
152
+ end
153
+
154
+ INDEX_DEFAULT_TOKEN = ", '\";=()[]{}?@&<>/:\n\t\r".split('')
155
+
156
+ def create_index_line(project_name, logstore_name, token = nil)
157
+ body = {
158
+ line: {
159
+ token: token || INDEX_DEFAULT_TOKEN
160
+ }
161
+ }
162
+ @http.post({ project: project_name, logstore: logstore_name, action: 'index' }, body.to_json)
163
+ end
164
+
165
+ def create_index(project_name, logstore_name, fields)
166
+ body = {
167
+ line: {
168
+ token: INDEX_DEFAULT_TOKEN
169
+ },
170
+ keys: {}
171
+ }
172
+ fields.each do |k, v|
173
+ body[:keys][k] = v
174
+ if %w[text json].include?(v[:type]) && v[:token].blank?
175
+ v[:token] = INDEX_DEFAULT_TOKEN
176
+ end
177
+ end
178
+ @http.post({ project: project_name, logstore: logstore_name, action: 'index' }, body.to_json)
179
+ end
180
+
181
+ def update_index(project_name, logstore_name, fields)
182
+ body = {
183
+ line: {
184
+ token: INDEX_DEFAULT_TOKEN
185
+ },
186
+ keys: {}
187
+ }
188
+ fields.each do |k, v|
189
+ body[:keys][k] = v
190
+ if v[:type] == 'text' && v[:token].blank?
191
+ v[:token] = INDEX_DEFAULT_TOKEN
192
+ end
193
+ end
194
+ @http.put({ project: project_name, logstore: logstore_name, action: 'index' }, body.to_json)
195
+ end
196
+
197
+ def delete_index(project_name, logstore_name)
198
+ body = { logstore_name: logstore_name }
199
+ @http.delete({ project: project_name, logstore: logstore_name, action: 'index' }, body.to_json)
200
+ end
201
+ end
202
+ end
203
+ end
@@ -0,0 +1,162 @@
1
+ require 'rest-client'
2
+ require 'base64'
3
+ require 'openssl'
4
+ require 'digest'
5
+ require 'date'
6
+ require 'zlib'
7
+
8
+ module Aliyun
9
+ module Log
10
+ class Request
11
+ include Common::Logging
12
+
13
+ def initialize(config)
14
+ @config = config
15
+ end
16
+
17
+ def get_resource_path(resources = {})
18
+ resources ||= {}
19
+ res = '/'
20
+ if resources[:logstore]
21
+ res << 'logstores'
22
+ res << "/#{resources[:logstore]}" unless resources[:logstore].empty?
23
+ end
24
+ res << "/#{resources[:action]}" if resources[:action]
25
+ res
26
+ end
27
+
28
+ def get_request_url(resources = {})
29
+ resources ||= {}
30
+ url = URI.parse(@config.endpoint)
31
+ url.host = "#{resources[:project]}." + url.host if resources[:project]
32
+ url.path = get_resource_path(resources)
33
+ url.to_s
34
+ end
35
+
36
+ def get(resources, payload = {})
37
+ do_request('GET', resources, payload)
38
+ end
39
+
40
+ def post(resources, payload)
41
+ do_request('POST', resources, payload)
42
+ end
43
+
44
+ def put(resources, payload)
45
+ do_request('PUT', resources, payload)
46
+ end
47
+
48
+ def delete(resources, payload)
49
+ do_request('DELETE', resources, payload)
50
+ end
51
+
52
+ def do_request(verb, resources, payload)
53
+ resource_path = get_resource_path(resources)
54
+ headers = {}
55
+ if verb == 'GET'
56
+ headers = compact_headers
57
+ headers['Authorization'] = signature(verb, resource_path, headers, payload)
58
+ else
59
+ headers = compact_headers(payload, resources[:is_pb])
60
+ headers['Authorization'] = signature(verb, resource_path, headers)
61
+ end
62
+ request_options = {
63
+ method: verb,
64
+ url: get_request_url(resources),
65
+ headers: headers,
66
+ open_timeout: @config.open_timeout,
67
+ read_timeout: @config.read_timeout
68
+ }
69
+ if verb == 'GET'
70
+ request_options[:url] = canonicalized_resource(request_options[:url], payload)
71
+ else
72
+ payload = Zlib::Deflate.deflate(payload.encode) if resources[:is_pb]
73
+ request_options[:payload] = payload
74
+ end
75
+ logger.debug(request_options)
76
+ request = RestClient::Request.new(request_options)
77
+ response = request.execute do |resp|
78
+ if resp.code >= 300
79
+ e = ServerError.new(resp)
80
+ logger.error(e.to_s)
81
+ raise e
82
+ else
83
+ resp.return!
84
+ end
85
+ end
86
+
87
+ logger.debug("Received HTTP response, code: #{response.code}, headers: " \
88
+ "#{response.headers}, body: #{response.body}")
89
+
90
+ response
91
+ end
92
+
93
+ def compact_headers(body = nil, is_pb = false)
94
+ headers = {
95
+ 'x-log-apiversion' => '0.6.0',
96
+ 'x-log-signaturemethod' => 'hmac-sha1',
97
+ 'x-log-bodyrawsize' => '0',
98
+ 'Date' => DateTime.now.httpdate,
99
+ 'User-Agent' => "aliyun-log ruby-#{RUBY_VERSION}/#{RUBY_PLATFORM}"
100
+ }
101
+ return headers if body.nil?
102
+ if is_pb
103
+ compressed = Zlib::Deflate.deflate(body.encode)
104
+ headers['Content-Length'] = compressed.bytesize.to_s
105
+ # 日志内容包含的日志必须小于3MB和4096条。
106
+ raise 'content length is larger than 3MB' if headers['Content-Length'].to_i > 3145728
107
+ headers['Content-MD5'] = Digest::MD5.hexdigest(compressed).upcase
108
+ headers['Content-Type'] = 'application/x-protobuf'
109
+ headers['x-log-compresstype'] = 'deflate'
110
+ headers['x-log-bodyrawsize'] = body.encode.bytesize.to_s
111
+ else
112
+ headers['Content-Type'] = 'application/json'
113
+ headers['Content-MD5'] = Digest::MD5.hexdigest(body.encode).upcase
114
+ headers['x-log-bodyrawsize'] = body.bytesize.to_s
115
+ end
116
+ headers
117
+ end
118
+
119
+ def signature(verb, resource, headers, query = {})
120
+ sha1_digest = OpenSSL::HMAC.digest(
121
+ OpenSSL::Digest.new('sha1'),
122
+ @config.access_key_secret,
123
+ string_to_sign(verb, resource, headers, query).chomp
124
+ )
125
+ logger.debug "\n#{string_to_sign(verb, resource, headers, query).chomp}"
126
+ base64_sign = Base64.strict_encode64(sha1_digest)
127
+ "LOG #{@config.access_key_id}:#{base64_sign}"
128
+ end
129
+
130
+ def string_to_sign(verb, resource, headers, query = {})
131
+ <<~DOC
132
+ #{verb}
133
+ #{headers['Content-MD5']}
134
+ #{headers['Content-Type']}
135
+ #{headers['Date']}
136
+ #{canonicalized_sls_headers(headers)}
137
+ #{canonicalized_resource(resource, query)}
138
+ DOC
139
+ end
140
+
141
+ def canonicalized_sls_headers(headers)
142
+ h = {}
143
+ headers.each do |k, v|
144
+ h[k.downcase] = v if k =~ /x-log-.*/
145
+ end
146
+ h.keys.sort.map do |e|
147
+ h[e]
148
+ "#{e}:#{h[e].gsub(/^\s+/, '')}"
149
+ end.join("\n")
150
+ end
151
+
152
+ def canonicalized_resource(resource = '', query = {})
153
+ return resource if query.empty?
154
+ url = URI.parse(resource)
155
+ q_str = query.keys.sort.map do |e|
156
+ "#{e}=#{query[e]}"
157
+ end.join('&')
158
+ "#{url}?#{q_str}"
159
+ end
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,31 @@
1
+ require 'json'
2
+
3
+ module Aliyun
4
+ module Log
5
+ class ServerError < StandardError
6
+ attr_reader :http_code, :error_code, :raw_message, :request_id
7
+
8
+ def initialize(response)
9
+ @http_code = response.code
10
+ body = JSON.parse(response.body)
11
+ @error_code = body['errorCode']
12
+ @raw_message = body['errorMessage']
13
+ if @error_code == 'IndexInfoInvalid'
14
+ human_info = ' please see the rules: ' \
15
+ 'https://help.aliyun.com/document_detail/74953.html'
16
+ @raw_message += human_info
17
+ end
18
+ @request_id = response.headers['x-log-requestid']
19
+ end
20
+
21
+ def message
22
+ @raw_message || "UnknownError[#{http_code}]."
23
+ end
24
+
25
+ def to_s
26
+ msg = @raw_message || "UnknownError[#{http_code}]."
27
+ "error_code: #{@error_code} message: #{msg} RequestId: #{request_id}"
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,5 @@
1
+ module Aliyun
2
+ module Log
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,136 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: aliyun-log
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Yingce Liu
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-06-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: protobuf
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 3.10.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 3.10.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: rest-client
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 2.1.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 2.1.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.17'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.17'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '12.3'
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: 12.3.3
65
+ type: :development
66
+ prerelease: false
67
+ version_requirements: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - "~>"
70
+ - !ruby/object:Gem::Version
71
+ version: '12.3'
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: 12.3.3
75
+ - !ruby/object:Gem::Dependency
76
+ name: rspec
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '3.0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '3.0'
89
+ description: Aliyun Log SDK for Ruby
90
+ email:
91
+ - yingce@live.com
92
+ executables: []
93
+ extensions: []
94
+ extra_rdoc_files: []
95
+ files:
96
+ - lib/aliyun/log.rb
97
+ - lib/aliyun/log/client.rb
98
+ - lib/aliyun/log/common.rb
99
+ - lib/aliyun/log/common/attr_struct.rb
100
+ - lib/aliyun/log/common/logging.rb
101
+ - lib/aliyun/log/config.rb
102
+ - lib/aliyun/log/logstore.rb
103
+ - lib/aliyun/log/project.rb
104
+ - lib/aliyun/log/protobuf.rb
105
+ - lib/aliyun/log/protocol.rb
106
+ - lib/aliyun/log/request.rb
107
+ - lib/aliyun/log/server_error.rb
108
+ - lib/aliyun/version.rb
109
+ homepage: https://github.com/yingce/aliyun-log
110
+ licenses:
111
+ - MIT
112
+ metadata:
113
+ allowed_push_host: https://rubygems.org
114
+ homepage_uri: https://github.com/yingce/aliyun-log
115
+ source_code_uri: https://github.com/yingce/aliyun-log
116
+ changelog_uri: https://github.com/yingce/aliyun-log/blob/master/CHANGELOG.md
117
+ post_install_message:
118
+ rdoc_options: []
119
+ require_paths:
120
+ - lib
121
+ required_ruby_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ required_rubygems_version: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ requirements: []
132
+ rubygems_version: 3.0.8
133
+ signing_key:
134
+ specification_version: 4
135
+ summary: Aliyun Log SDK for Ruby
136
+ test_files: []