builder_apm 0.5.2 → 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 07c43e6b1dbdf3d82b799d3c3ef46bf0fb4e11c42c3879f902cf22a22cb408f8
4
- data.tar.gz: 31408d58904939d8b3fe95c5d515bef2fe2904a828de0849456f95b981fa0292
3
+ metadata.gz: 3ba1912b1e309f8f3c0f215eaa29be48724f52acfdfd82aa41b5238c739ec3cb
4
+ data.tar.gz: b97fad9c760392060531925110503806d57d4ab72402054512006077d391ee08
5
5
  SHA512:
6
- metadata.gz: 1ec5e7f2e393b0ab717fbe6b294772eaa0d0ea1d6f2b1be6cd695c8d3aab3ca82a8998a8aad4c86e279f4d38e056780c57afc5216a4b60e350abff933f45d88c
7
- data.tar.gz: 9f2a147042b4b0dc40c694d708da5dcb53b120da5d6347e96bc7c1e0d6b72d4d94a81fa52c67a5f1107b5c82e155a1bfcc3a37d966929eb1c11f47128c0935bf
6
+ metadata.gz: e401a85d41e465c1845b6a3c5ed98e9b04b906e792549831636b5f7fa5571567fe10e62fc3244d2337d3822d6aa67ddb59583cf8d0e5534e95cb5e84145da807
7
+ data.tar.gz: d3bd84d4d9c4c35880e9cb3d30c8bb27af8021223dd6e97ec570b53090741232b07d65b9727345047e2c7ded811cc91446ce631a4e7cefa1abc7767c4ec3c117
@@ -346,6 +346,7 @@
346
346
 
347
347
  // Check if results are more than 50
348
348
  if (item.record_count > 50) {
349
+ resultsSpan.append('🚨');
349
350
  resultsSpan.addClass('highlight-results').attr('title', "This is a large number of results. Review if this can be paginated or limited.");
350
351
  }
351
352
 
@@ -1,54 +1,56 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
- <head>
4
- <title>BuilderApm Dashboard</title>
5
- <%= render 'builder_apm/css/main' %>
6
- <%= render 'builder_apm/css/dark' %>
7
- <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
8
- <script src="https://cdnjs.cloudflare.com/ajax/libs/dygraph/2.1.0/dygraph.min.js"></script>
9
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/dygraph/2.1.0/dygraph.min.css" />
10
- <%= render 'builder_apm/js/data_fetcher' %>
11
- <script>
12
- $(document).ready(function() {
3
+ <head>
4
+ <title>BuilderApm Dashboard</title>
5
+ <%= render 'builder_apm/css/main' %>
6
+ <%= render 'builder_apm/css/dark' %>
7
+ <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
8
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/dygraph/2.1.0/dygraph.min.js"></script>
9
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/dygraph/2.1.0/dygraph.min.css"/>
10
+ <%= render 'builder_apm/js/data_fetcher' %>
11
+ <script>
12
+ $(document).ready(function () { // Check for saved 'darkMode' in localStorage
13
+ if (localStorage.getItem('darkMode') === 'true') {
14
+ $('body').addClass('dark');
15
+ }
13
16
 
14
- // Check for saved 'darkMode' in localStorage
15
- if (localStorage.getItem('darkMode') === 'true') {
16
- $('body').addClass('dark');
17
- }
17
+ $('#clearData').on('click', function () {
18
+ localStorage.removeItem('builder_apm_requests');
19
+ localStorage.removeItem('builder_apm_cursor');
20
+ alert('Local Data Cleared');
21
+ });
22
+ $('#darkModeToggle').on('click', function () {
23
+ $('body').toggleClass('dark');
18
24
 
19
- $('#clearData').on('click', function() {
20
- localStorage.removeItem('builder_apm_requests');
21
- localStorage.removeItem('builder_apm_cursor');
22
- alert('Local Data Cleared');
23
- });
24
- $('#darkModeToggle').on('click', function() {
25
- $('body').toggleClass('dark');
26
-
27
- // Save the current mode in localStorage
28
- if ($('body').hasClass('dark')) {
29
- localStorage.setItem('darkMode', 'true');
30
- } else {
31
- localStorage.setItem('darkMode', 'false');
32
- }
33
- });
34
- $('body').show();
35
- });
36
- </script>
37
- </head>
38
- <body>
39
- <h1 id="header">BuilderApm Dashboard<span class="version"> (<%= BuilderApm::VERSION %>)</span></h1>
40
- <nav id="navbar">
41
- <ul>
42
- <li><%= link_to 'Dashboard', dashboard_path, class: ("active" if current_page?(dashboard_path)) %></li>
43
- <li><%= link_to 'Request Analysis', request_analysis_path, class: ("active" if current_page?(request_analysis_path)) %></li>
44
- <li><%= link_to '500 Errors', errors_500_path, class: ("active" if current_page?(errors_500_path)) %></li>
45
- <li><%= link_to 'Recent Requests', recent_requests_path, class: ("active" if current_page?(recent_requests_path)) %></li>
46
- <li><%= link_to 'Slow Requests', slow_requests_path, class: ("active" if current_page?(slow_requests_path)) %></li>
47
- <li><%= link_to 'N+1', n_plus_one_path, class: ("active" if current_page?(n_plus_one_path)) %></li>
48
- <li id="dark-mode-toggle"><button id="darkModeToggle" class="nav-button">Toggle Dark Mode</button></li>
49
- </ul>
50
- </nav>
51
- <div id="options">
52
- <input type="checkbox" id="autoUpdate" name="autoUpdate">
53
- <label for="autoUpdate">Auto-Update</label>
54
- </div>
25
+ // Save the current mode in localStorage
26
+ if ($('body').hasClass('dark')) {
27
+ localStorage.setItem('darkMode', 'true');
28
+ } else {
29
+ localStorage.setItem('darkMode', 'false');
30
+ }
31
+ });
32
+ $('body').show();
33
+ });
34
+ </script>
35
+ </head>
36
+ <body>
37
+ <h1 id="header">BuilderApm Dashboard<span class="version">
38
+ (<%= BuilderApm::VERSION %>)</span>
39
+ </h1>
40
+ <nav id="navbar">
41
+ <ul>
42
+ <li><%= link_to 'Dashboard', dashboard_path, class: ("active" if current_page?(dashboard_path)) %></li>
43
+ <li><%= link_to 'Request Analysis', request_analysis_path, class: ("active" if current_page?(request_analysis_path)) %></li>
44
+ <li><%= link_to '500 Errors', errors_500_path, class: ("active" if current_page?(errors_500_path)) %></li>
45
+ <li><%= link_to 'Recent Requests', recent_requests_path, class: ("active" if current_page?(recent_requests_path)) %></li>
46
+ <li><%= link_to 'Slow Requests', slow_requests_path, class: ("active" if current_page?(slow_requests_path)) %></li>
47
+ <li><%= link_to 'N+1', n_plus_one_path, class: ("active" if current_page?(n_plus_one_path)) %></li>
48
+ <li id="dark-mode-toggle">
49
+ <button id="darkModeToggle" class="nav-button">Toggle Dark Mode</button>
50
+ </li>
51
+ </ul>
52
+ </nav>
53
+ <div id="options">
54
+ <input type="checkbox" id="autoUpdate" name="autoUpdate">
55
+ <label for="autoUpdate">Load Older data</label>
56
+ </div>
@@ -17,7 +17,7 @@ module BuilderApm
17
17
  @enable_n_plus_one_profiler = true
18
18
  @api_key = nil
19
19
  @api = 'Bravo'
20
- @gems_to_track = ["bx_block_"]
20
+ @gems_to_track = []
21
21
  end
22
22
  end
23
23
  end
@@ -20,6 +20,8 @@ module BuilderApm
20
20
  uuid = event.payload[:headers].env['action_dispatch.request_id']
21
21
  Thread.current[:request_id] = uuid
22
22
  Thread.current[:stack] = [setup_controller_stack_data(event)]
23
+ Thread.current[:method_tracing] = 0
24
+ Thread.current[:db_tracing] = 0
23
25
  end
24
26
 
25
27
  def process_action(event)
@@ -23,80 +23,57 @@ module BuilderApm
23
23
  me.process_trace_point(tp) if me.valid_trace_point?(tp)
24
24
  duration = (Time.now.to_f * 1000) - starttime
25
25
 
26
- Thread.current["method_tracing"] = (Thread.current["method_tracing"] ||= 0) + duration
26
+ Thread.current[:method_tracing] = (Thread.current[:method_tracing] ||= 0) + duration
27
27
  end
28
28
  end
29
29
 
30
30
  def valid_trace_point?(tp)
31
- # return !Thread.current[:request_id].nil?
32
- !Thread.current[:request_id].nil? && not_controller_endpoint(tp) && tp.path.start_with?(@root_path)
33
- end
34
-
35
- def not_controller_endpoint(tp)
36
- start_controller = Thread.current[:stack]&.first || nil
37
-
38
- return false unless start_controller
39
-
40
- "#{tp.defined_class}##{tp.method_id}" != start_controller[:method]
41
- end
42
-
43
- def valid_gem_path(tp)
44
- not_this_gem = !tp.path.start_with?(@this_gem_path)
45
- is_a_tracked_gem = tp.path.split(File::SEPARATOR).any? { |folder| folder.start_with?(*gems_to_track) }
46
- is_a_rails_app_file = tp.path.start_with?(@root_path)
47
-
48
- not_this_gem && (is_a_tracked_gem || is_a_rails_app_file)
31
+ return false unless Thread.current[:request_id]
32
+ return false unless tp.path.start_with?(@root_path)
33
+ # return false if tp.path.start_with?(@this_gem_path)
34
+
35
+ start_controller = Thread.current[:stack]&.first
36
+ return false if start_controller && "#{tp.defined_class}##{tp.method_id}" == start_controller[:method]
37
+
38
+ gems_to_track = BuilderApm.configuration.gems_to_track
39
+ gems_to_track.any? { |gem| tp.path.include?(File::SEPARATOR + gem) }
49
40
  end
50
41
 
51
42
  def process_trace_point(tp)
52
43
  if tp.event == :call || tp.event == :b_call || tp.event == :c_call
53
- process_call_event(tp)
44
+ method_id = "#{tp.defined_class}##{tp.method_id}"
45
+ (@call_times[method_id]||= []) << Process.clock_gettime(Process::CLOCK_MONOTONIC)
46
+ caller_info = caller_locations(4,1).first
47
+ calling_file_path = caller_info.absolute_path
48
+ calling_line_number = caller_info.lineno
49
+
50
+ method_call = {
51
+ method: method_id,
52
+ method_line: "#{tp.path.gsub(@root_path, '')}:#{tp.lineno}",
53
+ triggering_line: "#{calling_file_path.gsub(@root_path, '')}:#{calling_line_number}",
54
+ children: [],
55
+ start_time: Time.now.to_f * 1000,
56
+ sql_events: []
57
+ }
58
+
59
+ (Thread.current[:stack] ||= []).push(method_call)
54
60
  else
55
- process_return_event(tp)
56
- end
57
- end
58
-
59
- private
60
-
61
- def gems_to_track
62
- @gems_to_track = BuilderApm.configuration.gems_to_track
63
- end
64
-
65
- def process_call_event(tp)
66
- method_id = "#{tp.defined_class}##{tp.method_id}"
67
- (@call_times[method_id]||= []) << Process.clock_gettime(Process::CLOCK_MONOTONIC)
68
- caller_info = caller_locations(4,1).first
69
- calling_file_path = caller_info.absolute_path
70
- calling_line_number = caller_info.lineno
71
-
72
- method_call = {
73
- method: method_id,
74
- method_line: "#{tp.path.gsub(@root_path, '')}:#{tp.lineno}",
75
- triggering_line: "#{calling_file_path.gsub(@root_path, '')}:#{calling_line_number}",
76
- children: [],
77
- start_time: Time.now.to_f * 1000,
78
- sql_events: []
79
- }
80
-
81
- (Thread.current[:stack] ||= []).push(method_call)
82
- end
83
-
84
- def process_return_event(tp)
85
- method_id = "#{tp.defined_class}##{tp.method_id}"
86
-
87
- if @call_times.key?(method_id)
88
- elapsed_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) - @call_times[method_id].pop
89
- elapsed_time_in_ms = (elapsed_time * 1000).round(3)
90
- @call_times.delete(method_id)
91
-
92
- method_call = (Thread.current[:stack] ||= []).pop
93
- method_call[:end_time] = Time.now.to_f * 1000
94
- method_call[:duration] = elapsed_time_in_ms
95
-
96
- if Thread.current[:stack]&.any?
97
- Thread.current[:stack].last[:children].push(method_call)
98
- else
99
- Thread.current[:stack].push(method_call)
61
+ method_id = "#{tp.defined_class}##{tp.method_id}"
62
+
63
+ if @call_times.key?(method_id)
64
+ elapsed_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) - @call_times[method_id].pop
65
+ elapsed_time_in_ms = (elapsed_time * 1000).round(3)
66
+ @call_times.delete(method_id)
67
+
68
+ method_call = (Thread.current[:stack] ||= []).pop
69
+ method_call[:end_time] = Time.now.to_f * 1000
70
+ method_call[:duration] = elapsed_time_in_ms
71
+
72
+ if Thread.current[:stack]&.any?
73
+ Thread.current[:stack].last[:children].push(method_call)
74
+ else
75
+ Thread.current[:stack].push(method_call)
76
+ end
100
77
  end
101
78
  end
102
79
  end
@@ -7,6 +7,7 @@ module BuilderApm
7
7
  end
8
8
 
9
9
  def call(env)
10
+ start_time = Time.now.to_f * 1000
10
11
  request_id = env["action_dispatch.request_id"]
11
12
  Thread.current[:request_id] = request_id
12
13
  Thread.current[:n_plus_one_duration] = 0
@@ -14,7 +15,6 @@ module BuilderApm
14
15
  Thread.current[:db_runtime] = 0
15
16
  Thread.current[:method_tracing] = 0
16
17
  Thread.current[:db_tracing] = 0
17
- start_time = Time.now.to_f * 1000
18
18
 
19
19
  @status, @headers, @response = @app.call(env)
20
20
 
@@ -1,3 +1,3 @@
1
1
  module BuilderApm
2
- VERSION = "0.5.2"
2
+ VERSION = "0.5.4"
3
3
  end
@@ -1,9 +1,9 @@
1
1
  BuilderApm.configure do |config|
2
- config.redis_url = 'redis://localhost:6379/0'
3
- config.enable_controller_profiler = true
4
- config.enable_active_record_profiler = true
5
- config.enable_methods_profiler = true
6
- # config.api_key = ENV["OPENAI_API_KEY"]
7
- # config.api = ENV["API_AI"] # "Bravo" - internal Ai | "OpenAi" - use openai ChatGPT
8
- config.gems_to_track = ["bx_block_"] #partial and full gem names can be used.
9
- end
2
+ config.redis_url = 'redis://localhost:6379/0' # optional - defaults to 'redis://localhost:6379/0'
3
+ config.api_key = ENV["OPENAI_API_KEY"] #required only if you want to use Ai Doctor
4
+ config.api = "Bravo" # optional - default to 'Bravo' - "Bravo" - internal Ai / "OpenAi" - use openai ChatGPT
5
+ config.gems_to_track = [] # optional - default to empty array []
6
+ config.enable_controller_profiler = true # optional - defaults to true
7
+ config.enable_active_record_profiler = true # optional - defaults to true
8
+ config.enable_methods_profiler = true # optional - defaults to true
9
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: builder_apm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.5.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Ketelle