forked from MiniProfiler/miniprofiler.github.com
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
408 lines (330 loc) · 19 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset='utf-8' />
<meta http-equiv="X-UA-Compatible" content="chrome=1" />
<meta name="description" content="MiniProfiler: A simple but effective mini-profiler for .NET and Ruby" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.0/css/bootstrap.min.css">
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.0/css/bootstrap-theme.min.css">
<link rel="stylesheet" type="text/css" media="screen" href="stylesheets/stylesheet.css">
<title>MiniProfiler: A simple but effective mini-profiler for .NET and Ruby</title>
</head>
<body>
<!-- HEADER -->
<div id="header_wrap" class="container">
<div class="row">
<header class="col-md-8 col-md-offset-2">
<a class="forkme_banner" href="https://github.com/MiniProfiler">Fork Me on GitHub</a>
<a class="forkme_banner" href="https://github.com/MiniProfiler/miniprofiler.github.com">Fork This Site</a>
<h1 id="project_title">MiniProfiler</h1>
<h2 id="project_tagline">A simple but effective mini-profiler for .NET and Ruby.</h2>
</header>
</div>
</div>
<!-- MAIN CONTENT -->
<div id="main_content_wrap">
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<p>A simple but effective mini-profiler for <a href="https://github.com/MiniProfiler/dotnet">.NET</a>, <a href="https://github.com/MiniProfiler/rack-mini-profiler">Ruby</a>, <a href="https://github.com/MiniProfiler/go">Go</a> and <a href="https://github.com/MiniProfiler/node">Node.js</a>.</p>
<h3>Where do I get support?</h3>
<p>Bugs, Feature Requests, Discussion and KB live at <a href="http://community.miniprofiler.com">community.miniprofiler.com</a> or on <a href="http://stackoverflow.com/questions/tagged/mini-profiler">Stack Overflow</a>. View <a href="https://github.com/MiniProfiler/dotnet/releases">Releases</a> and feel free to submit Pull Requests and Issues on GitHub.</p>
<h3>Where is the current Ruby documentation?</h3>
See <a href="https://github.com/MiniProfiler/rack-mini-profiler">Github</a> and <a href="http://samsaffron.com/archive/2012/07/12/miniprofiler-ruby-edition">Sams blog post</a>.
<h3>What does it profile?</h3>
<p>MiniProfiler does <strong>not</strong> attach itself to every single method call; that would be too invasive and wouldn't focus on the biggest performance issues. Instead, it provides:</p>
<ul>
<li>An ADO.NET profiler, capable of profiling calls on raw ADO.NET (SQL Server, Oracle, etc), LINQ-to-SQL, EF (including <em>Code First</em>), <a href="http://www.mindscapehq.com/blog/index.php/2011/07/28/using-the-asp-net-mvc-mini-profiler-with-lightspeed/">Lightspeed</a> and a range of other data access scenarios</li>
<li>A pragmatic <code>Step</code> instrumentation that you can add to code you want to explicitly profile</li>
</ul>
<p>Simple. Fast. Pragmatic. Useful.</p>
<h2>Getting Started on .Net:</h2>
<p>Hook up your application with at least one of the following packages are available on nuget:</p>
<ul>
<li><code><a href="https://www.nuget.org/packages/MiniProfiler/">MiniProfiler</a></code> - The core. Needed for any profiling (all of the packages below list this as a dependency)</li>
<li><code><a href="https://www.nuget.org/packages/MiniProfiler.EF6/">MiniProfiler.EF6</a></code> - For profiling Entity Framework version 6+</li>
<li><code><a href="https://www.nuget.org/packages/MiniProfiler.EF5/">MiniProfiler.EF5</a></code> - For profiling Entity Framework versions 4 and 5</li>
<li><strike><code><a href="https://www.nuget.org/packages/MiniProfiler.EF/">MiniProfiler.EF</a></code></strike> - obsolete package. Please use one of the other EF packages above instead.</li>
<li><code><a href="https://www.nuget.org/packages/MiniProfiler.Mvc3/">MiniProfiler.MVC3</a></code> - Profile MVC 3 websites</li>
<li><code><a href="https://www.nuget.org/packages/MiniProfiler.Mvc4/">MiniProfiler.MVC4</a></code> - Profile MVC 4 and 5 websites</li>
<li><code><a href="https://www.nuget.org/packages/MiniProfiler.Raven/">MiniProfiler.Raven</a></code> - Profile <a href="http://ravendb.net">RavenDb</a> connections</li>
<li><code><a href="https://www.nuget.org/packages/MiniProfiler.WCF">MiniProfiler.WCF</a></code> - Profile WCF</li>
<li><code><a href="https://www.nuget.org/packages/MiniProfiler.MongoDb">MiniProfiler.MongoDb</a></code> - Profile MongoDb</li>
</ul>
<pre style="background-color: #202020;border: 4px solid silver;border-radius: 5px;-moz-border-radius: 5px;-webkit-border-radius: 5px;box-shadow: 2px 2px 3px #6e6e6e;color: #E2E2E2;display: block;font: 1.5em 'andale mono', 'lucidaconsole', monospace;line-height: 1.5em;overflow: auto;padding: 15px;">PM> Install-Package MiniProfiler</pre>
<p>Write out our css and javascript includes just before closing the body tag:</p>
<pre><code>@using StackExchange.Profiling;
<head>
..
</head>
<body>
...
@MiniProfiler.RenderIncludes()
</body>
</code></pre>
<p>For requests that aren't being profiled, nothing will be written.</p>
<ul>
<li>Decide when you want to profile; perhaps for local requests, perhaps for special users (developers, admins, test team, whatever).</li>
</ul>
<p>The sample project starts profiling in <code>Global.asax.cs</code> <code>Application_BeginRequest</code>:</p>
<pre><code>using StackExchange.Profiling;
...
protected void Application_BeginRequest()
{
if (Request.IsLocal)
{
MiniProfiler.Start();
}
}
</code></pre>
<p>For the code you want to profile, use (regardless of whether the <code>profiler</code> is <code>null</code> or not):</p>
<pre><code>using StackExchange.Profiling;
...
var profiler = MiniProfiler.Current; // it's ok if this is null
using (profiler.Step("Set page title"))
{
ViewBag.Title = "Home Page";
}
using (profiler.Step("Doing complex stuff"))
{
using (profiler.Step("Step A"))
{ // something more interesting here
Thread.Sleep(100);
}
using (profiler.Step("Step B"))
{ // and here
Thread.Sleep(250);
}
}
</code></pre>
<p>You can make this as granular or high-level as you like; passing a <code>MiniProfiler</code> in as an optional argument (defaulting to <code>null</code>) to downstream methods works well.</p>
<p>Stop the profiler; the sample project does this in its <code>Global.asax.cs</code>:</p>
<pre><code>protected void Application_EndRequest()
{
MiniProfiler.Stop();
}
</code></pre>
<p>If all goes well, you'll see something like this:</p>
<div class="row"><div class="col-md-8 col-md-offset-2">
<img src="http://i.imgur.com/PsjLY.png" alt="demo" class="img-thumbnail">
</div></div>
<h3>Profiler Security</h3>
<h4>Accessing last profiled request</h4>
<p>Profiling information can be viewed for the last profiled request by navigating to</p>
<code>~/mini-profiler-resources/results</code>
<p>This resource is <strong>accessible to all by default</strong>, so you should assign a predicate delegate to <code>MiniProfiler.Settings.Results_Authorize</code> to restrict access. A good place to do this is in <code>Global.asax.cs</code>:</p>
<pre><code>protected void Application_Start(object sender, EventArgs e)
{
MiniProfiler.Settings.Results_Authorize = IsUserAllowedToSeeMiniProfilerUI;
}
private bool IsUserAllowedToSeeMiniProfilerUI(HttpRequest httpRequest)
{
// Implement your own logic for who
// should be able to access ~/mini-profiler-resources/results
var principal = httpRequest.RequestContext.HttpContext.User;
return principal.IsInRole("Developer");
}
</code></pre>
<h4>Accessing last 100 profiled requests</h4>
<p>Similarly, profiling information for the last 100 profiled requests can be viewed at</p>
<code>~/mini-profiler-resources/results-index</code>
<p>Access to this resource <strong>is disabled by default</strong> but this can be changed by assigning a predicate delegate to
<code>MiniProfiler.Settings.Results_List_Authorize</code>:
</p>
<pre><code>protected void Application_Start(object sender, EventArgs e)
{
MiniProfiler.Settings.Results_List_Authorize = IsUserAllowedToSeeMiniProfilerUI;
}
private bool IsUserAllowedToSeeMiniProfilerUI(HttpRequest httpRequest)
{
// Implement your own logic for who
// should be able to access ~/mini-profiler-resources/results-index
var principal = httpRequest.RequestContext.HttpContext.User;
return principal.IsInRole("Developer");
}
</code></pre>
<p>In using these profiling resources, it is possible to profile requests for <em>any/all users</em> but restrict access to viewing the results only to certain users.</p>
<h3>Database profiling</h3>
<p>The profiler includes powerful and comprehensive database profiling capabilities. To enable wrap your database connection with a profiling connection. </p>
<p>The built in database profiler supports any kind of DbConnection. It also supports Entity Framework and Linq-2-SQL.</p>
<h4>Usage: </h4>
<p>Use a factory to return your connection: </p>
<ul class="nav nav-tabs">
<li class="active"><a href="#DbConnection" data-toggle="tab">DbConnection</a></li>
<li><a href="#L2S" data-toggle="tab">Linq-to-Sql</a></li>
<li><a href="#EF6" data-toggle="tab">EF 6+</a></li>
<li><a href="#EF5" data-toggle="tab">EF 4 and 5</a></li>
<li><a href="#RavenDb" data-toggle="tab">RavenDb</a></li>
<li><a href="#MongoDB" data-toggle="tab">Mongo DB</a></li>
</ul>
<!-- Tab panes -->
<div class="tab-content connections">
<div class="tab-pane active" id="DbConnection">
<pre><code>public static DbConnection GetOpenConnection()
{
var cnn = CreateRealConnection(); // A SqlConnection, SqliteConnection ... or whatever
// wrap the connection with a profiling connection that tracks timings
return new StackExchange.Profiling.Data.ProfiledDbConnection(cnn, MiniProfiler.Current);
}
</code></pre>
</div>
<div class="tab-pane" id="L2S">
<pre><code>partial class DBContext
{
public static DBContext Get()
{
var conn = new StackExchange.Profiling.Data.ProfiledDbConnection(GetConnection(), MiniProfiler.Current);
return new DBContext(conn);
}
}
</code></pre>
</div>
<div class="tab-pane" id="EF6">
<p>Install the <a href="https://www.nuget.org/packages/MiniProfiler.EF6/">MiniProfiler.EF6</a> nuget and use one line of code to initialize for all connections in the app:</p>
<pre><code>using StackExchange.Profiling;
...
protected void Application_Start()
{
MiniProfilerEF6.Initialize();
}
</code></pre>
</div>
<div class="tab-pane" id="EF5">
<p>Install the <a href="https://www.nuget.org/packages/MiniProfiler.EF5/">MiniProfiler.EF5 nuget</a> and use the following code to instantiate your connection:</p>
<pre><code>
using StackExchange.Profiling.Data;
...
public static MyModel Get()
{
var conn = new EFProfiledDbConnection(GetConnection(), MiniProfiler.Current);
return ObjectContextUtils.CreateObjectContext<MyModel>(conn);
}
</code></pre>
<p><strong>Entity Framework - Code First</strong></p>
<p>MVC Mini Profiler can be hooked in to an EF code first project. To do so: </p>
<p>Install the Nuget MiniProfiler.EF5 package: </p>
<p>Run: <code>MiniProfilerEF.Initialize(); // in Application_Start</code></p>
<p>That's it ... you are done!</p>
<p>Note: EF Code First will store table metadata in a table called: !EdmMetadata. This metadata uses the provider as part of the entity key. If you initialized your provider as a non-profiled provider, you will have to re-build this metadata. Deleting all the rows from !EdmMetadata may do the trick, alternatively some smarter providers are able to handle this transparently. </p>
<p><strong>EF 4.1 Update 1</strong></p>
<p>Note, that EF 4.1 Update 1 (the version currently on NuGet) has a breaking change which throws the following error when specifying a connection string:</p>
<p><code>The given assembly name or codebase was invalid. (Exception from HRESULT: 0x80131047)</code></p>
<p>MiniProfiler attempts to resolve this issue by detecting the version of Entity Framework that it is running against. If this doesn't work (due to security exceptions), force the hack to be applied by replacing the <code>Initialize()</code> call with: </p>
<p><code>MiniProfilerEF.Initialize_EF42(); // in Application_Start</code></p>
<p>However, this is currently unable to profile SqlCE or Oracle databases. </p>
<p>To work around this an additional parameter has been added to the <code>Initialize</code> call:</p>
<ul>
<li>If you specify connection strings explicitly in your <code>web.config</code>, use <code>MiniProfilerEF.Initialize();</code>. This will not profile SqlCE or Oracle databases</li>
<li>If you don't specify connection strings (automatically inferred) and want SqlCE support, use <code>MiniProfilerEF.Initialize(false);</code>.</li>
</ul>
<p>Note, this should be a temporary solution until EF 4.2 is widely available.</p>
</div>
<div class="tab-pane" id="RavenDb">
<p>Include the <a href="https://www.nuget.org/packages/MiniProfiler.Raven">MiniProfiler.Raven nuget package</a> and call <code>MiniProfilerRaven.InitializeFor(store)</code> when you initialize your Raven <code>DocumentStore</code> (please note that <code>EmbeddableDocumentStore</code>
is not supported).</p>
<pre><code>var store = new DocumentStore();
store.Initialize();
// Initialize MiniProfiler
MiniProfilerRaven.InitializeFor(store);</code></pre>
</div>
<div class="tab-pane" id="MongoDB">
<p><strong>Profiling MongoDB</strong></p>
<p>Include the <a href="https://www.nuget.org/packages/MiniProfiler.MongoDb">MiniProfiler.MongoDB nuget package</a> and use this pattern to wrap your existing connections:</p>
<pre><code>using StackExchange.Profiling.MongoDB;
...
public MongoClient Client { get; }
private MongoServer _server;
public MongoServer Server
{
get
{
if (_server == null)
{
// Client property can return plain MongoClient object
_server = new ProfiledMongoServer(Client.GetServer());
}
return _server;
}
}</code></pre>
<p>After that you just have to get the references to your databases, collections from this <code>ProfiledMongoServer</code> property and that's it.</p>
<p><strong>Using MongoDB storage for profiler data</strong></p>
<p>To use the storage simply create an instance of <code>MongoDbStorage</code> type and assign it to <code>MiniProfiler.Settings.Storage</code> property:</p>
<pre><code>MiniProfiler.Settings.Storage = new MongoDbStorage("mongodb://localhost");</code></pre>
</div>
</div>
<h2>Various features</h2>
<h3>(N+1) and duplicate query detection===</h3>
<p>The profiler is able to detect and highlight areas where you are executing the same query multiple times with different parameters. This allows you to quickly find queries you may be able to batch.</p>
<div class="row"><div class="col-md-8 col-md-offset-2">
<img src="http://i.stack.imgur.com/0P0pr.png" alt="N+1" class="img-thumbnail">
</div></div>
<h3>What about AJAX?</h3>
<p>The profiler is also able to log all ajax calls: </p>
<div class="row"><div class="col-md-8 col-md-offset-2">
<img src="http://i.stack.imgur.com/3k2NN.png" alt="ajax calls" class="img-thumbnail">
</div></div>
<p>You will get one profile timing per ajax call. </p>
<h3>Abandoning a profiler session</h3>
<p>Often at the beginning of a session you may not know if a user should or should not be allowed to profile, a common pattern for dealing with such issues is:</p>
<pre><code>protected void Application_BeginRequest()
{
MvcMiniProfiler.MiniProfiler.Start();
}
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
if(!CurrentUserIsAllowedToSeeProfiler())
{
MvcMiniProfiler.MiniProfiler.Stop(discardResults: true);
}
}
</code></pre>
<p>See the <a href="https://github.com/MiniProfiler/dotnet/blob/52e44229ca4abae57e40cbfbf1dd38a6f9c1477b/Sample.Mvc/Global.asax.cs#L112"><code>Global.asax.cs</code></a> file in the Sample.MVC project for a demonstration of more config options that can be used.</p>
<h2>Basic Troubleshooting</h2>
<h3>MiniProfiler isn't showing</h3>
<ul>
<li>Run through the Getting Started steps again and double-check</li>
<li>If your <code>web.config</code> has the setting <code>runAllManagedModulesForAllRequests=false</code> then add the following to your <code>web.config</code> too:</li>
</ul>
<pre><code><system.webServer>
...
<handlers>
<add name="MiniProfiler" path="mini-profiler-resources/*" verb="*" type="System.Web.Routing.UrlRoutingModule" resourceType="Unspecified" preCondition="integratedMode" />
</handlers>
</system.webServer>
</code></pre>
<h2>Where is MiniProfiler used?</h2>
<p>MiniProfiler was designed by the team at <a href="http://stackoverflow.com">Stack Overflow</a>. It is in production use there and on the <a href="http://stackexchange.com">Stack Exchange</a> family of sites. </p>
<p>Also used at:</p>
<ul>
<li><a href="http://acturent.com">acturent.com</a></li>
<li><a href="http://plane9.com">plane9.com</a></li>
<li><a href="http://www.godaddy.com">GoDaddy.com</a></li>
</ul>
<p>(if you are using this in production please let us know and we will add you to the list)</p>
<h3>Frequently Asked Questions</h3>
<p>If you have other questions, please ask them on <a href="http://stackoverflow.com/questions/tagged/mini-profiler">Stack Overflow</a> or <a href="http://community.miniprofiler.com">community.miniprofiler.com</a>.</p>
</div>
</div>
</div>
</div> <!-- main content -->
<!-- FOOTER -->
<div id="footer_wrap" class="container">
<div class="row">
<footer class="col-md-8 col-md-offset-2">
<p class="copyright">MiniProfiler maintained by <a href="https://github.com/orgs/MiniProfiler/people">The Team</a></p>
</footer>
</div>
</div>
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.1.0.js"></script>
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.1.0/js/bootstrap.min.js"></script>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-45877749-2', 'miniprofiler.com');
ga('send', 'pageview');
</script>
</body>
</html>