active-record-profiler 1.1.0 → 1.2.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
  SHA1:
3
- metadata.gz: 1a7100d5c7531cd91b863eda7d33b18e4bf42f70
4
- data.tar.gz: bff2d8ace930dbc38ce3a1ec2bc6a36ed9f6e33a
3
+ metadata.gz: 9d6641cabb2840a5296af94eefdcc316c0e9db6a
4
+ data.tar.gz: 4fb6390d719cac7e40cf23fca1cdfa51c25e35fb
5
5
  SHA512:
6
- metadata.gz: 983b8595fbeedc12c65082590033ff996adc409c044682cd8cb6ece0dc893353771c72fdb1b063d137a4f840cceb582f7a9cffafb41a15cd6f7ddbaa78320501
7
- data.tar.gz: 4463447815648e31ca7ac8ace162fa9bcb22647510af5827e7867f3f8a9534c8fe829553ba6e483665d22f53005f12b4674922a7c60937d99350443b6abcf827
6
+ metadata.gz: 2a9998a9a5c8043121ab527de45f88aef74582deb027dc8a54e3c47d6968e1a078f511883f43c46d56d739e283fd34e324a1fd3c5b4a50937cabc1a03aea90b7
7
+ data.tar.gz: b0b449787dd1cf05f38a377cb16518dc71a3a4570625ffc34f6faefb4d4a1acf95c41d24cad032b227a8af1995f5809d722ccaf73bf8706e64c38fc3e6ff6e6a
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ # 1.2.0
2
+
3
+ * Support for registering alternate editor URL schemes (see README)
4
+
1
5
  # 1.1.0
2
6
 
3
7
  * Add self-profiling for the logger component
data/README.md CHANGED
@@ -1,6 +1,5 @@
1
1
  ActiveRecordProfiler
2
2
  ====================
3
- ** Note: ** This gem is in transition from an old Rails 2.x plugin and still has some issues to iron out. In particular, using the notification system to track ActiveRecord query durations isn't as straightforward as it seems, so the times recorded by the profiler don't match the times ActiveRecord reports in the logs. It's still handy for tracking where your N+1 queries are coming from, thoug....
4
3
 
5
4
  The `active-record-profiler` gem adds a log formatter to improve the standard SQL logging and a log subscriber to provide profiler-like tracking of SQL statements generated by application code. The log formatter makes the SQL statements in your logs look like this (imagine it's all in one log line):
6
5
 
@@ -21,13 +20,17 @@ Installation
21
20
  ============
22
21
  Add it to your Gemfile, like so:
23
22
 
24
- gem 'active-record-profiler'
23
+ ```ruby
24
+ gem 'active-record-profiler'
25
+ ```
25
26
 
26
27
  Then do `bundle install`, and then add a new initializer, `config/initializers/active_record_profiler.rb`:
27
28
 
28
- ActiveRecord::Base.logger =
29
- ActiveRecordProfiler::Logger.new(ActiveRecord::Base.logger)
30
- ActiveRecordProfiler::LogSubscriber.attach_to :active_record unless Rails.env.test?
29
+ ```ruby
30
+ ActiveRecord::Base.logger =
31
+ ActiveRecordProfiler::Logger.new(ActiveRecord::Base.logger)
32
+ ActiveRecordProfiler::LogSubscriber.attach_to :active_record unless Rails.env.test?
33
+ ```
31
34
 
32
35
  The first line adds call-site information to ActiveRecord logging, and the second line enables profiling (except in the test environment, where it would mess up your profiling data).
33
36
 
@@ -37,65 +40,107 @@ Configuration
37
40
  ## stats_flush_period ##
38
41
  Control the (approximate) frequency of statistics flushes (default: `1.hour`)
39
42
 
40
- ActiveRecordProfiler.stats_flush_period = 1.hour
43
+ ```ruby
44
+ ActiveRecordProfiler.stats_flush_period = 1.hour
45
+ ```
41
46
 
42
- Note that only flushed data is available for use in the rake reports (described below). If you are running a multithreaded or multiprocess server (which covers most common rails server types), your data will be incomplete until all those threads/processes/servers have flushed their data. This limitation exists primarily to avoid the overhead of coordinating/locking during the process of serving your application's web requests.
47
+ Note that only flushed data is available for use in the reports (described below). If you are running a multithreaded or multiprocess server (which covers most common rails server types), your data will be incomplete until all those threads/processes/servers have flushed their data. This limitation exists primarily to avoid the overhead of coordinating/locking during the process of serving your application's web requests.
43
48
 
44
49
  ## profile_dir ##
45
50
  Directory where profile data is recorded. (default: `Rails.root,join('log', 'profiler_data'`)
46
51
 
47
- ActiveRecordProfiler.profile_dir = Rails.root.join('log', 'profiler_data'
52
+ ```ruby
53
+ ActiveRecordProfiler.profile_dir = Rails.root.join('log', 'profiler_data')
54
+ ```
48
55
 
49
56
  ## sql_ignore_pattern ##
50
- Any SQL statements matching this pattern will not be tracked by the profiler output, though it will still appear in the enhanced SQL logging. (default: `/^(SHOW FIELDS |SET SQL_AUTO_IS_NULL|SET NAMES |EXPLAIN |BEGIN|COMMIT|PRAGMA )/`)
57
+ Any SQL statements matching this pattern will not be tracked by the profiler output, though it will still appear in the enhanced SQL logging. (default: `/^(SHOW (:?FULL )?FIELDS |SET SQL_AUTO_IS_NULL|SET NAMES |EXPLAIN |BEGIN|COMMIT|PRAGMA )/`)
51
58
 
52
- ActiveRecordProfiler.sql_ignore_pattern = /^SET /x
59
+ ```ruby
60
+ ActiveRecordProfiler.sql_ignore_pattern = /^SET /x
61
+ ```
53
62
 
54
63
  ## app_path_pattern ##
55
64
  Any calling location that matches this pattern will be tracked individually. Any locations that do __not__ match will be grouped under a single `Non-application code` label. The default only includes the `app`, `lib`, and `vendor` directories, but that's usually suitable and avoids noise. (default: `Regexp.new(Regexp.quote("#{Rails.root.expand_path}/") + "(:?app|lib|vendor)/")`)
56
65
 
57
- ActiveRecordProfiler.app_path_pattern = Regexp.new(Regexp.quote("#{Rails.root.expand_path}/"))
66
+ ```ruby
67
+ ActiveRecordProfiler.app_path_pattern = Regexp.new(Regexp.quote("#{Rails.root.expand_path}/"))
68
+ ```
58
69
 
59
70
  ## trim_root_path ##
60
71
  This prefix will be removed from the calling site filepath for brevity. (default: `"#{Rails.root.expand_path}/"`)
61
72
 
62
- ActiveRecordProfiler.trim_root_path = "#{Rails.root.parent.expand_path}/app"
73
+ ```ruby
74
+ ActiveRecordProfiler.trim_root_path = "#{Rails.root.parent.expand_path}/app"
75
+ ```
63
76
 
64
77
  ## profile_self ##
65
78
  This setting controls whether the profiler records information about how much time was spent in the profiling code itself. If you want to know what kind of overhead the profiler is adding, set this to true. (default: `false`)
66
79
 
67
- ActiveRecordProfiler.profile_self = true
68
-
80
+ ```ruby
81
+ ActiveRecordProfiler.profile_self = true
82
+ ```
69
83
 
70
84
  ## link_location ##
71
85
  Whether or not to make the locations in the profiler reports into source code links (only works with editors that can be launched via URL scheme) (default: `false`):
72
86
 
73
- ActiveRecordProfiler.link_location = true
74
-
87
+ ```ruby
88
+ ActiveRecordProfiler.link_location = true
89
+ ```
90
+
91
+ ## Source Code Editor Links ##
92
+ ActiveRecordProfiler currently only knows how to build links for a couple of different editors, but you can configure your own by adding a partial to your application, in `shared/active_record_profiler/_editor.html.erb`, which contains javascript code to set up a new formatter:
93
+
94
+ ```html
95
+ <script type="text/javascript">
96
+ // Remove default formatters, if you want:
97
+ // ActiveRecordProfiler.clearLinkFormatters();
98
+ //
99
+ // Add a new editor with a name and a function that takes the file and line
100
+ // number, and returns a URL that links to that source code location:
101
+ ActiveRecordProfiler.registerLinkFormatter('Sublime Text',
102
+ function(file, line, selectedLinkFormatter) {
103
+ return "subl://open/?url=file://" + file + "&line=" + line;
104
+ }
105
+ );
106
+ </script>
107
+ ```
108
+
109
+ The `ActiveRecordProfiler.registerLinkFormatter` method takes a `name` parameter (this shows up in the Editor menu) and a function which will be passed the `file` and `line` of a calling site. It will also be sent the `name` of the currently selected formatter, but this is usually ignored. The function should return a URL that links to the editor or source code view.
75
110
 
76
111
  Command Line Reports
77
112
  ====================
78
113
  To see a top-100 list of what SQL statements your application is spending its time in, run the following rake task:
79
114
 
80
- rake profiler:aggregate max_lines=100 show_sql=true
115
+ ```bash
116
+ rake profiler:aggregate max_lines=100 show_sql=true
117
+ ```
81
118
 
82
119
  This will return a list of the SQL which is taking the most time in your application in this format:
83
120
 
84
- <file path>:<line number>:in <method name>: <total duration>, <call count>, <max single call duration>
121
+ ```
122
+ <file path>:<line number>:in <method name>: <total duration>, <call count>, <max single call duration>
123
+ ```
85
124
 
86
125
  This will aggregate all of the profiler data you have accumulated; in order to limit the timeframe of the data, use the `prefix` option to specify a partial date/time:
87
126
 
88
- rake profiler:aggregate max_lines=100 show_sql=true prefix=2010-06-20-10 # data from June 20 during the 10am hour (roughly)
127
+ ```bash
128
+ rake profiler:aggregate max_lines=100 show_sql=true prefix=2010-06-20-10 # data from June 20 during the 10am hour (roughly)
129
+ ```
89
130
 
90
131
  Each thread running the profiler flushes its stats periodically, and there is a rake task to combine multiple profiler data files together in order to keep the number of data files down to a manageable number. A good way to manage the data files on a server is to set up a cron task to run the following command once per hour or once per day:
91
132
 
92
- rake profiler:aggregate compact=<'hour' or 'date'> RAILS_ENV=qa
133
+ ```bash
134
+ rake profiler:aggregate compact=<'hour' or 'date'> RAILS_ENV=qa
135
+ ```
93
136
 
94
137
  Compacting by hour will result in a single file for each hour any process dumped its stats. Compacting by day will result in a single file for each day. When using the `prefix` option to generate a profiler report, you cannot specify an hour if you have compacted your data by date instead of hour (the prefix matching operates on the file names, which will not have hours if they have been compacted by date).
95
138
 
96
139
  You can clear out all profiler data using the following command:
97
140
 
98
- rake profiler:clear_data
141
+ ```bash
142
+ rake profiler:clear_data
143
+ ```
99
144
 
100
145
  If you want programmatic access to the profiler data, check out the source code for the rake tasks in `lib/active-record-profiler/tasks.rake`.
101
146
 
@@ -109,13 +154,17 @@ The `active-record-profiler` gem also includes support for producing reports in
109
154
 
110
155
  In order to make it available, you'll want to mount the engine within your application's `routes.rb`. Since you don't want the public to have access to your profiler reports, you'll want to limit access to it. You could only mount the profiler's web interface in the development environment:
111
156
 
112
- mount ActiveRecordProfiler::Engine => "/profiler" if Rails.env.development?
157
+ ```ruby
158
+ mount ActiveRecordProfiler::Engine => "/profiler" if Rails.env.development?
159
+ ```
113
160
 
114
161
  Or, if you are using [Devise](https://github.com/plataformatec/devise) and have an admin flag on a `User` model, for example:
115
162
 
116
- authenticated :user, -> user { user.admin? } do
117
- mount ActiveRecordProfiler::Engine => "/profiler"
118
- end
163
+ ```ruby
164
+ authenticated :user, -> user { user.admin? } do
165
+ mount ActiveRecordProfiler::Engine => "/profiler"
166
+ end
167
+ ```
119
168
 
120
169
  When you visit the path where you've mounted the web interface, you will by default see a report for the current day. If you just installed `active-record-profiler`, there probably won't be anything there yet, in which case you should go play with your app for a while and come back later. :) Also note that if the web server you are using has multiple processes or threads, you won't see data from those other processes/threads until they dump their data.
121
170
 
@@ -3,7 +3,8 @@ var ActiveRecordProfiler = (function (my_module) {
3
3
 
4
4
  var SOURCE_ROOT_KEY = "db_prof_source_root";
5
5
  var SOURCE_EDITOR_KEY = "db_prof_source_editor";
6
- var profilerSourceRootField, sourceEditorSelect, railsRoot;
6
+ var profilerSourceRootField, sourceEditorSelect, railsRoot, editorOptions,
7
+ linkFormatters = {};
7
8
 
8
9
  function supportsLocalStorage() {
9
10
  try {
@@ -53,30 +54,58 @@ var ActiveRecordProfiler = (function (my_module) {
53
54
  }
54
55
  }
55
56
 
56
- my_module.formatLink = function (file, line, editor) {
57
- var link;
57
+ my_module.clearLinkFormatters = function () {
58
+ $.each(linkFormatters, function (editorName, formatter) {
59
+ if (editorOptions[editorName]) {
60
+ editorOptions[editorName].remove();
61
+ }
62
+ });
63
+ editorOptions = null;
64
+ linkFormatters = {};
65
+ };
58
66
 
59
- switch (editor) {
60
- case "subl":
61
- case "txmt":
62
- link = editor + "://open/?url=file://" + file + "&line=" + line;
63
- break;
64
- default:
65
- // do nothing, return undefined link
67
+ my_module.registerLinkFormatter = function (name, formatter) {
68
+ if (!editorOptions) {
69
+ editorOptions = {};
70
+ sourceEditorSelect.find('option').each(function (index, el) {
71
+ jqElement = $(el);
72
+ editorOptions[jqElement.text()] = jqElement;
73
+ });
66
74
  }
67
75
 
68
- return link;
76
+ linkFormatters[name] = formatter;
77
+ if (!editorOptions[name]) {
78
+ var newOption = $('<option>').text(name);
79
+ editorOptions[name] = newOption;
80
+ sourceEditorSelect.append(newOption);
81
+ if (name === getSourceEditor()) {
82
+ sourceEditorSelect.val(name);
83
+ }
84
+ } // else we already have an option and are just replacing the formatter
69
85
  };
70
86
 
71
87
  my_module.showSourceFile = function (file, line) {
72
88
  var root = profilerSourceRootField.val();
73
89
  var editor = sourceEditorSelect.val();
74
90
  if (root == "") { root = railsRoot; }
75
- // window.location = "txmt://open/?url=file://" + root + "/" + file + "&line=" + line;
76
- var link = my_module.formatLink(root + "/" + file, line, editor);
77
- if (link) {
78
- window.location = link;
91
+
92
+ if (!editor) {
93
+ console.log("Cannot link to source code: no editor specified.");
94
+ return;
95
+ }
96
+ var linkFormatter = linkFormatters[editor];
97
+ if (!linkFormatter) {
98
+ console.log("Cannot link to source code: no link formatter for editor '" + editor + "'.");
99
+ return;
100
+ }
101
+ var link = linkFormatter(root + "/" + file, line, editor);
102
+ if (!link) {
103
+ console.log("Cannot link to source code: link formatter returned undefined.");
104
+ return;
79
105
  }
106
+
107
+ // Send browser to editor link
108
+ window.location = link;
80
109
  };
81
110
 
82
111
  $(function () {
@@ -98,6 +127,20 @@ var ActiveRecordProfiler = (function (my_module) {
98
127
  var link = $(this);
99
128
  my_module.showSourceFile(link.data('file'), link.data('line'));
100
129
  });
130
+
131
+ // Install console.log dummy function if it doesn't exist, so we can log
132
+ // without fuss.
133
+ if (typeof window.console == 'undefined') {
134
+ window.console = {log: function (msg) {} };
135
+ }
136
+
137
+ // Add known editors/link formatters
138
+ ActiveRecordProfiler.registerLinkFormatter('Sublime Text', function(file, line) {
139
+ return "subl://open/?url=file://" + file + "&line=" + line;
140
+ });
141
+ ActiveRecordProfiler.registerLinkFormatter('TextMate', function(file, line) {
142
+ return "txmt://open/?url=file://" + file + "&line=" + line;
143
+ });
101
144
  });
102
145
 
103
146
  return my_module;
@@ -5,7 +5,5 @@
5
5
  <label for="source_root">Editor (for location links):</label>
6
6
  <select id="source_editor">
7
7
  <option value="">None</option>
8
- <option value="subl">Sublime Text</option>
9
- <option value="txmt">TextMate</option>
10
8
  </select>
11
9
  </form>
@@ -10,5 +10,7 @@
10
10
 
11
11
  <%= yield %>
12
12
 
13
+ <%= render 'shared/active_record_profiler/editors' %>
14
+
13
15
  </body>
14
16
  </html>
@@ -0,0 +1,10 @@
1
+ <script type="text/javascript">
2
+ // Remove default formatters, if you want:
3
+ // ActiveRecordProfiler.clearLinkFormatters();
4
+ //
5
+ // Add a new editor with a name and a function that takes the file and line
6
+ // number, and returns a URL that links to that source code location:
7
+ // ActiveRecordProfiler.registerLinkFormatter('Sublime Text', function(file, line) {
8
+ // return "subl://open/?url=file://" + file + "&line=" + line;
9
+ // });
10
+ </script>
@@ -1,3 +1,3 @@
1
1
  module ActiveRecordProfiler
2
- VERSION = "1.1.0"
2
+ VERSION = "1.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active-record-profiler
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Turner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-27 00:00:00.000000000 Z
11
+ date: 2015-01-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -122,6 +122,7 @@ files:
122
122
  - app/views/active_record_profiler/reports/_report_table.html.erb
123
123
  - app/views/active_record_profiler/reports/index.html.erb
124
124
  - app/views/layouts/active_record_profiler/application.html.erb
125
+ - app/views/shared/active_record_profiler/_editors.html.erb
125
126
  - config/initializers/default_config.rb
126
127
  - config/routes.rb
127
128
  - lib/active-record-profiler.rb