aliyun-log 0.2.8 → 0.2.13

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: b389451492d70d3427b9a940de87c2166d862ac543f882b97a3924e31b51e92c
4
- data.tar.gz: 6f8d17bad66ed46c0a8da7e514c10cfaa1198418e48e7d2f03be8f8de499d16d
3
+ metadata.gz: 5d6574ee8e72a65c178f4cdc28c61e63379999e51166c95756b9ffd6b367f47a
4
+ data.tar.gz: 8fdce159cd971c94c966b20db9926653a16e4bd5efaee918f619a6f0bf00a9e8
5
5
  SHA512:
6
- metadata.gz: 1c68ba2d18b987e36c96187a7007ede440af4f0beb36748e49ce213872f57dd5db78dfb82ed63c4f9ee5f87b558daa4fc0686b13e71533ba4d3dc6fdaa3333ae
7
- data.tar.gz: 3ce13d9720545a7394a0b64b2b6adb78f196dd83a554f7b872a57460e29dac5dd2876a5a528c7c728c537ece778bc4913900b0487856dd65c7d563ff5f0045ee
6
+ metadata.gz: 13ce9aed0a16e0c0a47fe8baadc45215967fd33cef33bece8bdfca0148a565155f347860d3bf986091b965419e04d513e19756c87b6f52ac32879188f07f3a11
7
+ data.tar.gz: f7c441bdb8ae2f3a768b236fb1bc8b86ad0c4965324b9323142565d50ed776b632ff11ba2036af7b1d1058968daeabe14080f792cbf2d438c777a6f4a25f17cf
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'version'
3
4
  require_relative 'log/common'
4
5
  require_relative 'log/client'
5
6
  require_relative 'log/config'
@@ -16,11 +16,17 @@ module Aliyun
16
16
  repeated Content, :contents, 2
17
17
  end
18
18
 
19
+ class LogTag < ::Protobuf::Message
20
+ required :string, :key, 1
21
+ required :string, :value, 2
22
+ end
23
+
19
24
  class LogGroup < ::Protobuf::Message
20
25
  repeated Log, :logs, 1
21
26
  optional :string, :reserved, 2
22
27
  optional :string, :topic, 3
23
28
  optional :string, :source, 4
29
+ repeated LogTag, :log_tags, 6
24
30
  end
25
31
  end
26
32
  end
@@ -4,7 +4,7 @@ require 'active_support'
4
4
  require 'active_support/time'
5
5
  require 'active_support/core_ext'
6
6
  require 'active_model'
7
- require 'forwardable'
7
+ require 'monitor'
8
8
 
9
9
  require_relative 'record/exception'
10
10
  require_relative 'record/field'
@@ -22,16 +22,21 @@ module Aliyun
22
22
 
23
23
  class_attribute :options, instance_accessor: false, default: {}
24
24
  class_attribute :base_class, instance_accessor: false, default: self
25
- class_attribute :log_connection, instance_accessor: false
26
25
  class_attribute :_schema_load, default: false
27
26
 
28
27
  Log.included_models << self unless Log.included_models.include? self
29
28
 
29
+ field :__time__, type: :long, cast_type: :integer
30
+ field :__topic__
31
+ field :__source__
32
+
30
33
  field :created_at, type: :text, cast_type: :datetime if Config.timestamps
31
34
 
32
35
  define_model_callbacks :save, :create, :initialize
33
36
 
34
37
  before_save :set_created_at
38
+
39
+ @lock = Monitor.new
35
40
  end
36
41
 
37
42
  include Field
@@ -79,6 +84,10 @@ module Aliyun
79
84
  end
80
85
  end
81
86
 
87
+ def new_record?
88
+ @new_record == true
89
+ end
90
+
82
91
  def inspect
83
92
  inspection = if defined?(@attributes) && @attributes
84
93
  self.class.attributes.keys.collect do |name|
@@ -20,6 +20,7 @@ module Aliyun
20
20
 
21
21
  included do
22
22
  class_attribute :attributes, instance_accessor: false, default: {}
23
+ class_attribute :tag_attributes, instance_accessor: false, default: {}
23
24
  extend Common::Logging
24
25
  end
25
26
 
@@ -31,7 +32,11 @@ module Aliyun
31
32
  end
32
33
 
33
34
  named = name.to_s
34
- self.attributes = attributes.merge(name => { type: type }.merge(options))
35
+ if options[:log_tag]
36
+ self.tag_attributes = tag_attributes.merge(name => { type: type }.merge(options))
37
+ else
38
+ self.attributes = attributes.merge(name => { type: type }.merge(options))
39
+ end
35
40
 
36
41
  warn_about_method_overriding(name, name)
37
42
  warn_about_method_overriding("#{named}=", name)
@@ -4,6 +4,14 @@ module Aliyun
4
4
  module Log
5
5
  module Record
6
6
  module Persistence
7
+ RESERVED_FIELDS = %i[
8
+ __time__
9
+ __topic__
10
+ __source__
11
+ __partition_time__
12
+ __extract_others__
13
+ ].freeze
14
+
7
15
  extend ActiveSupport::Concern
8
16
 
9
17
  module ClassMethods
@@ -35,15 +43,17 @@ module Aliyun
35
43
  end
36
44
 
37
45
  def sync_index
46
+ return if field_indices.blank?
38
47
  has_index? ? update_index : create_index
39
48
  end
40
49
 
41
50
  def auto_load_schema
42
- return if _schema_load
43
-
44
- create_logstore
45
- sync_index
46
- self._schema_load = true
51
+ @lock.synchronize do
52
+ return if _schema_load
53
+ create_logstore
54
+ sync_index
55
+ self._schema_load = true
56
+ end
47
57
  end
48
58
 
49
59
  def has_index?
@@ -53,19 +63,23 @@ module Aliyun
53
63
  false
54
64
  end
55
65
 
56
- def create(data, opts = {})
66
+ def create(data, force = false)
57
67
  auto_load_schema
58
68
  if data.is_a?(Array)
59
- logs = data.map do |log_attr|
60
- new(log_attr).save_array
69
+ # TODO batch insert
70
+ data.each do |log|
71
+ saved = new(log).save(force)
72
+ return false unless saved
61
73
  end
62
- res = Log.record_connection.put_log(project_name, logstore_name, logs, opts)
63
- res.code == 200
64
74
  else
65
- new(data).save
75
+ new(data).save(force)
66
76
  end
67
77
  end
68
78
 
79
+ def create!(data)
80
+ create(data, true)
81
+ end
82
+
69
83
  private
70
84
 
71
85
  def evaluate_default_value(val)
@@ -79,11 +93,12 @@ module Aliyun
79
93
  end
80
94
 
81
95
  def field_indices
82
- if options[:field_index] == false
83
- attributes.select { |_, value| value[:index] == true }
84
- else
85
- attributes.reject { |_, value| value[:index] == false }
86
- end
96
+ indices = if options[:field_index] == false
97
+ attributes.select { |_, value| value[:index] == true }
98
+ else
99
+ attributes.reject { |_, value| value[:index] == false }
100
+ end
101
+ indices.reject { |key, _| RESERVED_FIELDS.include?(key) }
87
102
  end
88
103
 
89
104
  def create_index
@@ -99,6 +114,7 @@ module Aliyun
99
114
  raw_conf = JSON.parse(conf_res)
100
115
  index_conf = raw_conf.deep_dup
101
116
  field_index_types.each do |k, v|
117
+ index_conf['keys'] ||= {}
102
118
  index_conf['keys'][k.to_s] ||= {}
103
119
  index_conf['keys'][k.to_s].merge!(v.as_json)
104
120
  end
@@ -123,38 +139,68 @@ module Aliyun
123
139
  end
124
140
  end
125
141
 
142
+ def dump_log_tags
143
+ log_tags = {}
144
+ self.class.tag_attributes.map do |key, options|
145
+ log_tags[key] = TypeCasting.dump_field(attributes[key], options)
146
+ end
147
+ log_tags.compact
148
+ end
149
+
126
150
  def dump_attributes
127
151
  attributes.dup.tap do |tap|
128
152
  tap.each do |k, v|
129
- tap[k] = TypeCasting.dump_field(v, self.class.attributes[k])
153
+ if self.class.attributes[k][:log_tag] || RESERVED_FIELDS.include?(k)
154
+ tap.delete(k)
155
+ else
156
+ tap[k] = TypeCasting.dump_field(v, self.class.attributes[k])
157
+ end
130
158
  end
131
159
  end
132
160
  end
133
161
 
134
- def save
162
+ def save(force = false)
135
163
  self.class.auto_load_schema
136
164
  run_callbacks(:create) do
137
165
  run_callbacks(:save) do
138
- if valid?
139
- res = Log.record_connection.put_log(
140
- self.class.project_name,
141
- self.class.logstore_name,
142
- dump_attributes
143
- )
144
- res.code == 200
145
- else
146
- false
147
- end
166
+ force && validate!
167
+ return false unless valid?
168
+ saved = put_logs
169
+ @new_record = false if saved
170
+ saved
148
171
  end
149
172
  end
150
173
  end
151
174
 
152
- def save_array
153
- run_callbacks(:create) do
154
- run_callbacks(:save) do
155
- validate! && dump_attributes
156
- end
157
- end
175
+ def save!
176
+ save(true)
177
+ end
178
+
179
+ private
180
+
181
+ def put_logs
182
+ log_tags = []
183
+ dump_log_tags.each do |k, v|
184
+ log_tags << Protobuf::LogTag.new(key: k, value: v)
185
+ end
186
+ lg = Protobuf::LogGroup.new(
187
+ logs: [generate_log],
188
+ log_tags: log_tags,
189
+ topic: read_attribute(:__topic__),
190
+ source: read_attribute(:__source__)
191
+ )
192
+ res = Log.record_connection.put_logs(
193
+ self.class.project_name,
194
+ self.class.logstore_name,
195
+ lg
196
+ )
197
+ res.code == 200
198
+ end
199
+
200
+ def generate_log
201
+ time = read_attribute(:__time__) || Time.now.to_i
202
+ contents = dump_attributes.map { |k, v| { key: k, value: v.to_s } }
203
+ Protobuf::Log.new(time: time, contents: contents)
158
204
  end
159
205
  end
160
206
  end
@@ -10,9 +10,9 @@ module Aliyun
10
10
  @klass.auto_load_schema
11
11
  end
12
12
 
13
- # def inspect
14
- # "#<#{self.class}>"
15
- # end
13
+ def inspect
14
+ "#<#{self.class}>"
15
+ end
16
16
 
17
17
  def first(line = 1)
18
18
  find_offset(0, line, false)
@@ -35,14 +35,28 @@ module Aliyun
35
35
  end
36
36
 
37
37
  def last(line = 1)
38
- find_offset(0, line, true)
38
+ data = find_offset(0, line, true)
39
+ line > 1 ? data.reverse : data
39
40
  end
40
41
 
41
42
  def find_offset(nth, line = 1, reverse = false)
43
+ # @opts[:select] = '*'
42
44
  @opts[:line] = line
43
45
  @opts[:offset] = nth
44
- @opts[:reverse] = reverse
45
- line <= 1 ? load[0] : load
46
+ if @opts[:order].present? && reverse
47
+ conds = []
48
+ @opts[:order].split(',').each do |field|
49
+ field.gsub!(/\s+desc|asc.*/i, '')
50
+ conds << "#{field.strip} DESC"
51
+ end
52
+ @opts[:order] = conds.join(', ')
53
+ end
54
+ @opts[:order] ||= reverse ? '__time__ DESC' : '__time__ ASC'
55
+ if @opts[:select].blank?
56
+ line <= 1 ? load[0] : load
57
+ else
58
+ line <= 1 ? result[0] : result
59
+ end
46
60
  end
47
61
 
48
62
  def scoping
@@ -78,10 +92,16 @@ module Aliyun
78
92
 
79
93
  def page(val)
80
94
  @opts[:page] = val - 1 if val >= 1
95
+ singleton_class.send(:define_method, :total_count) do
96
+ @total_count ||= count
97
+ end
98
+ singleton_class.send(:define_method, :total_pages) do
99
+ (total_count.to_f / (@opts[:line] || 100)).ceil
100
+ end
81
101
  self
82
102
  end
83
103
 
84
- def where(opts)
104
+ def api(opts)
85
105
  @opts.merge!(opts)
86
106
  self
87
107
  end
@@ -93,11 +113,49 @@ module Aliyun
93
113
  end
94
114
 
95
115
  def sql(*statement)
96
- ql = statement_ql(*statement)
116
+ unless statement[0].is_a?(String)
117
+ raise ParseStatementInvalid, 'Only support string statement'
118
+ end
119
+ ql = sanitize_array(*statement)
97
120
  @opts[:sql] = ql if ql.present?
98
121
  self
99
122
  end
100
123
 
124
+ def where(*statement)
125
+ if statement[0].is_a?(String)
126
+ ql = sanitize_array(*statement)
127
+ @opts[:where] = ql
128
+ else
129
+ ql = statement_ql(*statement)
130
+ @opts[:search] = ql
131
+ end
132
+ self
133
+ end
134
+
135
+ def select(*fields)
136
+ @opts[:select] = fields.join(', ')
137
+ self
138
+ end
139
+
140
+ def group(*fields)
141
+ @opts[:group] = fields.join(', ')
142
+ self
143
+ end
144
+
145
+ def order(*fields)
146
+ if fields[0].is_a?(Hash)
147
+ @opts[:order] = fields[0].map do |k, v|
148
+ unless %w[asc desc].include?(v.to_s)
149
+ raise ArgumentError, "Direction \"#{v}\" is invalid. Valid directions are: [:asc, :desc, :ASC, :DESC]"
150
+ end
151
+ "#{k} #{v}"
152
+ end.join(', ')
153
+ else
154
+ @opts[:order] = fields.join(', ')
155
+ end
156
+ self
157
+ end
158
+
101
159
  def query(opts = {})
102
160
  @opts[:query] = opts
103
161
  self
@@ -105,26 +163,38 @@ module Aliyun
105
163
 
106
164
  def count
107
165
  query = @opts.dup
108
- if query[:query].blank?
109
- where_cond = query[:sql].split(/where /i)[1] if query[:sql].present?
110
- query[:query] = "#{query[:search]}|SELECT COUNT(*) as count"
111
- query[:query] = "#{query[:query]} WHERE #{where_cond}" if where_cond.present?
166
+ if query[:select].blank?
167
+ @opts[:select] = 'COUNT(*) as count'
168
+ sql = to_sql
169
+ else
170
+ _sql = to_sql
171
+ sql = "SELECT COUNT(*) as count"
172
+ sql += " FROM(#{_sql})" if _sql.present?
112
173
  end
113
- res = Log.record_connection.get_logs(@klass.project_name, @klass.logstore_name, query)
114
- res = JSON.parse(res.body)
115
- res[0]['count'].to_i
174
+ query[:query] = "#{query[:search] || '*'}|#{sql}"
175
+ res = execute(query)
176
+ res.dig(0, 'count').to_i
177
+ end
178
+
179
+ def sum(field)
180
+ @opts[:select] = "SUM(#{field}) as sum"
181
+ query = @opts.dup
182
+ query[:query] = "#{query[:search] || '*'}|#{to_sql}"
183
+ res = execute(query)
184
+ res.dig(0, 'sum').to_f
116
185
  end
117
186
 
118
187
  def result
119
188
  query = @opts.dup
120
- if query[:page]
121
- query[:line] ||= 100
122
- query[:offset] = query[:page] * query[:line]
123
- end
124
189
  query[:query] = query[:search] || '*'
125
- query[:query] = "#{query[:query]}|#{query[:sql]}" if query[:sql].present?
126
- res = Log.record_connection.get_logs(@klass.project_name, @klass.logstore_name, query)
127
- JSON.parse(res)
190
+ sql = to_sql
191
+ if sql.present?
192
+ query[:query] += "|#{sql}"
193
+ @opts[:line] = nil
194
+ @opts[:offset] = nil
195
+ @opts[:page] = nil
196
+ end
197
+ execute(query)
128
198
  end
129
199
 
130
200
  def load
@@ -137,8 +207,38 @@ module Aliyun
137
207
  end
138
208
  end
139
209
 
210
+ def to_sql
211
+ return @opts[:sql] if @opts[:sql].present?
212
+ opts = @opts.dup
213
+ sql_query = []
214
+ sql_query << "WHERE #{opts[:where]}" if opts[:where].present?
215
+ sql_query << "GROUP BY #{opts[:group]}" if opts[:group].present?
216
+ sql_query << "ORDER BY #{opts[:order]}" if opts[:order].present?
217
+ if sql_query.present? || opts[:select].present?
218
+ sql_query.insert(0, "SELECT #{opts[:select] || '*'}")
219
+ sql_query.insert(1, 'FROM log') unless opts[:select]&.match?(/from\s+log/i)
220
+ if opts[:line] || opts[:page] || opts[:offset]
221
+ parse_page
222
+ sql_query << "LIMIT #{@opts[:offset]},#{@opts[:line]}"
223
+ end
224
+ end
225
+ "#{opts[:query]}#{sql_query.join(' ')}"
226
+ end
227
+
140
228
  private
141
229
 
230
+ def execute(query)
231
+ puts query.slice(:from, :to, :search, :query).to_json
232
+ res = Log.record_connection.get_logs(@klass.project_name, @klass.logstore_name, query)
233
+ JSON.parse(res)
234
+ end
235
+
236
+ def parse_page
237
+ @opts[:line] ||= 100
238
+ @opts[:page] ||= 0
239
+ @opts[:offset] = @opts[:page] * @opts[:line]
240
+ end
241
+
142
242
  def statement_ql(*statement)
143
243
  if statement.size == 1
144
244
  sanitize_hash(statement.first)
@@ -150,12 +250,28 @@ module Aliyun
150
250
  def sanitize_hash(search_content)
151
251
  return search_content unless search_content.is_a?(Hash)
152
252
 
153
- search_content.select { |_, v| v.present? }.map do |key, value|
154
- unless @klass.attributes[:"#{key}"]
253
+ search_content.reject { |_, v| v.nil? }.map do |key, value|
254
+ options = @klass.attributes[:"#{key}"]
255
+ unless options
155
256
  raise UnknownAttributeError, "unknown field '#{key}' for #{@klass.name}."
156
257
  end
157
258
 
158
- "#{key}: #{value}"
259
+ raise_if_hash_quote(value)
260
+
261
+ cast_type = options[:cast_type]
262
+
263
+ is_tag = @klass.tag_attributes[:"#{key}"]
264
+ key = :"__tag__:#{key}" if is_tag
265
+ if value.is_a?(Array)
266
+ values = value.uniq.map { |v| is_tag ? v : _quote(cast_type, v) }
267
+ str_values = values.map { |v| "#{key}: #{v}" }.join(' OR ')
268
+ values.size > 1 ? "(#{str_values})" : str_values
269
+ elsif value.is_a?(Range)
270
+ "#{key} in [#{value.begin} #{value.end}]"
271
+ else
272
+ quote_value = is_tag ? value : _quote(cast_type, value)
273
+ "#{key}: #{quote_value}"
274
+ end
159
275
  end.join(' AND ')
160
276
  end
161
277
 
@@ -165,7 +281,7 @@ module Aliyun
165
281
  replace_named_bind_variables(statement, values.first)
166
282
  elsif statement.include?('?')
167
283
  replace_bind_variables(statement, values)
168
- elsif statement.blank?
284
+ elsif statement.blank? || values.blank?
169
285
  statement
170
286
  else
171
287
  statement % values.collect(&:to_s)
@@ -175,7 +291,14 @@ module Aliyun
175
291
  def replace_named_bind_variables(statement, bind_vars)
176
292
  statement.gsub(/(:?):([a-zA-Z]\w*)/) do |match|
177
293
  if bind_vars.include?(match = Regexp.last_match(2).to_sym)
178
- "'#{bind_vars[match]}'"
294
+ match_value = bind_vars[match]
295
+ raise_if_hash_quote(match_value)
296
+ if match_value.is_a?(Array) || match_value.is_a?(Range)
297
+ values = match_value.map { |v| _quote_type_value(v) }
298
+ values.join(', ')
299
+ else
300
+ _quote_type_value(match_value)
301
+ end
179
302
  else
180
303
  raise ParseStatementInvalid, "missing value for :#{match} in #{statement}"
181
304
  end
@@ -191,7 +314,42 @@ module Aliyun
191
314
  end
192
315
  bound = values.dup
193
316
  statement.gsub(/\?/) do
194
- "'#{bound.shift}'"
317
+ value = bound.shift
318
+ raise_if_hash_quote(value)
319
+ if value.is_a?(Array) || value.is_a?(Range)
320
+ values = value.map { |v| _quote_type_value(v) }
321
+ values.join(', ')
322
+ else
323
+ _quote_type_value(value)
324
+ end
325
+ end
326
+ end
327
+
328
+ def _quote(type, value)
329
+ v = TypeCasting.cast_field(value, cast_type: type || :string)
330
+ case type
331
+ when :string, nil then "'#{v.to_s}'"
332
+ when :bigdecimal then v.to_s("F")
333
+ when :integer then v.to_s.to_i
334
+ when :datetime, :date then "'#{v.iso8601}'"
335
+ else
336
+ value.to_s
337
+ end
338
+ end
339
+
340
+ def _quote_type_value(value)
341
+ case value.class.name
342
+ when 'String' then "'#{value.to_s}'"
343
+ when 'BigDecimal', 'Float' then value.to_s("F")
344
+ when 'Date', 'DateTime', 'Time' then "'#{value.iso8601}'"
345
+ else
346
+ value
347
+ end
348
+ end
349
+
350
+ def raise_if_hash_quote(value)
351
+ if value.is_a?(Hash) || value.is_a?(ActiveSupport::HashWithIndifferentAccess)
352
+ raise ParseStatementInvalid, "can't quote Hash"
195
353
  end
196
354
  end
197
355
 
@@ -10,9 +10,10 @@ module Aliyun
10
10
  extend ActiveSupport::Concern
11
11
 
12
12
  module ClassMethods
13
- delegate :load, :result, :count, to: :all
14
- delegate :where, :query, :search, :sql, :from, :to,
15
- :page, :line, :limit, :offset, to: :all
13
+ delegate :load, :result, :count, :sum, to: :all
14
+ delegate :where, :query, :search, :sql, :from, :to, :api,
15
+ :page, :line, :limit, :offset, :select, :group,
16
+ :order, :to_sql, to: :all
16
17
  delegate :first, :last, :second, :third, :fourth, :fifth, :find_offset, to: :all
17
18
 
18
19
  def current_scope
@@ -9,7 +9,7 @@ module Aliyun
9
9
  TYPE_MAPPING = {
10
10
  text: :string,
11
11
  long: :integer,
12
- double: :bigdecimal,
12
+ double: :float,
13
13
  json: :json
14
14
  }.freeze
15
15
 
@@ -55,7 +55,17 @@ module Aliyun
55
55
  end
56
56
  end
57
57
 
58
- class StringType < Value; end
58
+ class StringType < Value
59
+ def cast(value)
60
+ if value.nil?
61
+ ''
62
+ elsif value.is_a? String
63
+ value.dup
64
+ else
65
+ value.to_s
66
+ end
67
+ end
68
+ end
59
69
 
60
70
  class DateType < Value
61
71
  def cast(value)
@@ -66,7 +76,7 @@ module Aliyun
66
76
 
67
77
  def dump(value)
68
78
  if value.respond_to?(:to_date)
69
- value.to_datetime.iso8601
79
+ value.to_date.to_s
70
80
  else
71
81
  value.to_s
72
82
  end
@@ -148,6 +158,26 @@ module Aliyun
148
158
  end
149
159
  end
150
160
 
161
+ class FloatType < Value
162
+ def cast(value)
163
+ if value == true
164
+ 1
165
+ elsif value == false
166
+ 0
167
+ elsif value.is_a?(Symbol)
168
+ value.to_s.to_f
169
+ elsif value.is_a?(String) && value.blank?
170
+ nil
171
+ elsif value.is_a?(Float) && !value.finite?
172
+ nil
173
+ elsif !value.respond_to?(:to_f)
174
+ nil
175
+ else
176
+ value.to_f
177
+ end
178
+ end
179
+ end
180
+
151
181
  class JsonType < Value
152
182
  def cast(value)
153
183
  return value unless value.is_a?(String)
@@ -183,6 +213,7 @@ module Aliyun
183
213
  register(:datetime, DateTimeType)
184
214
  register(:bigdecimal, BigDecimalType)
185
215
  register(:integer, IntegerType)
216
+ register(:float, FloatType)
186
217
  register(:json, JsonType)
187
218
  end
188
219
  end
@@ -7,6 +7,8 @@ require 'digest'
7
7
  require 'date'
8
8
  require 'zlib'
9
9
 
10
+ require_relative 'utils'
11
+
10
12
  module Aliyun
11
13
  module Log
12
14
  class Request
@@ -16,25 +18,6 @@ module Aliyun
16
18
  @config = config
17
19
  end
18
20
 
19
- def get_resource_path(resources = {})
20
- resources ||= {}
21
- res = '/'
22
- if resources[:logstore]
23
- res = "#{res}logstores"
24
- res = "#{res}/#{resources[:logstore]}" unless resources[:logstore].empty?
25
- end
26
- res = "#{res}/#{resources[:action]}" if resources[:action]
27
- res
28
- end
29
-
30
- def get_request_url(resources = {})
31
- resources ||= {}
32
- url = URI.parse(@config.endpoint)
33
- url.host = "#{resources[:project]}." + url.host if resources[:project]
34
- url.path = get_resource_path(resources)
35
- url.to_s
36
- end
37
-
38
21
  def get(resources, payload = {})
39
22
  do_request('GET', resources, payload)
40
23
  end
@@ -52,10 +35,11 @@ module Aliyun
52
35
  end
53
36
 
54
37
  def do_request(verb, resources, payload)
55
- resource_path = get_resource_path(resources)
38
+ resource_path = Utils.get_resource_path(resources)
39
+ url = Utils.get_request_url(@config.endpoint, resources)
56
40
  request_options = {
57
41
  method: verb,
58
- url: get_request_url(resources),
42
+ url: url,
59
43
  open_timeout: @config.open_timeout,
60
44
  read_timeout: @config.read_timeout
61
45
  }
@@ -75,15 +59,17 @@ module Aliyun
75
59
  response = request.execute do |resp|
76
60
  if resp.code >= 300
77
61
  e = ServerError.new(resp)
78
- logger.error(e.to_s)
62
+ logger.error("#{e.to_s} #{resp.code} #{resp}")
79
63
  raise e
80
64
  else
81
65
  resp.return!
82
66
  end
83
67
  end
84
68
 
85
- logger.debug("Received HTTP response, code: #{response.code}, headers: " \
86
- "#{response.headers}, body: #{response.body.force_encoding('UTF-8')}")
69
+ logger.debug("Received HTTP response, code: #{response.code}, " \
70
+ "url: #{request_options[:url]}, " \
71
+ "method: #{verb}, headers: #{response.headers}, " \
72
+ "body: #{response.body.force_encoding('UTF-8')}")
87
73
 
88
74
  response
89
75
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/core_ext'
4
+
5
+ module Aliyun
6
+ module Log
7
+ module Utils
8
+ module_function
9
+ def get_resource_path(resources = {})
10
+ resources ||= {}
11
+ res = '/'
12
+ if resources[:logstore]
13
+ res = "#{res}logstores"
14
+ res = "#{res}/#{resources[:logstore]}" unless resources[:logstore].empty?
15
+ end
16
+ res = "#{res}/#{resources[:action]}" if resources[:action]
17
+ res
18
+ end
19
+
20
+ def get_request_url(endpoint, resources = {})
21
+ resources ||= {}
22
+ url = URI.parse(endpoint)
23
+ url.host = "#{resources[:project]}." + url.host if resources[:project]
24
+ url.path = get_resource_path(resources)
25
+ url.to_s
26
+ end
27
+ end
28
+ end
29
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Aliyun
4
4
  module Log
5
- VERSION = '0.2.8'
5
+ VERSION = '0.2.13'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aliyun-log
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.8
4
+ version: 0.2.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yingce Liu
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-06-12 00:00:00.000000000 Z
11
+ date: 2020-07-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -114,6 +114,20 @@ dependencies:
114
114
  - - "~>"
115
115
  - !ruby/object:Gem::Version
116
116
  version: '3.0'
117
+ - !ruby/object:Gem::Dependency
118
+ name: webmock
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '3.0'
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: '3.0'
117
131
  description: Aliyun Log SDK for Ruby 阿里云日志服务(SLS) Ruby SDK, 目前仅实现基于Restfull部分接口和简单Model映射
118
132
  email:
119
133
  - yingce@live.com
@@ -141,6 +155,7 @@ files:
141
155
  - lib/aliyun/log/record/type_casting.rb
142
156
  - lib/aliyun/log/request.rb
143
157
  - lib/aliyun/log/server_error.rb
158
+ - lib/aliyun/log/utils.rb
144
159
  - lib/aliyun/version.rb
145
160
  homepage: https://github.com/yingce/aliyun-log
146
161
  licenses: