aliyun-log 0.1.0

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