simple_apm 1.1.1 → 1.1.2

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.
@@ -1,7 +1,7 @@
1
1
  <!DOCTYPE html>
2
- <html>
2
+ <html lang="<%= simple_apm_locale %>">
3
3
  <head>
4
- <title>Simple Apm</title>
4
+ <title><%= t("simple_apm.#{action_name}.title", default: 'Simple APM') %> · Simple APM</title>
5
5
  <meta charset="utf-8">
6
6
  <meta content="IE=Edge,chrome=1" http-equiv="X-UA-Compatible">
7
7
  <meta content="width=device-width, initial-scale=1.0" name="viewport">
@@ -12,36 +12,18 @@
12
12
  <script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
13
13
  <script src="//cdnjs.cloudflare.com/ajax/libs/echarts/4.1.0/echarts.js"></script>
14
14
  <script src="//cdn.datatables.net/1.10.15/js/jquery.dataTables.min.js"></script>
15
- <script type="text/javascript">
16
- // JqueryDataTable自定义排序方法
17
- jQuery.extend(jQuery.fn.dataTableExt.oSort, {
18
- "sec-pre": function (a) {
19
- var x = String(a).replace(/<[\s\S]*?>/g, ""); //去除html标记
20
- x = x.replace(/&amp;nbsp;/ig, ""); //去除空格
21
- x = x.replace(/%/, ""); //去除百分号
22
- if (x.indexOf('ms') > 0) {
23
- x = x.replace(/ms/, "");
24
- return parseFloat(x) / 1000;
25
- } else if (x.indexOf('min') > 0) {
26
- x = x.replace(/min/, "");
27
- return parseFloat(x) * 60;
28
- } else {
29
- x = x.replace(/min/, "");
30
- return parseFloat(x)
31
- }
32
- },
33
- "sec-asc": function (a, b) { //正序排序引用方法
34
- return ((a < b) ? -1 : ((a > b) ? 1 : 0));
35
- },
36
- "sec-desc": function (a, b) { //倒序排序引用方法
37
- return ((a < b) ? 1 : ((a > b) ? -1 : 0));
38
- }
39
- });
40
- </script>
15
+ <script type="application/json" id="apm-ui-config"><%= json_escape({
16
+ table: table_language,
17
+ copied: t('simple_apm.diagnostics.copied'),
18
+ copy_failed: t('simple_apm.diagnostics.copy_failed'),
19
+ load_error: t('simple_apm.index.load_error')
20
+ }.to_json).html_safe %></script>
21
+ <%= javascript_include_tag "simple_apm/application" %>
41
22
 
42
23
  <%= csrf_meta_tags %>
43
24
  </head>
44
25
  <body class="simple-apm">
26
+ <a class="apm-skip-link" href="#main-content"><%= t('simple_apm.common.skip_content') %></a>
45
27
  <div id="page-container" class="apm-shell">
46
28
  <nav class="apm-topbar">
47
29
  <div class="apm-topbar-inner">
@@ -52,14 +34,14 @@
52
34
  <div class="apm-nav">
53
35
  <%
54
36
  [
55
- [dashboard_path, t("simple_apm.layout.nav_dashboard")],
56
- [index_path, t("simple_apm.layout.nav_slow_requests")],
57
- [actions_path, t("simple_apm.layout.nav_actions")],
58
- [data_path, t("simple_apm.layout.nav_data")]
37
+ [dashboard_path(apm_date: apm_date), t("simple_apm.layout.nav_dashboard"), %w[dashboard]],
38
+ [index_path(apm_date: apm_date), t("simple_apm.layout.nav_slow_requests"), %w[index show]],
39
+ [actions_path(apm_date: apm_date), t("simple_apm.layout.nav_actions"), %w[actions action_info]],
40
+ [data_path(apm_date: apm_date), t("simple_apm.layout.nav_data"), %w[data]]
59
41
  ].each do |m|
60
42
  %>
61
- <a class="navbar-brand <%= 'active' if request.url =~ /#{m[0]}/ %>"
62
- href="<%= m[0] %>" >
43
+ <a class="navbar-brand <%= 'active' if m[2].include?(action_name) %>"
44
+ href="<%= m[0] %>" <%= 'aria-current=page' if m[2].include?(action_name) %>>
63
45
  <%= m[1] %>
64
46
  </a>
65
47
  <% end %>
@@ -72,12 +54,22 @@
72
54
  <% end %>
73
55
  </div>
74
56
  <div class="select-apm-date apm-date-select">
75
- <span><%= t("simple_apm.layout.date") %></span>
76
- <%= select_tag 'apm_date', options_for_select(SimpleApm::Redis.in_apm_days, apm_date), class: 'form-control' %>
57
+ <% date_path = action_name == 'show' ? (@request ? action_info_path : index_path) : request.path %>
58
+ <%= form_tag date_path, method: :get, class: 'apm-date-form' do %>
59
+ <label for="apm_date"><%= t("simple_apm.layout.date") %></label>
60
+ <%= hidden_field_tag :action_name, @request.action_name if action_name == 'show' && @request %>
61
+ <%= hidden_field_tag :action_name, @action.name if action_name == 'action_info' && @action %>
62
+ <%= hidden_field_tag :count, @sample_limit if action_name == 'index' %>
63
+ <%= select_tag 'apm_date', options_for_select((SimpleApm::Redis.in_apm_days + [apm_date]).uniq.sort.reverse, apm_date), class: 'form-control' %>
64
+ <noscript><button type="submit" class="btn btn-primary"><%= t('simple_apm.common.apply') %></button></noscript>
65
+ <% end %>
77
66
  </div>
78
67
  </div>
79
68
  </nav>
80
- <main class="apm-content">
69
+ <main id="main-content" class="apm-content" tabindex="-1">
70
+ <% if flash[:notice].present? %>
71
+ <div class="apm-notice" role="status"><%= flash[:notice] %></div>
72
+ <% end %>
81
73
  <%= yield %>
82
74
  </main>
83
75
  </div>
@@ -113,14 +105,19 @@
113
105
  <% end %>
114
106
  </div>
115
107
  </footer>
116
- <div id="sql-modal" class="modal" aria-hidden="true" role="dialog" style="display: none;" tabindex="-1">
108
+ <div id="sql-modal" class="modal" aria-hidden="true" aria-labelledby="sql-modal-title" role="dialog" style="display: none;" tabindex="-1">
117
109
  <div class="modal-dialog modal-lg modal-dialog-popout">
118
110
  <div class="apm-modal-panel">
119
111
  <div class="apm-modal-header">
120
- <div class="apm-modal-title">SQL</div>
112
+ <h2 id="sql-modal-title" class="apm-modal-title">SQL</h2>
113
+ <div class="apm-toolbar-actions">
114
+ <button type="button" class="btn btn-primary" data-copy-target="sql-modal-text"><%= t('simple_apm.common.copy') %></button>
115
+ <button type="button" class="btn apm-button-secondary" data-dismiss="modal"><%= t('simple_apm.common.close') %></button>
116
+ </div>
121
117
  </div>
122
118
  <div class="apm-modal-body">
123
- <pre class="modal-content" data-lang="SQL"></pre>
119
+ <pre id="sql-modal-text" class="modal-content" data-lang="SQL"></pre>
120
+ <p class="apm-copy-status" role="status" aria-live="polite"></p>
124
121
  </div>
125
122
  </div>
126
123
 
@@ -128,22 +125,4 @@
128
125
  </div>
129
126
 
130
127
  </body>
131
- <script>
132
- <% if flash[:notice].present? %>
133
- alert(<%= flash[:notice].to_json.html_safe %>)
134
- <% end %>
135
- var sql_modal_obj = $('#sql-modal')
136
- $('.select-apm-date select').on('change', function () {
137
- window.location.href = '<%= set_apm_date_path %>?apm_date=' + this.value
138
- })
139
- $('.sql').on('click', function () {
140
- sql_modal_obj.find('.modal-content').html($(this).html())
141
- sql_modal_obj.modal('show')
142
- })
143
- // 手写部分ujs
144
- $("a[data-confirm]").on('click', function () {
145
- return confirm($(this).data('confirm'))
146
- })
147
-
148
- </script>
149
128
  </html>
@@ -0,0 +1,17 @@
1
+ <section class="apm-panel apm-export">
2
+ <div class="apm-panel-header">
3
+ <div>
4
+ <h2 class="apm-panel-title"><%= t("simple_apm.diagnostics.title") %></h2>
5
+ <p class="apm-panel-subtitle"><%= t("simple_apm.diagnostics.hint") %></p>
6
+ </div>
7
+ <button type="button" class="btn btn-primary" data-copy-target="diagnostic-report"><%= t("simple_apm.diagnostics.copy") %></button>
8
+ </div>
9
+ <div class="apm-panel-body">
10
+ <details>
11
+ <summary><%= t("simple_apm.diagnostics.preview") %></summary>
12
+ <label class="sr-only" for="diagnostic-report"><%= t("simple_apm.diagnostics.title") %></label>
13
+ <textarea id="diagnostic-report" class="apm-report-text apm-mono" readonly rows="14" spellcheck="false"><%= JSON.pretty_generate(report) %></textarea>
14
+ </details>
15
+ <p class="apm-copy-status" role="status" aria-live="polite"></p>
16
+ </div>
17
+ </section>
@@ -0,0 +1,18 @@
1
+ <section class="apm-panel">
2
+ <div class="apm-panel-header">
3
+ <div>
4
+ <h2 class="apm-panel-title"><%= t('simple_apm.show.timing_title') %></h2>
5
+ <p class="apm-panel-subtitle"><%= t('simple_apm.show.timing_hint') %></p>
6
+ </div>
7
+ </div>
8
+ <div class="apm-panel-body">
9
+ <% parts.each do |label, duration| %>
10
+ <% percentage = duration_percent(duration, total) %>
11
+ <div class="apm-runtime-row">
12
+ <span><%= label %></span>
13
+ <meter min="0" max="100" value="<%= percentage %>" aria-label="<%= label %>"><%= percentage %>%</meter>
14
+ <span><%= sec_str duration %> · <%= percentage %>%</span>
15
+ </div>
16
+ <% end %>
17
+ </div>
18
+ </section>
@@ -1,34 +1,42 @@
1
+ <nav class="apm-breadcrumb" aria-label="<%= t('simple_apm.action_info.title') %>">
2
+ <%= link_to t('simple_apm.common.back_actions'), actions_path(apm_date: apm_date) %>
3
+ </nav>
1
4
  <div class="apm-page-header">
2
5
  <div>
3
6
  <h1 class="apm-page-title"><%= t("simple_apm.action_info.title") %></h1>
4
- <p class="apm-page-subtitle"><%= @action.name %></p>
7
+ <p class="apm-page-subtitle apm-mono"><%= @action.name %> · <%= apm_date %></p>
5
8
  </div>
6
9
  </div>
7
10
 
8
11
  <div class="apm-metrics">
9
12
  <div class="apm-stat">
10
13
  <p class="apm-stat-label"><%= t("simple_apm.action_info.daily_hits") %></p>
11
- <div class="apm-stat-value"><%= @action.click_count %></div>
14
+ <div class="apm-stat-value"><%= number_with_delimiter @action.click_count.to_i %></div>
12
15
  </div>
13
16
  <div class="apm-stat">
14
17
  <p class="apm-stat-label"><%= t("simple_apm.action_info.avg_response_time") %></p>
15
- <div class="apm-stat-value"><%= sec_str @action.time.to_f/@action.click_count.to_i %></div>
18
+ <div class="apm-stat-value"><%= sec_str @action.avg_time %></div>
16
19
  </div>
17
20
  <div class="apm-stat">
18
21
  <p class="apm-stat-label"><%= t("simple_apm.action_info.avg_db_time") %></p>
19
22
  <div class="apm-stat-value"><%= sec_str @action.avg_db_time %></div>
23
+ <div class="apm-stat-meta"><%= t('simple_apm.action_info.avg_http_time') %>: <%= sec_str @action.avg_http_time %></div>
20
24
  </div>
21
25
  <div class="apm-stat">
22
26
  <p class="apm-stat-label"><%= t("simple_apm.action_info.avg_sql_count") %></p>
23
27
  <div class="apm-stat-value"><%= @action.avg_queries_count.round(1) %></div>
28
+ <div class="apm-stat-meta"><%= t('simple_apm.action_info.cached_queries') %>: <%= @action.avg_cached_queries_count.round(1) %></div>
24
29
  </div>
25
30
  <div class="apm-stat">
26
31
  <p class="apm-stat-label"><%= t("simple_apm.action_info.slowest_response_time") %></p>
27
- <div class="apm-stat-value"><%= link_to sec_str(@action.slow_time), show_path(id: @action.slow_id) %></div>
28
- <div class="apm-stat-meta"><%= t("simple_apm.action_info.fastest") %> <%= link_to sec_str(@action.fast_time), show_path(id: @action.fast_id) %></div>
32
+ <div class="apm-stat-value"><%= link_to sec_str(@action.slow_time), show_path(id: @action.slow_id, apm_date: apm_date) %></div>
33
+ <div class="apm-stat-meta"><%= t("simple_apm.action_info.fastest") %> <%= link_to sec_str(@action.fast_time), show_path(id: @action.fast_id, apm_date: apm_date) %></div>
29
34
  </div>
30
35
  </div>
31
36
 
37
+ <%= render 'diagnostic_export', report: SimpleApm::DiagnosticReport.for_action(@action, date: apm_date) %>
38
+ <%= render 'timings', total: @action.avg_time, parts: [[t('simple_apm.common.db'), @action.avg_db_time], [t('simple_apm.common.http'), @action.avg_http_time]] %>
39
+
32
40
  <section class="apm-panel">
33
41
  <div class="apm-panel-header">
34
42
  <div>
@@ -38,36 +46,49 @@
38
46
  </div>
39
47
  <div class="apm-panel-body">
40
48
  <div class="apm-table-wrap">
41
- <table class="table table-bordered">
49
+ <table id="action-samples" class="table">
50
+ <thead>
42
51
  <tr>
43
52
  <th><%= t("simple_apm.action_info.response_time") %></th>
53
+ <th><%= t('simple_apm.common.db') %></th>
54
+ <th><%= t('simple_apm.common.sql') %></th>
55
+ <th><%= t('simple_apm.common.view') %></th>
56
+ <th><%= t('simple_apm.common.http') %></th>
44
57
  <th><%= t("simple_apm.action_info.access_time") %></th>
45
58
  <th><%= t("simple_apm.action_info.memory_delta") %></th>
46
59
  <th><%= t("simple_apm.action_info.request_id") %></th>
60
+ <th><%= t('simple_apm.common.status') %></th>
47
61
  <th><%= t("simple_apm.action_info.ip") %></th>
48
62
  <th><%= t("simple_apm.common.server") %></th>
49
63
  </tr>
64
+ </thead>
65
+ <tbody>
50
66
  <% @action.slow_requests.each do |slow_request| %>
51
67
  <%
52
68
  r = slow_request.request
53
69
  next if r.blank?
54
70
  %>
55
71
  <tr>
56
- <td>
57
- <%= sec_str r.during %>
58
- (DB: <%= sec_str r.db_runtime %> ,
59
- SQL: <%= r.queries_count.to_i %> ,
60
- <%= t("simple_apm.common.view") %>: <%= sec_str r.view_runtime %>
61
- <%= "HTTP: #{sec_str r.net_http_during}" if r.net_http_during.to_f > 0 %>)
62
- </td>
72
+ <td data-order="<%= r.during.to_f %>"><%= link_to sec_str(r.during), show_path(id: r.request_id, apm_date: apm_date) %></td>
73
+ <td data-order="<%= r.db_runtime.to_f %>"><%= sec_str r.db_runtime %></td>
74
+ <td><%= r.queries_count.to_i %></td>
75
+ <td data-order="<%= r.view_runtime.to_f %>"><%= sec_str r.view_runtime %></td>
76
+ <td data-order="<%= r.net_http_during.to_f %>"><%= sec_str r.net_http_during %></td>
63
77
  <td><%= time_label r.started %></td>
64
- <td><%= r.memory_during.to_f.round(1) %></td>
65
- <td><%= link_to r.request_id, show_path(id: r.request_id) %></td>
78
+ <td data-order="<%= r.memory_during.to_f %>"><%= r.memory_during.to_f.round(1) %> MB</td>
79
+ <td class="apm-mono"><%= link_to r.request_id, show_path(id: r.request_id, apm_date: apm_date) %></td>
80
+ <td><%= r.status.presence || t('simple_apm.common.unknown') %></td>
66
81
  <td><%= r.remote_addr %></td>
67
82
  <td><%= r.host %></td>
68
83
  </tr>
69
84
  <% end %>
85
+ </tbody>
70
86
  </table>
71
87
  </div>
72
88
  </div>
73
89
  </section>
90
+ <script>
91
+ $(function () {
92
+ $('#action-samples').DataTable(window.SimpleApmUI.tableOptions({order: [[0, 'desc']]}));
93
+ });
94
+ </script>
@@ -5,6 +5,25 @@
5
5
  </div>
6
6
  </div>
7
7
 
8
+ <% total_hits = @actions.sum { |action| action.click_count.to_i } %>
9
+ <div class="apm-metrics apm-metrics-compact">
10
+ <div class="apm-stat">
11
+ <p class="apm-stat-label"><%= t("simple_apm.actions.action_count") %></p>
12
+ <div class="apm-stat-value"><%= number_with_delimiter(@actions.length) %></div>
13
+ <div class="apm-stat-meta"><%= apm_date %></div>
14
+ </div>
15
+ <div class="apm-stat">
16
+ <p class="apm-stat-label"><%= t("simple_apm.actions.total_hits") %></p>
17
+ <div class="apm-stat-value"><%= number_with_delimiter(total_hits) %></div>
18
+ <div class="apm-stat-meta"><%= t("simple_apm.dashboard.current_day_total") %></div>
19
+ </div>
20
+ <div class="apm-stat">
21
+ <p class="apm-stat-label"><%= t("simple_apm.actions.weighted_avg_response") %></p>
22
+ <div class="apm-stat-value"><%= total_hits.positive? ? sec_str(@actions.sum { |action| action.time.to_f } / total_hits) : '—' %></div>
23
+ <div class="apm-stat-meta"><%= t("simple_apm.actions.summary_hint") %></div>
24
+ </div>
25
+ </div>
26
+
8
27
  <section class="apm-panel">
9
28
  <div class="apm-panel-header">
10
29
  <div>
@@ -17,27 +36,28 @@
17
36
  <table id="actions-table" class="table">
18
37
  <thead>
19
38
  <tr>
20
- <th><%= t("simple_apm.actions.name") %></th>
21
- <th><%= t("simple_apm.actions.click_count") %></th>
22
- <th><%= t("simple_apm.actions.avg_response_time") %></th>
23
- <th><%= t("simple_apm.actions.avg_db_time") %></th>
24
- <th><%= t("simple_apm.actions.avg_sql_count") %></th>
25
- <th><%= t("simple_apm.actions.avg_http_time") %></th>
26
- <th><%= t("simple_apm.actions.fastest_response_time") %></th>
27
- <th><%= t("simple_apm.actions.slowest_response_time") %></th>
39
+ <th scope="col"><%= t("simple_apm.actions.name") %></th>
40
+ <th scope="col"><%= t("simple_apm.actions.click_count") %></th>
41
+ <th scope="col"><%= t("simple_apm.actions.avg_response_time") %></th>
42
+ <th scope="col"><%= t("simple_apm.actions.avg_db_time") %></th>
43
+ <th scope="col"><%= t("simple_apm.actions.avg_sql_count") %></th>
44
+ <th scope="col"><%= t("simple_apm.actions.avg_http_time") %></th>
45
+ <th scope="col"><%= t("simple_apm.actions.fastest_response_time") %></th>
46
+ <th scope="col"><%= t("simple_apm.actions.slowest_response_time") %></th>
28
47
  </tr>
29
48
  </thead>
30
49
  <tbody>
31
50
  <% @actions.each do |action| %>
51
+ <% has_hits = action.click_count.to_i.positive? %>
32
52
  <tr>
33
- <td><%= link_to action.name, action_info_path(action_name: action.name) %></td>
34
- <td><%= action.click_count %></td>
35
- <td><%= sec_str action.avg_time %></td>
36
- <td><%= sec_str action.avg_db_time %></td>
37
- <td><%= action.avg_queries_count.round(1) %></td>
38
- <td><%= sec_str action.avg_http_time %></td>
39
- <td><%= link_to sec_str(action.fast_time), show_path(id: action.fast_id) %></td>
40
- <td><%= link_to sec_str(action.slow_time), show_path(id: action.slow_id) %></td>
53
+ <td class="apm-mono"><%= link_to action.name, action_info_path(action_name: action.name, apm_date: apm_date) %></td>
54
+ <td data-order="<%= action.click_count.to_i %>"><%= number_with_delimiter(action.click_count.to_i) %></td>
55
+ <td data-order="<%= has_hits ? action.avg_time : 0 %>"><%= has_hits ? sec_str(action.avg_time) : '—' %></td>
56
+ <td data-order="<%= has_hits ? action.avg_db_time : 0 %>"><%= has_hits ? sec_str(action.avg_db_time) : '—' %></td>
57
+ <td data-order="<%= has_hits ? action.avg_queries_count : 0 %>"><%= has_hits ? action.avg_queries_count.round(1) : '—' %></td>
58
+ <td data-order="<%= has_hits ? action.avg_http_time : 0 %>"><%= has_hits ? sec_str(action.avg_http_time) : '—' %></td>
59
+ <td data-order="<%= action.fast_time.to_f %>"><%= action.fast_id.present? ? link_to(sec_str(action.fast_time), show_path(id: action.fast_id, apm_date: apm_date)) : '—' %></td>
60
+ <td data-order="<%= action.slow_time.to_f %>"><%= action.slow_id.present? ? link_to(sec_str(action.slow_time), show_path(id: action.slow_id, apm_date: apm_date)) : '—' %></td>
41
61
  </tr>
42
62
  <% end %>
43
63
  </tbody>
@@ -47,11 +67,10 @@
47
67
  </section>
48
68
  <script type="text/javascript">
49
69
  $(document).ready(function(){
50
- $('#actions-table').DataTable({
51
- iDisplayLength: 25,
52
- // 自定义的排序方法
53
- aoColumnDefs: [ {sType: "sec", aTargets: [2,3,5,6]}]
54
- })
70
+ $('#actions-table').DataTable(window.SimpleApmUI.tableOptions({
71
+ order: [[2, 'desc']],
72
+ columnDefs: [{type: 'num', targets: [1, 2, 3, 4, 5, 6, 7]}]
73
+ }))
55
74
 
56
75
  })
57
76
  </script>
@@ -3,22 +3,26 @@
3
3
  <h1 class="apm-page-title"><%= t("simple_apm.dashboard.title") %></h1>
4
4
  <p class="apm-page-subtitle"><%= t("simple_apm.dashboard.subtitle") %></p>
5
5
  </div>
6
+ <div class="apm-toolbar-actions">
7
+ <%= link_to t("simple_apm.layout.nav_actions"), actions_path(apm_date: apm_date), class: 'btn apm-button-secondary' %>
8
+ <%= link_to t("simple_apm.layout.nav_slow_requests"), index_path(apm_date: apm_date), class: 'btn btn-primary' %>
9
+ </div>
6
10
  </div>
7
11
 
8
12
  <div class="apm-metrics">
9
13
  <div class="apm-stat">
10
- <p class="apm-stat-label"><%= t("simple_apm.dashboard.stat_points") %></p>
11
- <div class="apm-stat-value"><%= @x_names.length %></div>
12
- <div class="apm-stat-meta"><%= t("simple_apm.dashboard.ten_minute_intervals") %></div>
14
+ <p class="apm-stat-label"><%= t("simple_apm.dashboard.daily_avg_response") %></p>
15
+ <div class="apm-stat-value"><%= @daily_stats[:hits].positive? ? sec_str(@daily_stats[:avg_time]) : '—' %></div>
16
+ <div class="apm-stat-meta"><%= t("simple_apm.dashboard.weighted_daily_average") %></div>
13
17
  </div>
14
18
  <div class="apm-stat">
15
19
  <p class="apm-stat-label"><%= t("simple_apm.dashboard.hits") %></p>
16
- <div class="apm-stat-value"><%= @hits_arr.map(&:to_i).sum %></div>
20
+ <div class="apm-stat-value"><%= number_with_delimiter(@daily_stats[:hits]) %></div>
17
21
  <div class="apm-stat-meta"><%= t("simple_apm.dashboard.current_day_total") %></div>
18
22
  </div>
19
23
  <div class="apm-stat">
20
24
  <p class="apm-stat-label"><%= t("simple_apm.dashboard.peak_avg_response") %></p>
21
- <div class="apm-stat-value"><%= sec_str(@time_arr.map(&:to_f).max.to_f) %></div>
25
+ <div class="apm-stat-value"><%= @daily_stats[:hits].positive? ? sec_str(@time_arr.map(&:to_f).max.to_f) : '—' %></div>
22
26
  <div class="apm-stat-meta"><%= t("simple_apm.dashboard.interval_peak") %></div>
23
27
  </div>
24
28
  <div class="apm-stat">
@@ -34,11 +38,20 @@
34
38
  </div>
35
39
  <div class="apm-stat">
36
40
  <p class="apm-stat-label"><%= t("simple_apm.dashboard.query_date") %></p>
37
- <div class="apm-stat-value"><%= SimpleApm::RedisKey.query_date || Time.now.strftime('%Y-%m-%d') %></div>
41
+ <div class="apm-stat-value"><%= apm_date %></div>
38
42
  <div class="apm-stat-meta"><%= t("simple_apm.dashboard.switch_in_top_right") %></div>
39
43
  </div>
40
44
  </div>
41
45
 
46
+ <% if @daily_stats[:hits].zero? %>
47
+ <section class="apm-panel">
48
+ <div class="apm-empty-state">
49
+ <h2 class="apm-panel-title"><%= t("simple_apm.dashboard.no_data") %></h2>
50
+ <p><%= t("simple_apm.dashboard.no_data_hint") %></p>
51
+ <%= link_to t("simple_apm.layout.nav_data"), data_path, class: 'btn apm-button-secondary' %>
52
+ </div>
53
+ </section>
54
+ <% else %>
42
55
  <div class="apm-grid">
43
56
  <section class="apm-panel apm-col-6">
44
57
  <div class="apm-panel-header">
@@ -48,7 +61,7 @@
48
61
  </div>
49
62
  </div>
50
63
  <div class="apm-panel-body">
51
- <div id="time_chart" class="apm-chart"></div>
64
+ <div id="time_chart" class="apm-chart" role="img" aria-label="<%= t("simple_apm.dashboard.response_time") %> · <%= apm_date %>"></div>
52
65
  </div>
53
66
  </section>
54
67
 
@@ -60,17 +73,19 @@
60
73
  </div>
61
74
  </div>
62
75
  <div class="apm-panel-body">
63
- <div id="hits_chart" class="apm-chart"></div>
76
+ <div id="hits_chart" class="apm-chart" role="img" aria-label="<%= t("simple_apm.dashboard.hit_count") %> · <%= apm_date %>"></div>
64
77
  </div>
65
78
  </section>
66
79
  </div>
67
80
 
68
81
  <script>
69
- var time_chart = echarts.init(document.getElementById('time_chart')),
82
+ (function () {
83
+ var time_chart = echarts.init(document.getElementById('time_chart')),
70
84
  hits_chart = echarts.init(document.getElementById('hits_chart'));
71
85
  time_chart.setOption({
86
+ animation: false,
72
87
  color: ['#0f766e'],
73
- grid: {left: 48, right: 18, top: 24, bottom: 36},
88
+ grid: {left: 16, right: 18, top: 32, bottom: 16, containLabel: true},
74
89
  tooltip: {trigger: 'axis'},
75
90
  xAxis: {
76
91
  data: <%= @x_names.to_json.html_safe %>,
@@ -79,22 +94,25 @@
79
94
  },
80
95
  yAxis: {
81
96
  type: 'value',
97
+ name: 's',
82
98
  axisLine: {show: false},
83
99
  splitLine: {lineStyle: {color: '#eef2f7'}},
84
100
  axisLabel: {color: '#667085'}
85
101
  },
86
102
  series: [{
103
+ name: '<%= j t("simple_apm.dashboard.response_time") %> (s)',
87
104
  type: 'line',
88
- smooth: true,
89
- symbolSize: 6,
105
+ showSymbol: true,
106
+ symbolSize: 4,
90
107
  areaStyle: {color: 'rgba(15, 118, 110, 0.10)'},
91
- data: <%= @time_arr.to_json.html_safe %>
108
+ data: <%= @time_arr.each_with_index.map { |time, i| @hits_arr[i].to_i.positive? ? time : nil }.to_json.html_safe %>
92
109
  }]
93
110
  })
94
111
 
95
112
  hits_chart.setOption({
113
+ animation: false,
96
114
  color: ['#2563eb'],
97
- grid: {left: 48, right: 18, top: 24, bottom: 36},
115
+ grid: {left: 16, right: 18, top: 32, bottom: 16, containLabel: true},
98
116
  tooltip: {trigger: 'axis'},
99
117
  xAxis: {
100
118
  data: <%= @x_names.to_json.html_safe %>,
@@ -103,21 +121,22 @@
103
121
  },
104
122
  yAxis: {
105
123
  type: 'value',
124
+ minInterval: 1,
106
125
  axisLine: {show: false},
107
126
  splitLine: {lineStyle: {color: '#eef2f7'}},
108
127
  axisLabel: {color: '#667085'}
109
128
  },
110
129
  series: [{
111
- type: 'line',
112
- smooth: true,
113
- symbolSize: 6,
114
- areaStyle: {color: 'rgba(37, 99, 235, 0.10)'},
130
+ name: '<%= j t("simple_apm.dashboard.hit_count") %>',
131
+ type: 'bar',
115
132
  data: <%= @hits_arr.to_json.html_safe %>
116
133
  }]
117
134
  })
118
135
 
119
- $(window).on('resize', function () {
136
+ $(window).on('resize.simpleApmCharts', function () {
120
137
  time_chart.resize()
121
138
  hits_chart.resize()
122
139
  })
140
+ })();
123
141
  </script>
142
+ <% end %>