Class: Rookout::Processor::NamespaceSerializer2

Inherits:
Object
  • Object
show all
Defined in:
lib/rookout/processor/namespace_serializer2.rb

Constant Summary collapse

INT32_MIN =

Based off protobuf for Python

-2147483648
INT32_MAX =
2147483647
INT64_MIN =
-(1 << 63)
INT64_MAX =
(1 << 63) - 1

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeNamespaceSerializer2

Returns a new instance of NamespaceSerializer2.



26
27
28
29
# File 'lib/rookout/processor/namespace_serializer2.rb', line 26

def initialize
  @string_cache = {}
  @estimated_pending_bytes = 0
end

Instance Attribute Details

#estimated_pending_bytesObject (readonly)

Returns the value of attribute estimated_pending_bytes.



32
33
34
# File 'lib/rookout/processor/namespace_serializer2.rb', line 32

def estimated_pending_bytes
  @estimated_pending_bytes
end

#string_cacheObject (readonly)

Returns the value of attribute string_cache.



31
32
33
# File 'lib/rookout/processor/namespace_serializer2.rb', line 31

def string_cache
  @string_cache
end

Instance Method Details

#dump(namespace, log_errors) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/rookout/processor/namespace_serializer2.rb', line 55

def dump namespace, log_errors
  case namespace
  when Namespaces::RubyObjectNamespace
    dump_ruby_object_namespace namespace, log_errors
  when Namespaces::ContainerNamespace
    dump_container_namespace namespace, log_errors
  when Namespaces::TracebackNamespace
    dump_traceback_namespace namespace
  else
    raise NotImplementedError
  end
rescue StandardError => e
  message = "Failed to serialize namespace"
  variant = Com::Rookout::Variant2.new
  @estimated_pending_bytes = 0
  dump_variant_type variant, Com::Rookout::Variant::Type::VARIANT_ERROR

  if log_errors
    Logger.instance.exception message, e

    error = RookError.new e, message
    UserWarnings.notify_warning error
  end
  variant
end

#dump_array(obj, variant, current_depth, config, log_object_errors) ⇒ Object



209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/rookout/processor/namespace_serializer2.rb', line 209

def dump_array obj, variant, current_depth, config, log_object_errors
  variant.original_size = obj.length
  @estimated_pending_bytes += 3 # Header + number

  weighted_children_depth = current_depth + 1
  if weighted_children_depth <= config.max_collection_depth
    dump_variant_type variant, Com::Rookout::Variant::Type::VARIANT_LIST
    obj.each_with_index do |value, index|
      break if index >= config.max_width
      variant.collection_values << dump_raw_object(value, weighted_children_depth, config, log_object_errors)
      @estimated_pending_bytes += 3 # Header + size
    end
  else
    dump_variant_type_max_depth variant, Com::Rookout::Variant::Type::VARIANT_LIST
  end
end

#dump_code_object(obj, variant) ⇒ Object



258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
# File 'lib/rookout/processor/namespace_serializer2.rb', line 258

def dump_code_object obj, variant
  dump_variant_type variant, Com::Rookout::Variant::Type::VARIANT_CODE_OBJECT

  if obj.is_a?(Proc) || obj.is_a?(Method)
    source_location = obj.source_location
  else
    source_location = [nil, nil]
  end

  if obj.is_a? Proc
    name = ""
  else
    name = obj.name
  end

  variant.code_values << Com::Rookout::Variant::CodeObject.new(name: name,
                                                               filename: source_location[0],
                                                               lineno: source_location[1])
  # NOTE: This size is probably less, in Python we use the optional fields of CodeObject and in Ruby we don't,
  # but it is better to estimate more
  @estimated_pending_bytes += 14 # Header + size + (header + number) * 4
end

#dump_container_namespace(namespace, log_errors) ⇒ Object



297
298
299
300
301
302
303
304
305
306
307
308
309
# File 'lib/rookout/processor/namespace_serializer2.rb', line 297

def dump_container_namespace namespace, log_errors
  variant = Com::Rookout::Variant2.new
  dump_variant_type variant, Com::Rookout::Variant::Type::VARIANT_NAMESPACE

  namespace.hash.each do |key, value|
    variant.attribute_names_in_cache << get_string_index_in_cache(key.to_s)
    variant.attribute_values << dump(value, log_errors)
  end

  @estimated_pending_bytes += 4 # One number (packed field), One header + length

  variant
end

#dump_exception(obj, variant, current_depth, config, log_object_errors) ⇒ Object



243
244
245
246
247
248
249
250
251
252
253
254
255
256
# File 'lib/rookout/processor/namespace_serializer2.rb', line 243

def dump_exception obj, variant, current_depth, config, log_object_errors
  dump_variant_type variant, Com::Rookout::Variant::Type::VARIANT_OBJECT
  variant.attribute_names_in_cache << get_string_index_in_cache("message")
  variant.attribute_values << dump_raw_object(obj.message, current_depth + 1, config, log_object_errors)
  @estimated_pending_bytes += 6 # Header + number + header + size

  variant.attribute_names_in_cache << get_string_index_in_cache("cause")
  variant.attribute_values << dump_raw_object(obj.cause, current_depth + 1, config, log_object_errors)
  @estimated_pending_bytes += 6 # Header + number + header + size

  variant.attribute_names_in_cache << get_string_index_in_cache("backtrace")
  variant.attribute_values << dump_raw_object(obj.backtrace, current_depth + 1, config, log_object_errors)
  @estimated_pending_bytes += 6 # Header + number + header + size
end

#dump_hash(obj, variant, current_depth, config, log_object_errors) ⇒ Object



226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/rookout/processor/namespace_serializer2.rb', line 226

def dump_hash obj, variant, current_depth, config, log_object_errors
  variant.original_size = obj.length

  weighted_children_depth = current_depth + 1
  if current_depth <= config.max_collection_depth
    dump_variant_type variant, Com::Rookout::Variant::Type::VARIANT_MAP
    obj.each_with_index do |(key, value), index|
      break if index >= config.max_width
      variant.collection_keys << dump_raw_object(key, weighted_children_depth, config, log_object_errors)
      variant.collection_values << dump_raw_object(value, weighted_children_depth, config, log_object_errors)
      @estimated_pending_bytes += 6 # Header + size + header + size
    end
  else
    dump_variant_type_max_depth variant, Com::Rookout::Variant::Type::VARIANT_MAP
  end
end

#dump_integer(obj, variant) ⇒ Object



176
177
178
179
180
181
182
183
184
185
# File 'lib/rookout/processor/namespace_serializer2.rb', line 176

def dump_integer obj, variant
  if obj > INT32_MIN && obj < INT64_MAX
    dump_variant_type variant, Com::Rookout::Variant::Type::VARIANT_LONG
    variant.long_value = obj
  else
    dump_variant_type variant, Com::Rookout::Variant::Type::VARIANT_LARGE_INT
    variant.bytes_index_in_cache = get_string_index_in_cache obj.to_s
  end
  @estimated_pending_bytes += 3 # Header + number
end

#dump_nil(variant) ⇒ Object

rubocop:enable Style/ClassEqualityComparison rubocop:enable Metrics/AbcSize rubocop:enable Metrics/PerceivedComplexity rubocop:enable Metrics/CyclomaticComplexity



137
138
139
# File 'lib/rookout/processor/namespace_serializer2.rb', line 137

def dump_nil variant
  dump_variant_type variant, Com::Rookout::Variant::Type::VARIANT_NONE
end

#dump_numeric(obj, variant, config) ⇒ Object



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/rookout/processor/namespace_serializer2.rb', line 147

def dump_numeric obj, variant, config
  case obj
  when true
    dump_variant_type variant, Com::Rookout::Variant::Type::VARIANT_LONG
    variant.long_value = 1
    @estimated_pending_bytes += 2 # Header + short number
  when false
    dump_variant_type variant, Com::Rookout::Variant::Type::VARIANT_LONG
    variant.long_value = 0
    @estimated_pending_bytes += 2 # Header + short number
  when Integer
    dump_integer obj, variant
  when Float
    dump_variant_type variant, Com::Rookout::Variant::Type::VARIANT_DOUBLE
    variant.double_value = obj.to_f
    @estimated_pending_bytes += 7 # Header + 64 bit float
  when BigDecimal
    dump_string obj.to_s, variant, config # TODO: NS: This might cut the decimal value, is that ok?
  when Complex
    dump_variant_type variant, Com::Rookout::Variant::Type::VARIANT_COMPLEX
    variant.complex_value = Com::Rookout::Variant::Complex.new real: obj.real.to_f,
                                                               imaginary: obj.imaginary.to_f
    @estimated_pending_bytes += 8 # Large header + size + (header + 64 bit float) * 2
  else
    raise Exceptions::RookClassCannotBeSerialized.new(obj.class, "Unknown Numeric Type")
  end
  # TODO: ADD SUPPORT FOR RATIONALS
end

#dump_raw_object(obj, current_depth, config, log_object_errors) ⇒ Object



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/rookout/processor/namespace_serializer2.rb', line 85

def dump_raw_object obj, current_depth, config, log_object_errors
  unsafe_dump_object obj, current_depth, config, log_object_errors
rescue StandardError => e
  message = "Failed to serialize object"
  variant = Com::Rookout::Variant2.new
  @estimated_pending_bytes = 0
  dump_variant_type variant, Com::Rookout::Variant::Type::VARIANT_ERROR

  if log_object_errors
    Logger.instance.exception message, e

    error = RookError.new e, message
    UserWarnings.notify_warning error
  end
  variant
end

#dump_ruby_object_namespace(namespace, log_errors) ⇒ Object



81
82
83
# File 'lib/rookout/processor/namespace_serializer2.rb', line 81

def dump_ruby_object_namespace namespace, log_errors
  dump_raw_object namespace.obj, 0, namespace.dump_config, log_errors
end

#dump_string(obj, variant, config) ⇒ Object



187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/rookout/processor/namespace_serializer2.rb', line 187

def dump_string obj, variant, config
  obj = obj.to_s
  if obj.length > config.max_string
    final_obj = obj[0...config.max_string]
  else
    final_obj = obj
  end

  variant.original_size = obj.length
  dump_variant_type variant, Com::Rookout::Variant::Type::VARIANT_STRING
  variant.bytes_index_in_cache = get_string_index_in_cache final_obj
  @estimated_pending_bytes += 6 # Header + number + header + number
end

#dump_time(obj, variant) ⇒ Object



201
202
203
204
205
206
207
# File 'lib/rookout/processor/namespace_serializer2.rb', line 201

def dump_time obj, variant
  dump_variant_type variant, Com::Rookout::Variant::Type::VARIANT_TIME
  variant.time_value = Google::Protobuf::Timestamp.new
  variant.time_value.from_time obj

  @estimated_pending_bytes += 16 # Header + size + (header + 32 bit number + header + 64 bit number)
end

#dump_traceback_namespace(namespace) ⇒ Object



311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
# File 'lib/rookout/processor/namespace_serializer2.rb', line 311

def dump_traceback_namespace namespace
  variant = Com::Rookout::Variant2.new
  dump_variant_type variant, Com::Rookout::Variant::Type::VARIANT_TRACEBACK

  namespace.depth.times do |i|
    position = i + namespace.offset
    break if position >= namespace.stack_trace.length
    frame_info = namespace.stack_trace[position]

    code_object = Com::Rookout::Variant::CodeObject.new filename: frame_info.path,
                                                        lineno: frame_info.lineno,
                                                        name: frame_info.label
    variant.code_values << code_object
    # See dump_code_object
    @estimated_pending_bytes += 14 # Header + size + (header + number) * 4
  end
  variant
end

#dump_user_class(variant, obj, current_depth, config, log_object_errors) ⇒ Object



281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
# File 'lib/rookout/processor/namespace_serializer2.rb', line 281

def dump_user_class variant, obj, current_depth, config, log_object_errors
  weighted_children_depth = current_depth + 1
  if weighted_children_depth <= config.max_collection_depth
    dump_variant_type variant, Com::Rookout::Variant::Type::VARIANT_OBJECT

    obj.instance_variables.each do |name|
      raw_value = obj.instance_variable_get name
      variant.attribute_names_in_cache << get_string_index_in_cache(name.to_s)
      variant.attribute_values << dump_raw_object(raw_value, weighted_children_depth, config, log_object_errors)
      @estimated_pending_bytes += 6 # Header + number + header + number
    end
  else
    dump_variant_type_max_depth variant, Com::Rookout::Variant::Type::VARIANT_OBJECT
  end
end

#dump_variant_type(variant, type) ⇒ Object



45
46
47
48
# File 'lib/rookout/processor/namespace_serializer2.rb', line 45

def dump_variant_type variant, type
  variant.variant_type_max_depth = type << 1
  @estimated_pending_bytes += 2 # Field header + short number
end

#dump_variant_type_max_depth(variant, type) ⇒ Object



50
51
52
53
# File 'lib/rookout/processor/namespace_serializer2.rb', line 50

def dump_variant_type_max_depth variant, type
  variant.variant_type_max_depth = (type << 1) | 1
  @estimated_pending_bytes += 2 # Field header + short number
end

#get_string_index_in_cache(str) ⇒ Object



34
35
36
37
38
39
40
41
42
43
# File 'lib/rookout/processor/namespace_serializer2.rb', line 34

def get_string_index_in_cache str
  if @string_cache.key? str
    @string_cache[str]
  else
    @estimated_pending_bytes += str.length + 5
    current_size = @string_cache.size
    @string_cache.store str, current_size
    current_size
  end
end

#unsafe_dump_object(obj, current_depth, config, log_object_errors) ⇒ Object

rubocop:disable Metrics/AbcSize rubocop:disable Metrics/PerceivedComplexity rubocop:disable Metrics/CyclomaticComplexity rubocop:disable Style/ClassEqualityComparison



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/rookout/processor/namespace_serializer2.rb', line 106

def unsafe_dump_object obj, current_depth, config, log_object_errors
  variant = Com::Rookout::Variant2.new original_type_index_in_cache: get_string_index_in_cache(obj.class.to_s)

  if obj.nil?
    dump_nil variant
  elsif obj.is_a?(Numeric) || obj.is_a?(TrueClass) || obj.is_a?(FalseClass)
    dump_numeric obj, variant, config
  elsif obj.is_a?(String) || obj.is_a?(Symbol)
    dump_string obj, variant, config
  elsif obj.is_a? Time
    dump_time obj, variant
  elsif obj.class == Array
    dump_array obj, variant, current_depth, config, log_object_errors
  elsif obj.class == Hash || (!MASH.nil? && obj.is_a?(MASH)) ||
        (!HASH_WITH_INDIFFERENT_ACCESS.nil? && obj.is_a?(HASH_WITH_INDIFFERENT_ACCESS))
    dump_hash obj, variant, current_depth, config, log_object_errors
  elsif obj.is_a? Exception
    dump_exception obj, variant, current_depth, config, log_object_errors
  elsif obj.is_a?(Method) || obj.is_a?(Proc) || obj.is_a?(Class) || obj.is_a?(Module)
    dump_code_object obj, variant
  else
    dump_user_class variant, obj, current_depth, config, log_object_errors
  end

  variant
end