system-metrics 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/README.rdoc +16 -1
  2. data/app/views/layouts/system_metrics/metrics.html.erb +4 -15
  3. data/app/views/system_metrics/metrics/_menu.html.erb +1 -1
  4. data/app/views/system_metrics/metrics/admin.html.erb +1 -1
  5. data/lib/system_metrics/engine.rb +3 -3
  6. data/lib/system_metrics/instrument/base.rb +1 -1
  7. data/lib/system_metrics/nested_event.rb +8 -1
  8. data/lib/system_metrics/store.rb +10 -15
  9. data/lib/system_metrics/version.rb +1 -1
  10. data/public/images/gradient.png +0 -0
  11. data/public/stylesheets/app.css +197 -3
  12. data/spec/spec_helper.rb +2 -0
  13. data/spec/support/db_setup.rb +3 -0
  14. data/spec/support/mock_app.rb +1 -3
  15. data/spec/support/notifications_support.rb +10 -0
  16. data/spec/system_metrics/collector_spec.rb +1 -2
  17. data/spec/system_metrics/config_spec.rb +16 -8
  18. data/spec/system_metrics/engine_spec.rb +53 -28
  19. data/spec/system_metrics/instrument/action_controller_spec.rb +51 -0
  20. data/spec/system_metrics/instrument/action_mailer_spec.rb +40 -0
  21. data/spec/system_metrics/instrument/action_view_spec.rb +40 -0
  22. data/spec/system_metrics/instrument/active_record_spec.rb +50 -0
  23. data/spec/system_metrics/instrument/base_spec.rb +38 -0
  24. data/spec/system_metrics/instrument/rack_spec.rb +28 -0
  25. data/spec/system_metrics/middleware_spec.rb +1 -3
  26. data/spec/system_metrics/nested_event_spec.rb +87 -0
  27. data/spec/system_metrics/store_spec.rb +49 -0
  28. data/spec/system_metrics_spec.rb +0 -1
  29. data/system-metrics.gemspec +1 -0
  30. metadata +30 -11
  31. data/public/stylesheets/base.css +0 -46
  32. data/public/stylesheets/footer.css +0 -6
  33. data/public/stylesheets/graphs.css +0 -9
  34. data/public/stylesheets/header.css +0 -52
  35. data/public/stylesheets/menu_bar.css +0 -7
  36. data/public/stylesheets/metric.css +0 -19
  37. data/public/stylesheets/payload.css +0 -4
  38. data/public/stylesheets/portlet.css +0 -11
  39. data/public/stylesheets/title_bar.css +0 -29
data/README.rdoc CHANGED
@@ -74,9 +74,24 @@ This example instrument illustrates three concepts
74
74
  (2) It will inform SystemMetrics that the event should not be collected if the current user is an administrator.
75
75
  (3) It will add the current user's name to the event payload
76
76
 
77
+ = Date/Time Ranges
78
+
79
+ You can change the time range of metrics shown on the dashboard and category screens using two query parameters; from and to. Consider the following examples:
80
+
81
+ Show dashboard metrics from three hours ago until now
82
+ http://localhost:3000/system/metrics?from=3.hours
83
+
84
+ Show one day of dashboard metrics beginning two days ago
85
+ http://localhost:3000/system/metrics?from=2.days&to=1.day
86
+
87
+ Show one hour of category metrics ending 30 minutes ago
88
+ http://localhost:3000/system/metrics/category/active_record?from=90.minutes&to=30.minutes
89
+
90
+ As you might have guessed, the 'from' and 'to' query parameters take an integer and any valid method added by ActiveSupport::CoreExtensions::Numeric::Time to create a time in the past. The default 'from' time is 30 minutes and 'to' is 0 minutes (current time).
91
+
77
92
  = Authorization
78
93
 
79
- There's no authorization built into SystemMetrics, although it should be rather straightforward to add your own. Consider the following example implementation:
94
+ Since SystemMetrics is not recommended for production use, the lack of authorization is not likely a problem. However, it should be rather straightforward to add your own. Consider the following example implementation:
80
95
 
81
96
  # config/initializers/system_metrics_authorization.rb
82
97
  module SystemMetricsAuthorization
@@ -10,31 +10,20 @@
10
10
  <!--[if lt IE 8]>
11
11
  <%= stylesheet_link_tag 'system_metrics/ie', :media => 'screen, projection' %>
12
12
  <![endif]-->
13
- <%= stylesheet_link_tag 'system_metrics/base',
14
- 'system_metrics/app',
15
- 'system_metrics/header',
16
- 'system_metrics/footer',
17
- 'system_metrics/title_bar',
18
- 'system_metrics/portlet',
19
- 'system_metrics/payload',
20
- 'system_metrics/metric',
21
- 'system_metrics/menu_bar',
22
- 'system_metrics/graphs',
23
- :media => 'screen, projection', :cache => 'system_metrics' %>
13
+ <%= stylesheet_link_tag 'system_metrics/app', :media => 'screen, projection' %>
24
14
  <%= csrf_meta_tag %>
25
15
  </head>
26
16
  <body>
27
17
  <div class="container">
28
- <div id="header">
29
- <%= image_tag 'system_metrics/rings_13.png' %>
18
+ <div id="hd">
30
19
  <h1>System Metrics</h1>
31
20
  <%= render "menu" %>
32
21
  </div>
33
22
  <%= render "title_bar" %>
34
- <div id="content">
23
+ <div id="bd">
35
24
  <%= yield %>
36
25
  </div>
37
- <div id="footer">
26
+ <div id="ft">
38
27
  <span>Developed by <a href="http://www.nearinfinity.com">Near Infinity</a></span>
39
28
  </div>
40
29
  </div>
@@ -1,4 +1,4 @@
1
- <ul id="tabs">
1
+ <ul>
2
2
  <li><%= link_to 'Dashboard', metrics_path %></li>
3
3
  <% for metric in SystemMetrics::Metric.select('DISTINCT(category)').order('category ASC') -%>
4
4
  <li><%= link_to metric.category.titleize, system_metrics_category_path(metric.category) %></li>
@@ -21,7 +21,7 @@
21
21
  <%= submit_tag 'Delete Category' %>
22
22
  <% end -%>
23
23
  </td>
24
- <tr>
24
+ </tr>
25
25
  <% end -%>
26
26
  </tbody>
27
27
  </table>
@@ -5,13 +5,13 @@ module SystemMetrics
5
5
 
6
6
  config.system_metrics = SystemMetrics::Config.new
7
7
 
8
- initializer "system_metrics.initialize" do |app|
8
+ initializer "system_metrics.initialize", :before => "system_metrics.start_subscriber" do |app|
9
9
  self.smc = app.config.system_metrics
10
10
  raise ArgumentError.new(smc.errors) if smc.invalid?
11
11
  self.collector = SystemMetrics::Collector.new(smc.store)
12
12
  end
13
13
 
14
- initializer "system_metrics.start_subscriber" do |app|
14
+ initializer "system_metrics.start_subscriber", :before => "system_metrics.add_middleware" do |app|
15
15
  ActiveSupport::Notifications.subscribe /^[^!]/ do |*args|
16
16
  unless smc.notification_exclude_patterns.any? { |pattern| pattern =~ name }
17
17
  process_event SystemMetrics::NestedEvent.new(*args)
@@ -19,7 +19,7 @@ module SystemMetrics
19
19
  end
20
20
  end
21
21
 
22
- initializer "system_metrics.add_middleware" do |app|
22
+ initializer "system_metrics.add_middleware", :before => :load_environment_config do |app|
23
23
  app.config.middleware.use SystemMetrics::Middleware, collector, smc.path_exclude_patterns
24
24
  end
25
25
 
@@ -41,7 +41,7 @@ module SystemMetrics
41
41
  # ignore the event, it should still return true if it generally
42
42
  # handles events like the one passed.
43
43
  def handles?(event)
44
- event.name =~ pattern
44
+ (event.name =~ pattern) != nil
45
45
  end
46
46
 
47
47
  # Indicates whether the given event should be completely ingored
@@ -2,6 +2,7 @@ require 'active_support/notifications'
2
2
 
3
3
  module SystemMetrics
4
4
  class NestedEvent < ActiveSupport::Notifications::Event
5
+ attr_reader :action, :category
5
6
 
6
7
  def self.arrange(events, options={})
7
8
  events.sort! { |a, b| a.end <=> b.end } unless options[:presort] == false
@@ -17,6 +18,11 @@ module SystemMetrics
17
18
  root
18
19
  end
19
20
 
21
+ def initialize(*args)
22
+ super
23
+ @action, @category = name.split('.')
24
+ end
25
+
20
26
  def exclusive_duration
21
27
  @exclusive_duration ||= duration - children.inject(0.0) { |sum, child| sum + child.duration }
22
28
  end
@@ -45,8 +51,9 @@ module SystemMetrics
45
51
  def to_hash
46
52
  {
47
53
  :name => name,
54
+ :action => action,
55
+ :category => category,
48
56
  :started_at => started_at,
49
- :ended_at => self.ended_at,
50
57
  :transaction_id => transaction_id,
51
58
  :payload => payload,
52
59
  :duration => duration,
@@ -1,6 +1,8 @@
1
1
  module SystemMetrics
2
2
  class Store
3
+
3
4
  def save(events)
5
+ return unless events.present?
4
6
  root_event = SystemMetrics::NestedEvent.arrange(events, :presort => false)
5
7
  root_model = create_metric(root_event)
6
8
  root_model.update_attributes(:request_id => root_model.id)
@@ -9,23 +11,16 @@ module SystemMetrics
9
11
 
10
12
  private
11
13
 
12
- def save_tree(events, request_id, parent_id)
13
- events.each do |event|
14
- model = create_metric(event, :request_id => request_id, :parent_id => parent_id)
15
- save_tree(event.children, request_id, model.id)
14
+ def save_tree(events, request_id, parent_id)
15
+ events.each do |event|
16
+ model = create_metric(event, :request_id => request_id, :parent_id => parent_id)
17
+ save_tree(event.children, request_id, model.id)
18
+ end
16
19
  end
17
- end
18
20
 
19
- def create_metric(event, merge_params={})
20
- action, category = event.name.split('.')
21
- params = event.to_hash.delete_if do |key, value|
22
- ![:name, :started_at, :transaction_id, :payload, :duration, :exclusive_duration].include?(key)
21
+ def create_metric(event, merge_params={})
22
+ SystemMetrics::Metric.create(event.to_hash.merge(merge_params))
23
23
  end
24
- params = params.merge(merge_params).merge(
25
- :action => action,
26
- :category => category
27
- )
28
- SystemMetrics::Metric.create(params)
29
- end
24
+
30
25
  end
31
26
  end
@@ -1,3 +1,3 @@
1
1
  module SystemMetrics
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
Binary file
@@ -1,13 +1,207 @@
1
- .container {
1
+ body {
2
+ color: #555555;
3
+ font-family: "Helvetica Neue",Arial,Helvetica,sans-serif;
4
+ font-size: 75%;
5
+ line-height: 150%;
6
+ background-color: #FAD08A;
7
+ margin: 0 auto;
8
+ max-width: 100%;
2
9
  width: 100%;
3
10
  }
4
11
 
5
- #content {
12
+ a:hover {
13
+ color: #0099FF;
14
+ }
15
+
16
+ a:visited {
17
+ color: #004C99;
18
+ }
19
+
20
+ a {
21
+ color: #0066CC;
22
+ text-decoration: underline;
23
+ }
24
+
25
+ h1, h2, h3, h4, h5, h6 {
26
+ color: #555555;
27
+ font-weight: bold;
28
+ }
29
+
30
+ #container {
31
+ height: 100%;
32
+ min-height: 100%;
33
+ }
34
+
35
+ #bd {
6
36
  padding: 20px;
7
- background: #FFF;
37
+ background-color: #FAFCFF;
38
+ }
39
+
40
+ tr {
41
+ height: 45px;
42
+ }
43
+
44
+ thead tr {
45
+ color: #667495;
8
46
  }
9
47
 
10
48
  div.clear {
11
49
  clear: both;
12
50
  }
13
51
 
52
+ #hd {
53
+ top: 0;
54
+ width: 100%;
55
+ height: 40px;
56
+ z-index: 2;
57
+ background: url("../../images/system_metrics/gradient.png") repeat-x scroll 0 -58px transparent;
58
+ text-align: right;
59
+ border-top: 2px solid #F8BC59;
60
+ }
61
+
62
+ #hd h1 {
63
+ color: #F8BC59;
64
+ font-size: 1.8em;
65
+ position: absolute;
66
+ top: 10px;
67
+ left: 20px;
68
+ text-shadow: 0 1px 0 black;
69
+ }
70
+
71
+ #hd ul {
72
+ border: 0 none;
73
+ clear: both;
74
+ margin: 0 1.622%;
75
+ overflow: hidden;
76
+ padding: 0;
77
+ text-shadow: 0 1px 0 black;
78
+ }
79
+
80
+ #hd ul li {
81
+ color: #C4D9FF;
82
+ cursor: pointer;
83
+ margin: 6px 0.5em 0;
84
+ padding: 0;
85
+ display: inline-block;
86
+ list-style-image: none;
87
+ list-style-type: none;
88
+ margin-left: 0;
89
+ padding-left: 10px;
90
+ padding-right: 10px;
91
+ vertical-align: middle;
92
+ white-space: nowrap;
93
+ -moz-box-orient: vertical;
94
+ }
95
+
96
+ #hd ul li a {
97
+ color: inherit;
98
+ cursor: inherit;
99
+ line-height: 28px;
100
+ padding: 0.5em 1em;
101
+ text-decoration: inherit;
102
+ }
103
+
104
+ #hd ul li.active {
105
+ background-color: #323C46;
106
+ color: #F6A828;
107
+ -moz-border-radius: 25px 25px 25px 25px;
108
+ -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5) inset, 0 -1px 0 rgba(255, 255, 255, 0.2) inset;
109
+ }
110
+
111
+ #hd ul li:hover {
112
+ color: #EEE;
113
+ }
114
+
115
+ #title-bar {
116
+ background: #EFEFEF;
117
+ border-bottom: 1px solid #EDEDED;
118
+ color: #5E6469;
119
+ font-size: 1em;
120
+ font-weight: bold;
121
+ line-height: 140%;
122
+ padding: 10px 30px;
123
+ position: relative;
124
+ text-shadow: 0 1px 0 white;
125
+ -moz-box-shadow: 0 1px 2px #AAAAAA;
126
+ -webkit-box-shadow: 0 1px 2px #AAAAAA;
127
+ box-shadow: 0 1px 2px #AAAAAA;
128
+ }
129
+
130
+ #title-bar h2 {
131
+ font-size: 2.6em;
132
+ font-weight: bold;
133
+ margin: 12px 0 10px;
134
+ }
135
+
136
+ #title-bar h4 {
137
+ margin-bottom: 0.25em;
138
+ font-weight: normal;
139
+ }
140
+
141
+ #ft {
142
+ background-color: #FAD08A;
143
+ border-top: 1px solid #F8BC59;
144
+ color: #B17107;
145
+ height: 45px;
146
+ line-height: 44px;
147
+ text-align: center;
148
+ text-shadow: 0 -1px 0 #FBDAA2;
149
+ width: 100%;
150
+ z-index: 2;
151
+ -moz-box-shadow: 0 1px 0 #FCE3BB inset;
152
+ }
153
+
154
+ #menu-bar {
155
+ margin-bottom: 10px;
156
+ }
157
+
158
+ #menu-bar form {
159
+ float: right;
160
+ }
161
+
162
+ #metric-details {
163
+ border-right: 1px solid #EFEFEF;
164
+ float: left;
165
+ padding-right: 20px;
166
+ width: 37%;
167
+ }
168
+
169
+ #metric-details h2 {
170
+ font-size: 500%;
171
+ line-height: normal;
172
+ margin-bottom: 20px;
173
+ color: #323537;
174
+ text-align: center;
175
+ }
176
+
177
+ #metric-children {
178
+ float: right;
179
+ width: 60%;
180
+ }
181
+
182
+ div.payload {
183
+ border-left: 1px solid #EFEFEF;
184
+ padding-left: 10px;
185
+ }
186
+
187
+ div.portlet {
188
+ position: relative;
189
+ float: left;
190
+ width: 45em;
191
+ border: 1px solid #EDEDED;
192
+ padding: 10px;
193
+ margin: 0 20px 20px 0;
194
+ -moz-box-shadow: 1px 1px 1px #AAA;
195
+ -webkit-box-shadow: 1px 1px 1px #AAA;
196
+ box-shadow: 1px 1px 1px #AAA;
197
+ }
198
+
199
+ .hbar {
200
+ display: block;
201
+ background: #0A0;
202
+ height: 10px;
203
+ }
204
+
205
+ .hbar.slow {
206
+ background: #A00;
207
+ }
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,7 @@
1
+ $:.push File.expand_path("../../app/models", __FILE__)
1
2
  require 'rspec'
2
3
  require 'rails'
4
+ require 'system_metrics'
3
5
 
4
6
  # Requires supporting files with custom matchers and macros, etc,
5
7
  # in ./support/ and its subdirectories.
@@ -23,10 +23,13 @@ class CreateMeasurements < ActiveRecord::Migration
23
23
  def self.up
24
24
  create_table :system_metrics, :force => true do |t|
25
25
  t.string :name
26
+ t.string :action
27
+ t.string :category
26
28
  t.datetime :started_at
27
29
  t.string :transaction_id
28
30
  t.text :payload
29
31
  t.float :duration
32
+ t.float :exclusive_duration
30
33
  t.integer :request_id
31
34
  t.integer :parent_id
32
35
  end
@@ -6,9 +6,7 @@ class MockApp
6
6
  end
7
7
 
8
8
  class Config
9
- def system_metrics
10
- @system_metrics ||= {}
11
- end
9
+ attr_accessor :system_metrics
12
10
 
13
11
  def middleware
14
12
  @middleware ||= Middleware.new
@@ -9,4 +9,14 @@ module NotificationsSupport
9
9
  end
10
10
  end
11
11
 
12
+ def event(options={})
13
+ SystemMetrics::NestedEvent.new(
14
+ options[:name] || 'sql.active_record',
15
+ options[:start] || (Time.now - 5.seconds),
16
+ options[:end] || Time.now,
17
+ options[:transaction_id] || 'tid',
18
+ options[:payload] || {}
19
+ )
20
+ end
21
+
12
22
  end