aliyun-log 0.2.12 → 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: ba1bcbd83277ca8da27978ecd7a603a205a19c1600b11f359135e2629e6f61c4
4
- data.tar.gz: d1e731f6b181167ef11004c7c79bbbef9acd290be531a08a24bb6f87134cfaac
3
+ metadata.gz: 5d6574ee8e72a65c178f4cdc28c61e63379999e51166c95756b9ffd6b367f47a
4
+ data.tar.gz: 8fdce159cd971c94c966b20db9926653a16e4bd5efaee918f619a6f0bf00a9e8
5
5
  SHA512:
6
- metadata.gz: 850989116e4820287e15fbe5361319f1043d4a1c3e7991bab947187bcac2d0114ee9244df26c4c132cd29d400752b4f18a6c0a3bcccaaabdda151858829b19e4
7
- data.tar.gz: c03afaddd81499c4cb36be357d9894eccf2574fa009afa2d57f7d01e61885534a60b94f4bc2dfaa315e5db0862481225966fc71f27fb8ce1d6a1686284f90e40
6
+ metadata.gz: 13ce9aed0a16e0c0a47fe8baadc45215967fd33cef33bece8bdfca0148a565155f347860d3bf986091b965419e04d513e19756c87b6f52ac32879188f07f3a11
7
+ data.tar.gz: f7c441bdb8ae2f3a768b236fb1bc8b86ad0c4965324b9323142565d50ed776b632ff11ba2036af7b1d1058968daeabe14080f792cbf2d438c777a6f4a25f17cf
@@ -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
@@ -40,11 +48,12 @@ module Aliyun
40
48
  end
41
49
 
42
50
  def auto_load_schema
43
- return if _schema_load
44
-
45
- create_logstore
46
- sync_index
47
- 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
48
57
  end
49
58
 
50
59
  def has_index?
@@ -54,19 +63,23 @@ module Aliyun
54
63
  false
55
64
  end
56
65
 
57
- def create(data, opts = {})
66
+ def create(data, force = false)
58
67
  auto_load_schema
59
68
  if data.is_a?(Array)
60
- logs = data.map do |log_attr|
61
- 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
62
73
  end
63
- res = Log.record_connection.put_log(project_name, logstore_name, logs, opts)
64
- res.code == 200
65
74
  else
66
- new(data).save
75
+ new(data).save(force)
67
76
  end
68
77
  end
69
78
 
79
+ def create!(data)
80
+ create(data, true)
81
+ end
82
+
70
83
  private
71
84
 
72
85
  def evaluate_default_value(val)
@@ -80,11 +93,12 @@ module Aliyun
80
93
  end
81
94
 
82
95
  def field_indices
83
- if options[:field_index] == false
84
- attributes.select { |_, value| value[:index] == true }
85
- else
86
- attributes.reject { |_, value| value[:index] == false }
87
- 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) }
88
102
  end
89
103
 
90
104
  def create_index
@@ -125,38 +139,68 @@ module Aliyun
125
139
  end
126
140
  end
127
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
+
128
150
  def dump_attributes
129
151
  attributes.dup.tap do |tap|
130
152
  tap.each do |k, v|
131
- 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
132
158
  end
133
159
  end
134
160
  end
135
161
 
136
- def save
162
+ def save(force = false)
137
163
  self.class.auto_load_schema
138
164
  run_callbacks(:create) do
139
165
  run_callbacks(:save) do
140
- if valid?
141
- res = Log.record_connection.put_log(
142
- self.class.project_name,
143
- self.class.logstore_name,
144
- dump_attributes
145
- )
146
- res.code == 200
147
- else
148
- false
149
- end
166
+ force && validate!
167
+ return false unless valid?
168
+ saved = put_logs
169
+ @new_record = false if saved
170
+ saved
150
171
  end
151
172
  end
152
173
  end
153
174
 
154
- def save_array
155
- run_callbacks(:create) do
156
- run_callbacks(:save) do
157
- validate! && dump_attributes
158
- end
159
- 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)
160
204
  end
161
205
  end
162
206
  end
@@ -216,7 +216,7 @@ module Aliyun
216
216
  sql_query << "ORDER BY #{opts[:order]}" if opts[:order].present?
217
217
  if sql_query.present? || opts[:select].present?
218
218
  sql_query.insert(0, "SELECT #{opts[:select] || '*'}")
219
- sql_query.insert(1, 'FROM log')
219
+ sql_query.insert(1, 'FROM log') unless opts[:select]&.match?(/from\s+log/i)
220
220
  if opts[:line] || opts[:page] || opts[:offset]
221
221
  parse_page
222
222
  sql_query << "LIMIT #{@opts[:offset]},#{@opts[:line]}"
@@ -250,7 +250,7 @@ module Aliyun
250
250
  def sanitize_hash(search_content)
251
251
  return search_content unless search_content.is_a?(Hash)
252
252
 
253
- search_content.select { |_, v| v.present? }.map do |key, value|
253
+ search_content.reject { |_, v| v.nil? }.map do |key, value|
254
254
  options = @klass.attributes[:"#{key}"]
255
255
  unless options
256
256
  raise UnknownAttributeError, "unknown field '#{key}' for #{@klass.name}."
@@ -259,14 +259,18 @@ module Aliyun
259
259
  raise_if_hash_quote(value)
260
260
 
261
261
  cast_type = options[:cast_type]
262
+
263
+ is_tag = @klass.tag_attributes[:"#{key}"]
264
+ key = :"__tag__:#{key}" if is_tag
262
265
  if value.is_a?(Array)
263
- values = value.uniq.map { |v| _quote(cast_type, v) }
266
+ values = value.uniq.map { |v| is_tag ? v : _quote(cast_type, v) }
264
267
  str_values = values.map { |v| "#{key}: #{v}" }.join(' OR ')
265
268
  values.size > 1 ? "(#{str_values})" : str_values
266
269
  elsif value.is_a?(Range)
267
270
  "#{key} in [#{value.begin} #{value.end}]"
268
271
  else
269
- "#{key}: #{_quote(cast_type, value)}"
272
+ quote_value = is_tag ? value : _quote(cast_type, value)
273
+ "#{key}: #{quote_value}"
270
274
  end
271
275
  end.join(' AND ')
272
276
  end
@@ -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)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Aliyun
4
4
  module Log
5
- VERSION = '0.2.12'
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.12
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-07-13 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