rack-mini-profiler 0.1.6 → 0.1.11.pre

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.

Potentially problematic release.


This version of rack-mini-profiler might be problematic. Click here for more details.

@@ -13,6 +13,7 @@ module Rack
13
13
  data = ::File.open(path(key),"rb") {|f| f.read}
14
14
  return Marshal.load data
15
15
  rescue => e
16
+ p e
16
17
  return nil
17
18
  end
18
19
  end
@@ -39,9 +40,14 @@ module Rack
39
40
 
40
41
  me = self
41
42
  Thread.new do
42
- while true do
43
- me.cleanup_cache if MiniProfiler.instance
44
- sleep(3600)
43
+ begin
44
+ while true do
45
+ # TODO: a sane retry count before bailing
46
+ me.cleanup_cache
47
+ sleep(3600)
48
+ end
49
+ rescue
50
+ # don't crash the thread, we can clean up next time
45
51
  end
46
52
  end
47
53
  end
@@ -83,10 +89,6 @@ module Rack
83
89
  }
84
90
  end
85
91
 
86
-
87
- private
88
-
89
-
90
92
  def cleanup_cache
91
93
  files = Dir.entries(@path)
92
94
  @timer_struct_lock.synchronize {
@@ -52,10 +52,6 @@ module Rack
52
52
  }
53
53
  end
54
54
 
55
-
56
- private
57
-
58
-
59
55
  def cleanup_cache
60
56
  expire_older_than = ((Time.now.to_f - MiniProfiler::MemoryStore::EXPIRE_TIMER_CACHE) * 1000).to_i
61
57
  @timer_struct_lock.synchronize {
@@ -22,7 +22,9 @@ module Rack
22
22
  end
23
23
 
24
24
  def to_json(*a)
25
- ::JSON.generate(@attributes, a[0])
25
+ # this does could take in an option hash, but the only interesting there is max_nesting.
26
+ # if this becomes an option we could increase
27
+ ::JSON.generate( @attributes, :max_nesting => 100 )
26
28
  end
27
29
 
28
30
  end
@@ -1,3 +1,5 @@
1
+ require 'fileutils'
2
+
1
3
  module MiniProfilerRails
2
4
 
3
5
  class Railtie < ::Rails::Railtie
@@ -22,7 +24,7 @@ module MiniProfilerRails
22
24
 
23
25
  # The file store is just so much less flaky
24
26
  tmp = Rails.root.to_s + "/tmp/miniprofiler"
25
- Dir::mkdir(tmp) unless File.exists?(tmp)
27
+ FileUtils.mkdir_p(tmp) unless File.exists?(tmp)
26
28
 
27
29
  c.storage_options = {:path => tmp}
28
30
  c.storage = Rack::MiniProfiler::FileStore
@@ -13,6 +13,12 @@ class SqlPatches
13
13
  rescue NameError
14
14
  false
15
15
  end
16
+
17
+ def self.module_exists?(name)
18
+ eval(name + ".class").to_s.eql?('Module')
19
+ rescue NameError
20
+ false
21
+ end
16
22
  end
17
23
 
18
24
  # The best kind of instrumentation is in the actual db provider, however we don't want to double instrument
@@ -85,6 +91,23 @@ if SqlPatches.class_exists? "PG::Result"
85
91
  class PG::Connection
86
92
  alias_method :exec_without_profiling, :exec
87
93
  alias_method :async_exec_without_profiling, :async_exec
94
+ alias_method :exec_prepared_without_profiling, :exec_prepared
95
+ alias_method :send_query_prepared_without_profiling, :send_query_prepared
96
+ alias_method :prepare_without_profiling, :prepare
97
+
98
+ def prepare(*args,&blk)
99
+ current = ::Rack::MiniProfiler.current
100
+ return prepare_without_profiling(*args,&blk) unless current
101
+
102
+ @prepare_map ||= {}
103
+ @prepare_map[args[0]] = args[1]
104
+
105
+ # dont leak more than 10k ever
106
+ @prepare_map = {} if @prepare_map.length > 10000
107
+
108
+ prepare_without_profiling(*args,&blk)
109
+
110
+ end
88
111
 
89
112
  def exec(*args,&blk)
90
113
  current = ::Rack::MiniProfiler.current
@@ -98,6 +121,34 @@ if SqlPatches.class_exists? "PG::Result"
98
121
  result
99
122
  end
100
123
 
124
+ def exec_prepared(*args,&blk)
125
+ current = ::Rack::MiniProfiler.current
126
+ return exec_prepared_without_profiling(*args,&blk) unless current
127
+
128
+ start = Time.now
129
+ result = exec_prepared_without_profiling(*args,&blk)
130
+ elapsed_time = ((Time.now - start).to_f * 1000).round(1)
131
+ mapped = args[0]
132
+ mapped = @prepare_map[mapped] || args[0] if @prepare_map
133
+ result.instance_variable_set("@miniprofiler_sql_id", ::Rack::MiniProfiler.record_sql(mapped, elapsed_time))
134
+
135
+ result
136
+ end
137
+
138
+ def send_query_prepared(*args,&blk)
139
+ current = ::Rack::MiniProfiler.current
140
+ return send_query_prepared_without_profiling(*args,&blk) unless current
141
+
142
+ start = Time.now
143
+ result = send_query_prepared_without_profiling(*args,&blk)
144
+ elapsed_time = ((Time.now - start).to_f * 1000).round(1)
145
+ mapped = args[0]
146
+ mapped = @prepare_map[mapped] || args[0] if @prepare_map
147
+ result.instance_variable_set("@miniprofiler_sql_id", ::Rack::MiniProfiler.record_sql(mapped, elapsed_time))
148
+
149
+ result
150
+ end
151
+
101
152
  def async_exec(*args,&blk)
102
153
  current = ::Rack::MiniProfiler.current
103
154
  return exec_without_profiling(*args,&blk) unless current
@@ -134,45 +185,46 @@ end
134
185
 
135
186
  ## based off https://github.com/newrelic/rpm/blob/master/lib/new_relic/agent/instrumentation/active_record.rb
136
187
  ## fallback for alls sorts of weird dbs
137
- module Rack
138
- class MiniProfiler
139
- module ActiveRecordInstrumentation
140
- def self.included(instrumented_class)
141
- instrumented_class.class_eval do
142
- unless instrumented_class.method_defined?(:log_without_miniprofiler)
143
- alias_method :log_without_miniprofiler, :log
144
- alias_method :log, :log_with_miniprofiler
145
- protected :log
188
+ if SqlPatches.module_exists?('ActiveRecord')
189
+ module Rack
190
+ class MiniProfiler
191
+ module ActiveRecordInstrumentation
192
+ def self.included(instrumented_class)
193
+ instrumented_class.class_eval do
194
+ unless instrumented_class.method_defined?(:log_without_miniprofiler)
195
+ alias_method :log_without_miniprofiler, :log
196
+ alias_method :log, :log_with_miniprofiler
197
+ protected :log
198
+ end
146
199
  end
147
200
  end
148
- end
149
201
 
150
- def log_with_miniprofiler(*args, &block)
151
- current = ::Rack::MiniProfiler.current
152
- return log_without_miniprofiler(*args, &block) unless current
202
+ def log_with_miniprofiler(*args, &block)
203
+ current = ::Rack::MiniProfiler.current
204
+ return log_without_miniprofiler(*args, &block) unless current
153
205
 
154
- sql, name, binds = args
155
- t0 = Time.now
156
- rval = log_without_miniprofiler(*args, &block)
157
-
158
- # Don't log schema queries if the option is set
159
- return rval if Rack::MiniProfiler.config.skip_schema_queries and name =~ /SCHEMA/
206
+ sql, name, binds = args
207
+ t0 = Time.now
208
+ rval = log_without_miniprofiler(*args, &block)
209
+
210
+ # Don't log schema queries if the option is set
211
+ return rval if Rack::MiniProfiler.config.skip_schema_queries and name =~ /SCHEMA/
160
212
 
161
- elapsed_time = ((Time.now - t0).to_f * 1000).round(1)
162
- Rack::MiniProfiler.record_sql(sql, elapsed_time)
163
- rval
213
+ elapsed_time = ((Time.now - t0).to_f * 1000).round(1)
214
+ Rack::MiniProfiler.record_sql(sql, elapsed_time)
215
+ rval
216
+ end
164
217
  end
165
218
  end
166
- end
167
219
 
168
- def self.insert_instrumentation
169
- ActiveRecord::ConnectionAdapters::AbstractAdapter.module_eval do
170
- include ::Rack::MiniProfiler::ActiveRecordInstrumentation
220
+ def self.insert_instrumentation
221
+ ActiveRecord::ConnectionAdapters::AbstractAdapter.module_eval do
222
+ include ::Rack::MiniProfiler::ActiveRecordInstrumentation
223
+ end
171
224
  end
172
- end
173
225
 
174
- if defined?(::Rails) && !SqlPatches.patched?
175
- insert_instrumentation
226
+ if defined?(::Rails) && !SqlPatches.patched?
227
+ insert_instrumentation
228
+ end
176
229
  end
177
230
  end
178
-
@@ -1,6 +1,6 @@
1
- require File.expand_path('mini_profiler/profiler', File.dirname(__FILE__) )
2
- require File.expand_path('patches/sql_patches', File.dirname(__FILE__) )
1
+ require 'mini_profiler/profiler'
2
+ require 'patches/sql_patches'
3
3
 
4
4
  if defined?(::Rails) && ::Rails::VERSION::MAJOR.to_i == 3
5
- require File.expand_path('mini_profiler_rails/railtie', File.dirname(__FILE__) )
5
+ require 'mini_profiler_rails/railtie'
6
6
  end
@@ -1,9 +1,8 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "rack-mini-profiler"
3
- s.version = "0.1.6"
3
+ s.version = "0.1.11.pre"
4
4
  s.summary = "Profiles loading speed for rack applications."
5
5
  s.authors = ["Aleks Totic","Sam Saffron", "Robin Ward"]
6
- s.date = "2012-04-02"
7
6
  s.description = "Page loading speed displayed on every page. Optimize while you develop, performance is a feature."
8
7
  s.email = "sam.saffron@gmail.com"
9
8
  s.homepage = "http://miniprofiler.com"
@@ -14,9 +13,9 @@ Gem::Specification.new do |s|
14
13
  "README.md",
15
14
  "CHANGELOG"
16
15
  ]
17
- s.add_runtime_dependency 'rack', '>= 1.1.3'
16
+ s.add_runtime_dependency 'rack', '>= 1.1.3'
18
17
  if RUBY_VERSION < "1.9"
19
- s.add_runtime_dependency 'json', '>= 1.6'
18
+ s.add_runtime_dependency 'json', '>= 1.6'
20
19
  end
21
20
 
22
21
  s.add_development_dependency 'rake'
metadata CHANGED
@@ -1,8 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-mini-profiler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
5
- prerelease:
4
+ version: 0.1.11.pre
5
+ prerelease: 7
6
6
  platform: ruby
7
7
  authors:
8
8
  - Aleks Totic
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2012-04-02 00:00:00.000000000 Z
14
+ date: 2012-08-10 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rack
@@ -93,7 +93,6 @@ files:
93
93
  - lib/mini_profiler/page_timer_struct.rb
94
94
  - lib/mini_profiler/context.rb
95
95
  - lib/mini_profiler/config.rb
96
- - lib/mini_profiler/body_add_proxy.rb
97
96
  - lib/mini_profiler/profiling_methods.rb
98
97
  - lib/mini_profiler/client_timer_struct.rb
99
98
  - lib/mini_profiler/profiler.rb
@@ -107,7 +106,6 @@ files:
107
106
  - lib/html/share.html
108
107
  - lib/html/includes.less
109
108
  - lib/html/list.css
110
- - lib/html/MiniProfilerHandler.cs
111
109
  - lib/html/includes.js
112
110
  - lib/html/jquery.tmpl.js
113
111
  - lib/html/list.tmpl
@@ -132,16 +130,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
132
130
  version: '0'
133
131
  segments:
134
132
  - 0
135
- hash: -974819475
133
+ hash: -126757873
136
134
  required_rubygems_version: !ruby/object:Gem::Requirement
137
135
  none: false
138
136
  requirements:
139
- - - ! '>='
137
+ - - ! '>'
140
138
  - !ruby/object:Gem::Version
141
- version: '0'
142
- segments:
143
- - 0
144
- hash: -974819475
139
+ version: 1.3.1
145
140
  requirements: []
146
141
  rubyforge_project:
147
142
  rubygems_version: 1.8.24
@@ -1,419 +0,0 @@
1
- using System;
2
- using System.Collections.Generic;
3
- using System.IO;
4
- using System.Web;
5
- using System.Web.Routing;
6
- using System.Linq;
7
-
8
- using StackExchange.Profiling.Helpers;
9
- using System.Text;
10
- using System.Collections.Concurrent;
11
-
12
- namespace StackExchange.Profiling.UI
13
- {
14
- /// <summary>
15
- /// Understands how to route and respond to MiniProfiler UI urls.
16
- /// </summary>
17
- public class MiniProfilerHandler : IRouteHandler, IHttpHandler
18
- {
19
- internal static HtmlString RenderIncludes(MiniProfiler profiler, RenderPosition? position = null, bool? showTrivial = null, bool? showTimeWithChildren = null, int? maxTracesToShow = null, bool? showControls = null, bool? useExistingjQuery = null)
20
- {
21
- string format = GetResource("include.partial.html");
22
-
23
- var result = "";
24
-
25
- if (profiler != null)
26
- {
27
- // HACK: unviewed ids are added to this list during Storage.Save, but we know we haven't see the current one yet,
28
- // so go ahead and add it to the end - it's usually the only id, but if there was a redirect somewhere, it'll be there, too
29
- MiniProfiler.Settings.EnsureStorageStrategy();
30
-
31
- var authorized =
32
- MiniProfiler.Settings.Results_Authorize == null ||
33
- MiniProfiler.Settings.Results_Authorize(HttpContext.Current.Request);
34
-
35
- List<Guid> ids;
36
- if (authorized)
37
- {
38
- ids = MiniProfiler.Settings.Storage.GetUnviewedIds(profiler.User);
39
- ids.Add(profiler.Id);
40
- }
41
- else
42
- {
43
- ids = new List<Guid> { profiler.Id };
44
- }
45
-
46
- result = format.Format(new
47
- {
48
- path = VirtualPathUtility.ToAbsolute(MiniProfiler.Settings.RouteBasePath).EnsureTrailingSlash(),
49
- version = MiniProfiler.Settings.Version,
50
- ids = ids.ToJson(),
51
- position = (position ?? MiniProfiler.Settings.PopupRenderPosition).ToString().ToLower(),
52
- showTrivial = showTrivial ?? MiniProfiler.Settings.PopupShowTrivial ? "true" : "false",
53
- showChildren = showTimeWithChildren ?? MiniProfiler.Settings.PopupShowTimeWithChildren ? "true" : "false",
54
- maxTracesToShow = maxTracesToShow ?? MiniProfiler.Settings.PopupMaxTracesToShow,
55
- showControls = showControls ?? MiniProfiler.Settings.ShowControls ? "true" : "false",
56
- currentId = profiler.Id,
57
- authorized = authorized ? "true" : "false",
58
- useExistingjQuery = useExistingjQuery ?? MiniProfiler.Settings.UseExistingjQuery ? "true" : "false"
59
- });
60
-
61
- }
62
-
63
- return new HtmlString(result);
64
- }
65
-
66
- /// <summary>
67
- /// Usually called internally, sometimes you may clear the routes during the apps lifecycle, if you do that call this to bring back mp
68
- /// </summary>
69
- public static void RegisterRoutes()
70
- {
71
-
72
- var routes = RouteTable.Routes;
73
- var handler = new MiniProfilerHandler();
74
- var prefix = MiniProfiler.Settings.RouteBasePath.Replace("~/", "").EnsureTrailingSlash();
75
-
76
- using (routes.GetWriteLock())
77
- {
78
- var route = new Route(prefix + "{filename}", handler)
79
- {
80
- // we have to specify these, so no MVC route helpers will match, e.g. @Html.ActionLink("Home", "Index", "Home")
81
- Defaults = new RouteValueDictionary( new { controller = "MiniProfilerHandler", action = "ProcessRequest" }),
82
- Constraints = new RouteValueDictionary( new { controller = "MiniProfilerHandler", action = "ProcessRequest" })
83
- };
84
-
85
- // put our routes at the beginning, like a boss
86
- routes.Insert(0, route);
87
- }
88
- }
89
-
90
- /// <summary>
91
- /// Returns this <see cref="MiniProfilerHandler"/> to handle <paramref name="requestContext"/>.
92
- /// </summary>
93
- public IHttpHandler GetHttpHandler(RequestContext requestContext)
94
- {
95
- return this; // elegant? I THINK SO.
96
- }
97
-
98
- /// <summary>
99
- /// Try to keep everything static so we can easily be reused.
100
- /// </summary>
101
- public bool IsReusable
102
- {
103
- get { return true; }
104
- }
105
-
106
- /// <summary>
107
- /// Returns either includes' css/javascript or results' html.
108
- /// </summary>
109
- public void ProcessRequest(HttpContext context)
110
- {
111
- string output;
112
- string path = context.Request.AppRelativeCurrentExecutionFilePath;
113
-
114
- switch (Path.GetFileNameWithoutExtension(path).ToLowerInvariant())
115
- {
116
- case "jquery.1.7.1":
117
- case "jquery.tmpl":
118
- case "includes":
119
- case "list":
120
- output = Includes(context, path);
121
- break;
122
-
123
- case "results-index":
124
- output = Index(context);
125
- break;
126
-
127
- case "results-list":
128
- output = ResultList(context);
129
- break;
130
-
131
- case "results":
132
- output = Results(context);
133
- break;
134
-
135
- default:
136
- output = NotFound(context);
137
- break;
138
- }
139
-
140
- context.Response.Write(output);
141
- }
142
-
143
- private static string ResultList(HttpContext context)
144
- {
145
- string message;
146
- if (!AuthorizeRequest(context, isList: true, message: out message))
147
- {
148
- return message;
149
- }
150
-
151
- var lastId = context.Request["last-id"];
152
- Guid lastGuid = Guid.Empty;
153
-
154
- if (!lastId.IsNullOrWhiteSpace()) {
155
- Guid.TryParse(lastId, out lastGuid);
156
- }
157
-
158
- var guids = MiniProfiler.Settings.Storage.List(100);
159
-
160
- if (lastGuid != Guid.Empty)
161
- {
162
- guids = guids.TakeWhile(g => g != lastGuid);
163
- }
164
-
165
- guids = guids.Reverse();
166
-
167
- return guids.Select(g =>
168
- {
169
- var profiler = MiniProfiler.Settings.Storage.Load(g);
170
- return new
171
- {
172
- profiler.Id,
173
- profiler.Name,
174
- profiler.DurationMilliseconds,
175
- profiler.DurationMillisecondsInSql,
176
- profiler.ClientTimings,
177
- profiler.Started,
178
- profiler.ExecutedNonQueries,
179
- profiler.ExecutedReaders,
180
- profiler.ExecutedScalars,
181
- profiler.HasAllTrivialTimings,
182
- profiler.HasDuplicateSqlTimings,
183
- profiler.HasSqlTimings,
184
- profiler.HasTrivialTimings,
185
- profiler.HasUserViewed,
186
- profiler.MachineName,
187
- profiler.User
188
- };
189
- }
190
-
191
- ).ToJson();
192
- }
193
-
194
- private static string Index(HttpContext context)
195
- {
196
- string message;
197
- if (!AuthorizeRequest(context, isList: true, message: out message))
198
- {
199
- return message;
200
- }
201
-
202
- context.Response.ContentType = "text/html";
203
-
204
- var path = VirtualPathUtility.ToAbsolute(MiniProfiler.Settings.RouteBasePath).EnsureTrailingSlash();
205
-
206
- return new StringBuilder()
207
- .AppendLine("<html><head>")
208
- .AppendFormat("<title>List of profiling sessions</title>")
209
- .AppendLine()
210
- .AppendLine("<script type='text/javascript' src='" + path + "jquery.1.7.1.js?v=" + MiniProfiler.Settings.Version + "'></script>")
211
- .AppendLine("<script type='text/javascript' src='" + path + "jquery.tmpl.js?v=" + MiniProfiler.Settings.Version + "'></script>")
212
- .AppendLine("<script type='text/javascript' src='" + path + "includes.js?v=" + MiniProfiler.Settings.Version + "'></script>")
213
- .AppendLine("<script type='text/javascript' src='" + path + "list.js?v=" + MiniProfiler.Settings.Version + "'></script>")
214
- .AppendLine("<link href='" + path +"list.css?v=" + MiniProfiler.Settings.Version + "' rel='stylesheet' type='text/css'>")
215
- .AppendLine("<script type='text/javascript'>MiniProfiler.list.init({path: '" + path + "', version: '" + MiniProfiler.Settings.Version + "'})</script>")
216
- .AppendLine("</head><body></body></html>")
217
- .ToString();
218
- }
219
-
220
- /// <summary>
221
- /// Handles rendering static content files.
222
- /// </summary>
223
- private static string Includes(HttpContext context, string path)
224
- {
225
- var response = context.Response;
226
-
227
- switch (Path.GetExtension(path))
228
- {
229
- case ".js":
230
- response.ContentType = "application/javascript";
231
- break;
232
- case ".css":
233
- response.ContentType = "text/css";
234
- break;
235
- case ".tmpl":
236
- response.ContentType = "text/x-jquery-tmpl";
237
- break;
238
- default:
239
- return NotFound(context);
240
- }
241
-
242
- #if !DEBUG
243
- var cache = response.Cache;
244
- cache.SetCacheability(System.Web.HttpCacheability.Public);
245
- cache.SetExpires(DateTime.Now.AddDays(7));
246
- cache.SetValidUntilExpires(true);
247
- #endif
248
-
249
-
250
- var embeddedFile = Path.GetFileName(path);
251
- return GetResource(embeddedFile);
252
- }
253
-
254
- /// <summary>
255
- /// Handles rendering a previous MiniProfiler session, identified by its "?id=GUID" on the query.
256
- /// </summary>
257
- private static string Results(HttpContext context)
258
- {
259
- // when we're rendering as a button/popup in the corner, we'll pass ?popup=1
260
- // if it's absent, we're rendering results as a full page for sharing
261
- var isPopup = !string.IsNullOrWhiteSpace(context.Request["popup"]);
262
-
263
- // this guid is the MiniProfiler.Id property
264
- Guid id;
265
- if (!Guid.TryParse(context.Request["id"], out id))
266
- return isPopup ? NotFound(context) : NotFound(context, "text/plain", "No Guid id specified on the query string");
267
-
268
- MiniProfiler.Settings.EnsureStorageStrategy();
269
- var profiler = MiniProfiler.Settings.Storage.Load(id);
270
-
271
- var provider = WebRequestProfilerProvider.Settings.UserProvider;
272
- string user = null;
273
- if (provider != null)
274
- {
275
- user = provider.GetUser(context.Request);
276
- }
277
-
278
- MiniProfiler.Settings.Storage.SetViewed(user, id);
279
-
280
- if (profiler == null)
281
- {
282
- return isPopup ? NotFound(context) : NotFound(context, "text/plain", "No MiniProfiler results found with Id=" + id.ToString());
283
- }
284
-
285
- bool needsSave = false;
286
- if (profiler.ClientTimings == null)
287
- {
288
- profiler.ClientTimings = ClientTimings.FromRequest(context.Request);
289
- if (profiler.ClientTimings != null)
290
- {
291
- needsSave = true;
292
- }
293
- }
294
-
295
- if (profiler.HasUserViewed == false)
296
- {
297
- profiler.HasUserViewed = true;
298
- needsSave = true;
299
- }
300
-
301
- if (needsSave) MiniProfiler.Settings.Storage.Save(profiler);
302
-
303
-
304
- var authorize = MiniProfiler.Settings.Results_Authorize;
305
-
306
-
307
- if (authorize != null && !authorize(context.Request))
308
- {
309
- context.Response.ContentType = "application/json";
310
- return "hidden".ToJson();
311
- }
312
-
313
- return isPopup ? ResultsJson(context, profiler) : ResultsFullPage(context, profiler);
314
- }
315
-
316
- private static bool AuthorizeRequest(HttpContext context, bool isList, out string message)
317
- {
318
- message = null;
319
- var authorize = MiniProfiler.Settings.Results_Authorize;
320
- var authorizeList = MiniProfiler.Settings.Results_List_Authorize;
321
-
322
- if (authorize != null && !authorize(context.Request) || (isList && (authorizeList == null || !authorizeList(context.Request))))
323
- {
324
- context.Response.StatusCode = 401;
325
- context.Response.ContentType = "text/plain";
326
- message = "unauthorized";
327
- return false;
328
- }
329
- return true;
330
- }
331
-
332
- private static string ResultsJson(HttpContext context, MiniProfiler profiler)
333
- {
334
- context.Response.ContentType = "application/json";
335
- return MiniProfiler.ToJson(profiler);
336
- }
337
-
338
- private static string ResultsFullPage(HttpContext context, MiniProfiler profiler)
339
- {
340
- context.Response.ContentType = "text/html";
341
-
342
- var template = GetResource("share.html");
343
- return template.Format(new
344
- {
345
- name = profiler.Name,
346
- duration = profiler.DurationMilliseconds.ToString(),
347
- path = VirtualPathUtility.ToAbsolute(MiniProfiler.Settings.RouteBasePath).EnsureTrailingSlash(),
348
- json = MiniProfiler.ToJson(profiler),
349
- includes = RenderIncludes(profiler),
350
- version = MiniProfiler.Settings.Version
351
- });
352
- }
353
-
354
- private static bool bypassLocalLoad = false;
355
- private static string GetResource(string filename)
356
- {
357
- filename = filename.ToLower();
358
- string result;
359
-
360
- #if DEBUG
361
- // attempt to simply load from file system, this lets up modify js without needing to recompile A MILLION TIMES
362
- if (!bypassLocalLoad)
363
- {
364
-
365
- var trace = new System.Diagnostics.StackTrace(true);
366
- var path = System.IO.Path.GetDirectoryName(trace.GetFrames()[0].GetFileName()) + "\\..\\UI\\" + filename;
367
- try
368
- {
369
- return File.ReadAllText(path);
370
- }
371
- catch
372
- {
373
- bypassLocalLoad = true;
374
- }
375
- }
376
-
377
- #endif
378
-
379
- if (!_ResourceCache.TryGetValue(filename, out result))
380
- {
381
- string customTemplatesPath = HttpContext.Current.Server.MapPath(MiniProfiler.Settings.CustomUITemplates);
382
- string customTemplateFile = System.IO.Path.Combine(customTemplatesPath, filename);
383
-
384
- if (System.IO.File.Exists(customTemplateFile))
385
- {
386
- result = File.ReadAllText(customTemplateFile);
387
- }
388
- else
389
- {
390
- using (var stream = typeof(MiniProfilerHandler).Assembly.GetManifestResourceStream("StackExchange.Profiling.UI." + filename))
391
- using (var reader = new StreamReader(stream))
392
- {
393
- result = reader.ReadToEnd();
394
- }
395
- }
396
- _ResourceCache[filename] = result;
397
- }
398
-
399
- return result;
400
- }
401
-
402
- /// <summary>
403
- /// Embedded resource contents keyed by filename.
404
- /// </summary>
405
- private static readonly ConcurrentDictionary<string, string> _ResourceCache = new ConcurrentDictionary<string, string>();
406
-
407
- /// <summary>
408
- /// Helper method that sets a proper 404 response code.
409
- /// </summary>
410
- private static string NotFound(HttpContext context, string contentType = "text/plain", string message = null)
411
- {
412
- context.Response.StatusCode = 404;
413
- context.Response.ContentType = contentType;
414
-
415
- return message;
416
- }
417
-
418
- }
419
- }