Class: BuilderApm::Doctor::BacktraceReducer

Inherits:
Object
  • Object
show all
Defined in:
lib/builder_apm/doctor/backtrace_reducer.rb

Constant Summary collapse

TOKEN_LIMIT =
10500

Instance Method Summary collapse

Constructor Details

#initializeBacktraceReducer

Returns a new instance of BacktraceReducer.



9
10
11
12
# File 'lib/builder_apm/doctor/backtrace_reducer.rb', line 9

def initialize
  @token_count = 0
  @ref_count = 0
end

Instance Method Details

#build_reduced_method(method) ⇒ Object



28
29
30
31
32
33
34
35
36
37
# File 'lib/builder_apm/doctor/backtrace_reducer.rb', line 28

def build_reduced_method(method)
  {
    "dur" => method.fetch("duration", 0.0).to_f.round(3),
    "method" => method.fetch("method", nil),
    "line" => method.fetch("method_line", nil),
    "trigger" => method.fetch("triggering_line", nil),
    "sql" => [],
    "children" => []
  }
end

#count_tokens(string) ⇒ Object



85
86
87
88
89
# File 'lib/builder_apm/doctor/backtrace_reducer.rb', line 85

def count_tokens(string)
  tokens = string.scan(/[\w']+|[.,!?;:]/)
  tokens = tokens.flat_map { |token| token.split(/(?<=[.,!?;:])$/) }
  tokens.length + 17
end

#increment_token_count(string) ⇒ Object



91
92
93
# File 'lib/builder_apm/doctor/backtrace_reducer.rb', line 91

def increment_token_count(string)
  @token_count += count_tokens(string)
end

#over_limit?Boolean

Returns:

  • (Boolean)


95
96
97
# File 'lib/builder_apm/doctor/backtrace_reducer.rb', line 95

def over_limit?
  @token_count + @ref_count > TOKEN_LIMIT
end

#process_children(method, reduced_method) ⇒ Object



49
50
51
52
53
54
55
56
# File 'lib/builder_apm/doctor/backtrace_reducer.rb', line 49

def process_children(method, reduced_method)
  method.fetch("children", []).each do  |child| 
    reduced_child = reduce_method(child)
    return if over_limit?

    reduced_method["children"] << reduced_child unless reduced_child.nil?
  end
end

#process_sql_events(method, reduced_method) ⇒ Object



39
40
41
42
43
44
45
46
47
# File 'lib/builder_apm/doctor/backtrace_reducer.rb', line 39

def process_sql_events(method, reduced_method)
  method.fetch("sql_events", []).each do |event| 
    sql_event = reduce_event(event) 
    return if over_limit? || (sql_event["dur"] < 1 && sql_event["dur"] > 0)

    reduced_method["sql"] << sql_event
    increment_token_count(sql_event.to_s)
  end
end

#reduce_backtrace(data: {}) ⇒ Object



99
100
101
# File 'lib/builder_apm/doctor/backtrace_reducer.rb', line 99

def reduce_backtrace(data: {})
  reduce_json(data["stack"]).to_s
end

#reduce_event(event) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/builder_apm/doctor/backtrace_reducer.rb', line 58

def reduce_event(event)
  params = event.fetch("params", [])
  params = short_hash(params) if params.size > 3
  # sql = truncate_string(event.fetch("sql", ""), 400)
  sql = truncate_string(event.fetch("sql", "").gsub("\"", ""), 400)

  {
    "dur" => event.fetch("duration", 0.0).to_f.round(3),
    "sql" => sql,
    "params" => params,
    "records" => event.fetch("record_count", 0),
    "trigger" => event.fetch("triggering_line", nil)
  }
end

#reduce_json(json) ⇒ Object



73
74
75
# File 'lib/builder_apm/doctor/backtrace_reducer.rb', line 73

def reduce_json(json)
  json.map { |method| reduce_method(method) }.compact
end

#reduce_method(method) ⇒ Object



14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/builder_apm/doctor/backtrace_reducer.rb', line 14

def reduce_method(method)
  return nil if over_limit?

  reduced_method = build_reduced_method(method)
  return nil if reduced_method["dur"] < 1 && reduced_method["dur"] > 0

  increment_token_count(reduced_method.to_json)

  process_sql_events(method, reduced_method)
  process_children(method, reduced_method)

  reduced_method
end

#short_hash(input_string) ⇒ Object



77
78
79
# File 'lib/builder_apm/doctor/backtrace_reducer.rb', line 77

def short_hash(input_string)
  Digest::MD5.hexdigest(input_string.join(','))[0...8]
end

#truncate_string(str, length) ⇒ Object



81
82
83
# File 'lib/builder_apm/doctor/backtrace_reducer.rb', line 81

def truncate_string(str, length)
  str.length > length ? str[0...length] + "..." : str
end