solid_apm 0.6.0 → 0.7.0

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: d90f515a42a990a08a88c44bb8146dfe87176c81ad8584bcf7e4a29083316c2e
4
- data.tar.gz: a92fd226a1a96882700cea025afa4ba1d8d2356cce2dd621701149e612e9fe2c
3
+ metadata.gz: 2980cc185b4e779e37f5a2b1ef323f3bddc9453076725d992a3d7641e54ae370
4
+ data.tar.gz: 9ef8518d90d7351f17001d428c79dba5c7ebecd890c642f47ae2fd1e744f5591
5
5
  SHA512:
6
- metadata.gz: 3d0af12fc21edcb8117da1f466b440c0241ccb6995f174abf50e09e77e7fa8a32a36b1c0aa2559d55af6238dce318101bd42e38f06536f28d75499c8bdbc0a11
7
- data.tar.gz: 5b0829667356213cda1c572c8386f902b2054143bf66b2252f2e047d9590345acaea13c4902b7dee3c04b42e6dbe73f2449d7a30197afdf5a3989628d3d1ef8b
6
+ metadata.gz: b9af1a90d9603e05b5436bdcb420c31dfe7156d4768f261772a6e602f160385a6c7af60e8b08bb2050df4151a27703858c184bf271bfeac69d05de5b6efa344f
7
+ data.tar.gz: 48fb657be11a65ae888235a88ac8794a1ecdf8ea4863d5c7cdb1c3e292cabb04917b1b109d1c157099550a53931d1272fa0362ffbddb433fb8e4f839ce8cf93c
data/Rakefile CHANGED
@@ -1,6 +1,6 @@
1
1
  require "bundler/setup"
2
2
 
3
- APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
3
+ APP_RAKEFILE = File.expand_path("spec/dummy/Rakefile", __dir__)
4
4
  load "rails/tasks/engine.rake"
5
5
 
6
6
  load "rails/tasks/statistics.rake"
@@ -8,4 +8,3 @@ window.Stimulus = Application.start();
8
8
 
9
9
  // require "./controllers/spans-chart_controller"
10
10
  // import "./controllers/spans-chart_controller.js"
11
- // import "./controllers/transaction-chart_controller"
@@ -3,22 +3,41 @@
3
3
  module SolidApm
4
4
  class TransactionsController < ApplicationController
5
5
  TransactionAggregation = Struct.new(:name, :tmp, :latency, :percentile_95, :impact)
6
+ private_constant :TransactionAggregation
6
7
 
7
8
  def index
8
- @aggregated_transactions = Transaction.where(created_at: from_to_range).group_by(&:name)
9
- @aggregated_transactions.transform_values! do |transactions|
10
- latency = transactions.map(&:duration).sum / transactions.size
11
- tmp = transactions.size.to_f / ((from_to_range.end - from_to_range.begin) / 60).to_i
9
+ if from_to_range.end < from_to_range.begin
10
+ flash[:error] = 'Invalid time range'
11
+ redirect_to transactions_path
12
+ return
13
+ end
14
+
15
+ @transactions_scope = Transaction.where(timestamp: from_to_range)
16
+ if params[:name].present?
17
+ @transactions_scope = @transactions_scope.where(name: params[:name])
18
+ end
19
+ transaction_names = @transactions_scope.distinct.pluck(:name)
20
+ latency_95p = @transactions_scope.group(:name).percentile(:duration, 0.95)
21
+ latency_median = @transactions_scope.group(:name).median(:duration)
22
+ tmp_dict = @transactions_scope.group(:name).group_by_minute(:timestamp, series: false).count.each_with_object({}) do |(k, v), h|
23
+ current_value = h[k.first] ||= 0
24
+ h[k.first] = v if v > current_value
25
+ end
26
+
27
+ @aggregated_transactions = transaction_names.each_with_object({}) do |transaction_name, h|
28
+ latency = latency_median[transaction_name]
29
+ tmp = tmp_dict[transaction_name]
12
30
  impact = latency * tmp
13
- percentile_95 = transactions[transactions.size * 0.95].duration
14
- TransactionAggregation.new(
15
- transactions.first.name,
31
+ h[transaction_name] = TransactionAggregation.new(
32
+ transaction_name,
16
33
  tmp,
17
34
  latency,
18
- percentile_95,
35
+ latency_95p[transaction_name],
19
36
  impact
20
37
  )
21
38
  end
39
+
40
+ return if @aggregated_transactions.empty?
22
41
  # Find the maximum and minimum impact values
23
42
  max_impact = @aggregated_transactions.values.max_by(&:impact).impact
24
43
  min_impact = @aggregated_transactions.values.min_by(&:impact).impact
@@ -30,32 +49,15 @@ module SolidApm
30
49
  aggregation.impact = normalized_impact.to_i || 0
31
50
  end
32
51
  @aggregated_transactions = @aggregated_transactions.sort_by { |_, v| -v.impact }.to_h
33
- end
34
52
 
35
- def show_by_name
36
- @transactions = Transaction.where(name: params[:name]).order(timestamp: :desc).limit(20)
37
- end
38
-
39
- def show
40
- @transaction = Transaction.find(params[:id])
53
+ scope = @transactions_scope.group_by_second(:timestamp, n: n_intervals_seconds(from_to_range))
54
+ @throughput_data = scope.count
55
+ @latency_data = scope.median(:duration).transform_values(&:to_i)
41
56
  end
42
57
 
43
58
  def spans
44
- @transaction = Transaction.find(params[:id])
45
- @spans = @transaction.spans
46
- render json: @spans
47
- end
48
-
49
- def count_time_aggregations
50
- scope = Transaction.all.order(timestamp: :desc)
51
- .where(created_at: from_to_range)
52
-
53
-
54
- if params[:name].present?
55
- scope = scope.where(name: params[:name])
56
- end
57
-
58
- render json: aggregate(scope.select(:id, :created_at).find_each, from_to_range, intervals_count: 20).transform_values!(&:count)
59
+ @transaction = Transaction.find_by!(uuid: params[:uuid])
60
+ @transaction.spans.to_a
59
61
  end
60
62
 
61
63
  private
@@ -64,10 +66,19 @@ module SolidApm
64
66
  params[:from_value] ||= 60
65
67
  params[:from_unit] ||= 'minutes'
66
68
  from = params[:from_value].to_i.public_send(params[:from_unit].to_sym).ago
67
- to = Time.current
69
+ params[:to_value] ||= 1
70
+ params[:to_unit] ||= 'seconds'
71
+ to = params[:to_value].to_i.public_send(params[:to_unit].to_sym).ago
68
72
  (from..to)
69
73
  end
70
74
 
75
+ def n_intervals_seconds(range, intervals_count: 30)
76
+ start_time = range.begin
77
+ end_time = range.end
78
+ time_range_in_seconds = (end_time - start_time).to_i
79
+ (time_range_in_seconds / intervals_count.to_f).round
80
+ end
81
+
71
82
  def aggregate(items, range, intervals_count: 20)
72
83
  start_time = range.begin
73
84
  end_time = range.end
@@ -1,4 +1,33 @@
1
1
  module SolidApm
2
2
  module ApplicationHelper
3
+ def area_chart_options
4
+ {
5
+ module: true,
6
+ chart: {
7
+ type: 'area', height: '200', background: '0', foreColor: '#ffffff55', zoom: {
8
+ enabled: false,
9
+ }, toolbar: {
10
+ show: false,
11
+ }
12
+ },
13
+ xaxis: {
14
+ type: 'datetime',
15
+ tooltip: {
16
+ enabled: false
17
+
18
+ }
19
+ },
20
+ stroke: {
21
+ curve: 'smooth'
22
+ }, theme: {
23
+ mode: 'dark',
24
+ }, grid: {
25
+ show: true, borderColor: '#ffffff55',
26
+ }, dataLabels: {
27
+ enabled: false
28
+ },
29
+ tooltip: {x: {formatter: {function: {args: "val", body: "return new Date(val).toLocaleString()"}} }}
30
+ }
31
+ end
3
32
  end
4
33
  end
@@ -8,13 +8,14 @@ module SolidApm
8
8
  super do |name, start, finish, id, payload|
9
9
  transaction = SpanSubscriber::Base.transaction
10
10
  transaction.name = "#{payload[:request].controller_class}##{payload[:request].path_parameters[:action]}"
11
+ transaction.timestamp = start
11
12
  transaction.end_time = finish
12
- transaction.duration = ((transaction.end_time.to_f - transaction.timestamp.to_f) * 1000).round(6)
13
+ transaction.duration = ((finish.to_f - start.to_f) * 1000).round(6)
13
14
  transaction.metadata = {
14
15
  params: payload[:request].params.except(:controller, :action),
15
16
  context: SpanSubscriber::Base.context
16
17
  }
17
- SpanSubscriber::Base.context = nil
18
+ SpanSubscriber::Base.context = {}
18
19
  end
19
20
  end
20
21
 
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
  module SolidApm
3
- module SpanSubscriber
4
- class ActiveRecordSql < Base
5
- PATTERN = "sql.active_record"
3
+ module SpanSubscriber
4
+ class ActiveRecordSql < Base
5
+ PATTERN = "sql.active_record"
6
6
 
7
- def summary(payload)
8
- payload[:sql]
7
+ def summary(payload)
8
+ payload[:sql]
9
+ end
9
10
  end
10
11
  end
11
12
  end
12
- end
@@ -5,18 +5,23 @@
5
5
  <%= csrf_meta_tags %>
6
6
  <%= csp_meta_tag %>
7
7
 
8
- <script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
8
+ <script src="https://cdn.jsdelivr.net/npm/apexcharts@4.4.0"></script>
9
9
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@1.0.1/css/bulma.min.css">
10
10
  <%= stylesheet_link_tag "solid_apm/application", media: "all" %>
11
11
  <%= javascript_include_tag "solid_apm/application", "data-turoblinks-track": "reload", type: "module" %>
12
- <%= javascript_include_tag "solid_apm/controllers/transaction-chart_controller", "data-turoblinks-track": "reload", type: "module" %>
13
- <%= javascript_include_tag "solid_apm/controllers/spans-chart_controller", "data-turoblinks-track": "reload", type: "module" %>
14
12
  </head>
15
13
 
16
- <body style="overflow: scroll">
14
+ <body>
17
15
  <section class="section">
18
16
  <%= yield %>
19
17
  </section>
18
+
19
+ <% if flash[:error] %>
20
+ <div class="notification is-danger mb-1" style="width: 20em; position: absolute; bottom: 1em; right: 1em;">
21
+ <button class="delete"></button>
22
+ <%= flash[:error] %>
23
+ </div>
24
+ <% end %>
20
25
  </body>
21
26
 
22
27
  </html>
@@ -0,0 +1,34 @@
1
+ <%= form_with path: transactions_path, method: :get do |f| %>
2
+ <div class="is-flex is-flex-direction-row is-justify-content-center is-align-items-center" style="gap: 1em">
3
+ <%= f.number_field :from_value, value: params[:from_value] || 60, min: 1, class: 'input', style: 'width: 6em' %>
4
+ <div class="select">
5
+ <%= f.select :from_unit, {
6
+ "minutes" => "minutes",
7
+ "hours" => "hours",
8
+ "days" => "days",
9
+ "weeks" => "weeks",
10
+ "months" => "months",
11
+ "years" => "years"
12
+ }, {selected: params[:from_unit] || 'minutes' } %>
13
+ </div>
14
+ <b>→</b>
15
+ <%= f.number_field :to_value, value: params[:to_value] || 1, min: 1, class: 'input', style: 'width: 6em' %>
16
+ <div class="select">
17
+ <%= f.select :to_unit, {
18
+ "seconds" => "seconds",
19
+ "minutes" => "minutes",
20
+ "hours" => "hours",
21
+ "days" => "days",
22
+ "weeks" => "weeks",
23
+ "months" => "months",
24
+ "years" => "years"
25
+ }, {selected: params[:to_unit] || 'seconds' } %>
26
+ </div>
27
+
28
+ <% if params[:name] %>
29
+ <%= f.hidden_field :name, value: params[:name] %>
30
+ <% end %>
31
+
32
+ <%= f.submit 'Apply', class: 'button' %>
33
+ </div>
34
+ <% end %>
@@ -0,0 +1,10 @@
1
+ <div class="columns pt-2" style="height: 16em">
2
+ <div class="column">
3
+ <h2 class="ml-4">Throughput</h2>
4
+ <%= area_chart({ name: 'tmp', data: @throughput_data }, area_chart_options.merge(colors: ['#43BCCD'])) %>
5
+ </div>
6
+ <div class="column">
7
+ <h2 class="ml-4">Latency</h2>
8
+ <%= area_chart({ name: 'ms', data: @latency_data }, area_chart_options.merge(colors: ['#13d8aa'])) %>
9
+ </div>
10
+ </div>
@@ -1,26 +1,15 @@
1
- <h1 class="title">Transactions</h1>
2
-
3
- <%= form_with path: transactions_path, method: :get do |f| %>
4
- <div class="is-flex is-flex-direction-row is-justify-content-center is-align-items-center" style="gap: 1em">
5
- <%= f.label 'From' %>
6
- <%= f.number_field :from_value, value: params[:from_value] || 60, min: 1, class: 'input', style: 'width: 6em' %>
7
- <div class="select">
8
- <%= f.select :from_unit, {
9
- "minutes" => "minutes",
10
- "hours" => "hours",
11
- "days" => "days",
12
- "weeks" => "weeks",
13
- "months" => "months",
14
- "years" => "years"
15
- }, {selected: params[:from_unit] || 'minutes' } %>
16
- </div>
17
- <span class="has-text-white-ter">ago</span>
18
- <b>→</b>
19
- <span class="has-text-white-ter">now</span>
20
- <%= f.submit 'Apply', class: 'button' %>
21
- </div>
1
+ <% if params[:name] %>
2
+ <h1 class="title"><%= link_to '⬅ ', transactions_path(
3
+ from_value: params[:from_value],
4
+ from_unit: params[:from_unit],
5
+ to_value: params[:to_value],
6
+ to_unit: params[:to_unit]) %><%= params[:name] %></h1>
7
+ <% else %>
8
+ <h1 class="title">Solid APM</h1>
22
9
  <% end %>
23
- <div data-controller="transaction-chart"></div>
10
+
11
+ <%= render 'time_range_form' %>
12
+ <%= render 'charts' %>
24
13
 
25
14
  <table class="table is-fullwidth">
26
15
  <thead>
@@ -35,7 +24,12 @@
35
24
 
36
25
  <% @aggregated_transactions.each do |name, aggregation| %>
37
26
  <tr>
38
- <td><%= link_to name, transaction_by_name_path(name) %></td>
27
+ <td><%= link_to name, transactions_path(
28
+ from_value: params[:from_value],
29
+ from_unit: params[:from_unit],
30
+ to_value: params[:to_value],
31
+ to_unit: params[:to_unit],
32
+ name: name) %>
39
33
  <td><%= aggregation.latency.round(2) %> ms</td>
40
34
  <td><%= aggregation.tmp.round(2) %></td>
41
35
  <td><%= aggregation.percentile_95.round(2) %> ms</td>
@@ -45,3 +39,28 @@
45
39
  </tr>
46
40
  <% end %>
47
41
  </table>
42
+
43
+ <% if params[:name] %>
44
+ <table class="table is-fullwidth is-hoverable">
45
+ <thead>
46
+ <tr>
47
+ <th scope="col">Name</th>
48
+ <th scope="col">Timestamp</th>
49
+ <th scope="col">Type</th>
50
+ <th scope="col">Duration</th>
51
+ <th scope="col">Metadata</th>
52
+ </tr>
53
+ </thead>
54
+ <tbody>
55
+ <% @transactions_scope.order(timestamp: :desc).each do |transaction| %>
56
+ <tr>
57
+ <td><%= link_to transaction.name, transaction_spans_path(uuid: transaction.uuid) %></td>
58
+ <td><%= transaction.timestamp %></td>
59
+ <td><%= transaction.type %></td>
60
+ <td><%= transaction.duration.round(2) %></td>
61
+ <td><%= transaction.metadata %></td>
62
+ </tr>
63
+ <% end %>
64
+ </tbody>
65
+ </table>
66
+ <% end %>
@@ -0,0 +1,34 @@
1
+ <h1 class="title"><%= link_to '⬅ ', request.referer %><%= @transaction.name %></h1>
2
+ <h2 class="title is-6"><span class="has-text-grey">Trace ID:</span> <%= @transaction.uuid %></h2>
3
+ <h2 class="title is-6"><span class="has-text-grey">Timestamp:</span> <%= @transaction.timestamp %></h2>
4
+ <h2 class="title is-6"><span class="has-text-grey">Duration:</span> <%= @transaction.duration.round(2) %> ms</h2>
5
+ <h2 class="title is-6"><span class="has-text-grey">Metadata:</span> <%= @transaction.metadata %></h2>
6
+
7
+ <h2 class="title is-4 mt-6">Spans</h2>
8
+
9
+ <% min_start_time = @transaction.spans.minimum(:timestamp) %>
10
+ <% max_end_time = @transaction.spans.maximum(:end_time) %>
11
+ <% total_duration = max_end_time - min_start_time %>
12
+
13
+ <div class="is-fullwidth">
14
+ <% @transaction.spans.each do |span| %>
15
+ <% left_percent = ((span.timestamp - min_start_time).to_f / total_duration * 100) %>
16
+ <% width_percent = [((span.end_time - span.timestamp).to_f / total_duration * 100), 0.1].max %>
17
+ <% right_percent = (100 - left_percent - width_percent) %>
18
+
19
+ <div style="display: flex; height: 1.5em;">
20
+ <div style="flex: <%= left_percent %>"></div>
21
+ <div style="flex: <%= width_percent %>; display: flex; align-items: center; justify-content: center; border-radius: 5px" class="has-background-primary-15">
22
+ </div>
23
+ <div style="flex: <%= right_percent %>;"></div>
24
+ </div>
25
+ <div style="margin-left: <%= left_percent %>%" class="mt-1 mb-2">
26
+ <p>
27
+ <span class="has-text-grey-lighter "><%= span.name %></span><span class="has-text-grey pl-2"><%= span.duration.round(2) %>ms</span>
28
+ </p>
29
+ <p>
30
+ <%= span.summary %>
31
+ </p>
32
+ </div>
33
+ <% end %>
34
+ </div>
data/config/routes.rb CHANGED
@@ -2,10 +2,5 @@ SolidApm::Engine.routes.draw do
2
2
  root 'transactions#index'
3
3
 
4
4
  get 'transactions', to: 'transactions#index'
5
- get 'transactions/count_time_aggregations',
6
- default: { format: 'json' }
7
-
8
- get 'transactions/:id', to: 'transactions#show', as: 'transaction', constraints: { id: /\d+/ }
9
- get 'transactions/:name', to: 'transactions#show_by_name', as: 'transaction_by_name'
10
- get 'transactions/:id/spans', to: 'transactions#spans', as: 'transaction_spans'
5
+ get 'transactions/:uuid/spans', to: 'transactions#spans', as: 'transaction_spans'
11
6
  end
@@ -43,7 +43,6 @@ module SolidApm
43
43
  now = Time.zone.now
44
44
  SpanSubscriber::Base.transaction = Transaction.new(
45
45
  uuid: SecureRandom.uuid,
46
- timestamp: now,
47
46
  unix_minute: (now.to_f / 60).to_i,
48
47
  type: 'request'
49
48
  )
@@ -1,3 +1,3 @@
1
1
  module SolidApm
2
- VERSION = "0.6.0"
2
+ VERSION = "0.7.0"
3
3
  end
data/lib/solid_apm.rb CHANGED
@@ -1,3 +1,8 @@
1
+ require 'English' # For apexcharts Regex
2
+ require 'groupdate'
3
+ require 'active_median'
4
+ require 'apexcharts'
5
+
1
6
  require "solid_apm/version"
2
7
  require "solid_apm/engine"
3
8
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solid_apm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jean-Francis Bastien
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-01-17 00:00:00.000000000 Z
10
+ date: 2025-02-12 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: actionpack
@@ -65,6 +65,48 @@ dependencies:
65
65
  - - ">="
66
66
  - !ruby/object:Gem::Version
67
67
  version: '7.1'
68
+ - !ruby/object:Gem::Dependency
69
+ name: apexcharts
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ type: :runtime
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ - !ruby/object:Gem::Dependency
83
+ name: groupdate
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ type: :runtime
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ - !ruby/object:Gem::Dependency
97
+ name: active_median
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ type: :runtime
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
68
110
  description: SolidApm allow you to monitor your application without any external service.
69
111
  email:
70
112
  - bhacaz@gmail.com
@@ -77,8 +119,6 @@ files:
77
119
  - Rakefile
78
120
  - app/assets/config/solid_apm_manifest.js
79
121
  - app/assets/javascripts/solid_apm/application.js
80
- - app/assets/javascripts/solid_apm/controllers/spans-chart_controller.js
81
- - app/assets/javascripts/solid_apm/controllers/transaction-chart_controller.js
82
122
  - app/assets/stylesheets/solid_apm/application.css
83
123
  - app/controllers/solid_apm/application_controller.rb
84
124
  - app/controllers/solid_apm/transactions_controller.rb
@@ -95,10 +135,11 @@ files:
95
135
  - app/models/solid_apm/transaction.rb
96
136
  - app/views/javascripts/_javascripts.html.erb
97
137
  - app/views/layouts/solid_apm/application.html.erb
138
+ - app/views/solid_apm/application/_time_range_form.html.erb
98
139
  - app/views/solid_apm/spans/index.html.erb
140
+ - app/views/solid_apm/transactions/_charts.html.erb
99
141
  - app/views/solid_apm/transactions/index.html.erb
100
- - app/views/solid_apm/transactions/show.html.erb
101
- - app/views/solid_apm/transactions/show_by_name.html.erb
142
+ - app/views/solid_apm/transactions/spans.html.erb
102
143
  - config/routes.rb
103
144
  - db/migrate/20240608015633_create_solid_apm_transactions.rb
104
145
  - db/migrate/20240608021940_create_solid_apm_spans.rb
@@ -1,97 +0,0 @@
1
- import {
2
- Controller,
3
- } from "https://unpkg.com/@hotwired/stimulus/dist/stimulus.js";
4
-
5
- // Connects to data-controller="spans-charts"
6
- window.Stimulus.register('spans-chart',
7
- class extends Controller {
8
- static values = { id: String }
9
-
10
- connect() {
11
- console.log("Connected")
12
- const options = {
13
- series: [
14
- {
15
- data: []
16
- }
17
- ],
18
- chart: {
19
- type: "rangeBar",
20
- height: "250em",
21
- },
22
- plotOptions: {
23
- bar: {
24
- horizontal: true
25
- }
26
- },
27
- xaxis: {
28
- type: "datetime",
29
- labels: {
30
- show: false
31
- }
32
- },
33
- tooltip: {
34
- custom: function ({y1, y2,dataPointIndex, seriesIndex, w}) {
35
- // custom: function (opts) {
36
- // console.log(opts)
37
- // console.log(value)
38
- return (
39
- '<div class="apexcharts-tooltip-title has-text-black" style="max-width: 40em; text-wrap: balance;">' +
40
- w.globals.initialSeries[seriesIndex].data[dataPointIndex].duration + "ms" +
41
- "<br>" +
42
- w.globals.initialSeries[seriesIndex].data[dataPointIndex].name +
43
- "<br>" +
44
- w.globals.initialSeries[seriesIndex].data[dataPointIndex].summary +
45
- '</div>'
46
- )
47
- }
48
- },
49
- yaxis: {
50
- labels: {
51
- formatter: function (value, opts) {
52
- if (opts === undefined) {
53
- return value[1] - value[0] + "ms"
54
- }
55
- if (opts.dataPointIndex >= 0) {
56
- return opts.w.globals.initialSeries[opts.seriesIndex].data[opts.dataPointIndex].name
57
- }
58
- return value
59
- }
60
- }
61
- },
62
- }
63
-
64
- fetch(this.idValue + "/spans.json")
65
- .then(response => response.json())
66
- .then(data => {
67
- options.series[0].data = data.map(d => {
68
- let startTime = new Date(d.timestamp).getTime()
69
- let endTime = new Date(d.end_time).getTime()
70
- if (endTime - startTime < 1) {
71
- endTime = startTime + 1
72
- }
73
- return {
74
- x: d.uuid,
75
- y: [startTime, endTime],
76
- name: d.name,
77
- summary: d.summary || d.name,
78
- duration: this.round(d.duration, 2)
79
- }
80
- })
81
- this.chart = new ApexCharts(this.element, options)
82
- this.chart.render()
83
- })
84
- }
85
-
86
- disconnect() {
87
- if (this.chart) {
88
- this.chart.destroy()
89
- this.chart = null
90
- }
91
- }
92
-
93
- round(num, decimalPlaces = 0) {
94
- num = Math.round(num + "e" + decimalPlaces);
95
- return Number(num + "e" + -decimalPlaces);
96
- }
97
- })
@@ -1,76 +0,0 @@
1
- import {
2
- Controller,
3
- } from "https://unpkg.com/@hotwired/stimulus/dist/stimulus.js";
4
- // unload chart https://github.com/Deanout/weight_tracker/blob/d4123acb952d91fcc9bedb96bbd786088a71482a/app/javascript/controllers/weights_controller.js#L4
5
- // tooltip: {
6
- // y: {
7
- // formatter: function (value, {series, seriesIndex, dataPointIndex, w}) {
8
- // return w.globals.initialSeries[seriesIndex].data[dataPointIndex].name + "\n" + value + "ms"
9
- // }
10
- // }
11
- // }
12
-
13
- // Connects to data-controller="transaction-chart"
14
- window.Stimulus.register('transaction-chart',
15
- class extends Controller {
16
- static values = { name: String }
17
-
18
- connect() {
19
- var options = {
20
- chart: {
21
- type: 'bar',
22
- height: '200em'
23
- },
24
- series: [{
25
- name: 'tpm',
26
- }],
27
- xaxis: {
28
- type: 'datetime'
29
- },
30
- dataLabels: {
31
- enabled: false
32
- },
33
- tooltip: {
34
- x: {
35
- formatter: function (value) {
36
- return new Date(value).toLocaleString()
37
- }
38
- }
39
- }
40
- }
41
-
42
- let path = "count_time_aggregations?";
43
- if (this.nameValue) {
44
- path = path + "name=" + encodeURIComponent(this.nameValue);
45
- }
46
-
47
- const fromValue = document.querySelector('input[name="from_value"]')
48
- const fromUnit = document.querySelector('select[name="from_unit"]');
49
- if (fromValue && fromUnit) {
50
- path = path + "&from_value=" + fromValue.value + "&from_unit=" + fromUnit.value;
51
- }
52
-
53
- const base = window.location.pathname.split('/transactions')[0];
54
- path = base + "/transactions/" + path;
55
- path = path.replace("//", "/");
56
- fetch(path)
57
- .then(response => response.json())
58
- .then(data => {
59
- const transformedData = []
60
- for (let [key, value] of Object.entries(data)) {
61
- transformedData.push({x: key, y: value})
62
- }
63
- options.series[0].data = transformedData
64
- this.chart = new ApexCharts(this.element, options)
65
- this.chart.render()
66
- })
67
- }
68
-
69
- // Unloads the chart before loading new data.
70
- disconnect() {
71
- if (this.chart) {
72
- this.chart.destroy();
73
- this.chart = null;
74
- }
75
- }
76
- })
@@ -1,9 +0,0 @@
1
-
2
- <h1 class="title"><%= @transaction.name %></h1>
3
- <h2 class="title is-6"><span class="has-text-grey-dark">Trace ID:</span> <%= @transaction.uuid %></h2>
4
- <h2 class="title is-6"><span class="has-text-grey-dark">Timestamp:</span> <%= @transaction.timestamp %></h2>
5
- <h2 class="title is-6"><span class="has-text-grey-dark">Duration:</span> <%= @transaction.duration %> ms</h2>
6
- <h2 class="title is-6"><span class="has-text-grey-dark">Unix minute:</span> <%= @transaction.unix_minute %></h2>
7
- <h2 class="title is-6"><span class="has-text-grey-dark">Metadata:</span> <%= @transaction.metadata %></h2>
8
-
9
- <%= render template: 'solid_apm/spans/index', collection: @transaction.spans, locals: { spans: @transaction.spans } %>
@@ -1,27 +0,0 @@
1
- <h1 class="title is-3"><%= params[:name] %></h1>
2
- <div data-controller="transaction-chart" data-transaction-chart-name-value="<%= params[:name] %>"></div>
3
-
4
- <table class="table">
5
- <thead>
6
- <tr>
7
- <% SolidApm::Transaction.attribute_names.each do |attribute| %>
8
- <% next if attribute.to_s.end_with?('_at') %>
9
- <th scope="col"><%= attribute.humanize %></th>
10
- <% end %>
11
- </tr>
12
- </thead>
13
- <tbody>
14
- <% @transactions.each do |transaction| %>
15
- <tr>
16
- <% transaction.attributes.each do |attribute| %>
17
- <% next if attribute[0].to_s.end_with?('_at') %>
18
- <% if attribute[0] == 'uuid' %>
19
- <td><%= link_to attribute[1], transaction_path(transaction) %></td>
20
- <% else %>
21
- <td><%= attribute[1] %></td>
22
- <% end %>
23
- <% end %>
24
- </tr>
25
- <% end %>
26
- </tbody>
27
- </table>