miniprofiler 0.1.7.1 → 0.1.7.2

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.
data/UI/includes.less ADDED
@@ -0,0 +1,468 @@
1
+ .box-shadow(@dx, @dy, @radius, @color) {
2
+ -moz-box-shadow: @dx @dy @radius @color;
3
+ -webkit-box-shadow: @dx @dy @radius @color;
4
+ box-shadow: @dx @dy @radius @color;
5
+ }
6
+
7
+ @anchorColor: #0077CC;
8
+ @buttonBorderColor: #888;
9
+ @numberColor: #111;
10
+ @textColor: #555;
11
+ @mutedColor: #aaa;
12
+ @normalFonts: Helvetica, Arial, sans-serif;
13
+ @codeFonts: Consolas, monospace, serif;
14
+ @zindex:2147483640; // near 32bit max 2147483647
15
+
16
+ // do some resets
17
+ .profiler-result, .profiler-queries {
18
+ color:#555;
19
+ line-height:1;
20
+ font-size:12px;
21
+
22
+ pre, code, label, table, tbody, thead, tfoot, tr, th, td {
23
+ margin:0;
24
+ padding:0;
25
+ border:0;
26
+ font-size:100%;
27
+ font:inherit;
28
+ vertical-align:baseline;
29
+ background-color:transparent;
30
+ overflow:visible;
31
+ max-height:none;
32
+ }
33
+ table {
34
+ border-collapse:collapse;
35
+ border-spacing:0;
36
+ }
37
+ a, a:hover {
38
+ cursor:pointer;
39
+ color:@anchorColor;
40
+ }
41
+ a {
42
+ text-decoration:none;
43
+ &:hover {
44
+ text-decoration:underline;
45
+ }
46
+ }
47
+ }
48
+
49
+ // styles shared between popup view and full view
50
+ .profiler-result
51
+ {
52
+
53
+ .profiler-toggle-duration-with-children
54
+ {
55
+ float: right;
56
+ }
57
+
58
+ table.profiler-client-timings
59
+ {
60
+ margin-top: 10px;
61
+ }
62
+
63
+ font-family:@normalFonts;
64
+
65
+ .profiler-label {
66
+ color:@textColor;
67
+ overflow:hidden;
68
+ text-overflow: ellipsis;
69
+ }
70
+
71
+ .profiler-unit {
72
+ color:@mutedColor;
73
+ }
74
+
75
+ .profiler-trivial {
76
+ display:none;
77
+ td, td * {
78
+ color:@mutedColor !important;
79
+ }
80
+ }
81
+
82
+ pre, code, .profiler-number, .profiler-unit {
83
+ font-family:@codeFonts;
84
+ }
85
+
86
+ .profiler-number {
87
+ color:@numberColor;
88
+ }
89
+
90
+ .profiler-info {
91
+ text-align:right;
92
+ .profiler-name {
93
+ float:left;
94
+ }
95
+ .profiler-server-time {
96
+ white-space:nowrap;
97
+ }
98
+ }
99
+
100
+ .profiler-timings {
101
+ th {
102
+ background-color:#fff;
103
+ color:@mutedColor;
104
+ text-align:right;
105
+ }
106
+ th, td {
107
+ white-space:nowrap;
108
+ }
109
+ .profiler-duration-with-children {
110
+ display:none;
111
+ }
112
+ .profiler-duration {
113
+ .profiler-number;
114
+ text-align:right;
115
+ }
116
+ .profiler-indent {
117
+ letter-spacing:4px;
118
+ }
119
+ .profiler-queries-show {
120
+ .profiler-number, .profiler-unit {
121
+ color:@anchorColor;
122
+ }
123
+ }
124
+ .profiler-queries-duration {
125
+ padding-left:6px;
126
+ }
127
+ .profiler-percent-in-sql {
128
+ white-space:nowrap;
129
+ text-align:right;
130
+ }
131
+
132
+ tfoot {
133
+ td {
134
+ padding-top:10px;
135
+ text-align:right;
136
+
137
+ a {
138
+ font-size:95%;
139
+ display:inline-block;
140
+ margin-left:12px;
141
+
142
+ &:first-child {
143
+ float:left;
144
+ margin-left:0px;
145
+ }
146
+ }
147
+ }
148
+ }
149
+ }
150
+
151
+ .profiler-queries {
152
+ font-family:@normalFonts;
153
+
154
+ .profiler-stack-trace {
155
+ margin-bottom:15px;
156
+ }
157
+ pre {
158
+ font-family:@codeFonts;
159
+ white-space:pre-wrap;
160
+ }
161
+
162
+ th {
163
+ background-color:#fff;
164
+ border-bottom:1px solid #555;
165
+ font-weight:bold;
166
+ padding:15px;
167
+ white-space:nowrap;
168
+ }
169
+
170
+ td {
171
+ padding:15px;
172
+ text-align:left;
173
+ background-color:#fff;
174
+
175
+ &:last-child {
176
+ padding-right:25px; // compensate for scrollbars
177
+ }
178
+ }
179
+
180
+ .profiler-odd td {
181
+ background-color:#e5e5e5;
182
+ }
183
+
184
+ .profiler-since-start, .profiler-duration {
185
+ text-align:right;
186
+ }
187
+
188
+ .profiler-info div {
189
+ text-align:right;
190
+ margin-bottom:5px;
191
+ }
192
+
193
+ .profiler-gap-info, .profiler-gap-info td { background-color: #ccc;}
194
+ .profiler-gap-info {
195
+ .profiler-unit {color: #777;}
196
+ .profiler-info {text-align: right}
197
+ &.profiler-trivial-gaps {display: none}
198
+ }
199
+
200
+ .profiler-trivial-gap-container { text-align: center;}
201
+
202
+ // prettify colors
203
+ .str{color:maroon}
204
+ .kwd{color:#00008b}
205
+ .com{color:gray}
206
+ .typ{color:#2b91af}
207
+ .lit{color:maroon}
208
+ .pun{color:#000}
209
+ .pln{color:#000}
210
+ .tag{color:maroon}
211
+ .atn{color:red}
212
+ .atv{color:blue}
213
+ .dec{color:purple}
214
+ }
215
+
216
+ .profiler-warning, .profiler-warning *, .profiler-warning .profiler-queries-show, .profiler-warning .profiler-queries-show .profiler-unit { // i'm no good at css
217
+ color:#f00;
218
+ &:hover {
219
+ color:#f00;
220
+ }
221
+ }
222
+
223
+ .profiler-nuclear {
224
+ .profiler-warning;
225
+ font-weight:bold;
226
+ padding-right:2px;
227
+ }
228
+ }
229
+
230
+ // ajaxed-in results will be appended to this
231
+ .profiler-results
232
+ {
233
+ z-index:@zindex + 3;
234
+ position:fixed;
235
+ top:0px;
236
+
237
+ @radius:10px;
238
+
239
+ &.profiler-left {
240
+ left:0px;
241
+
242
+ &.profiler-no-controls .profiler-result:last-child .profiler-button, .profiler-controls {
243
+ -webkit-border-bottom-right-radius: @radius;
244
+ -moz-border-radius-bottomright: @radius;
245
+ border-bottom-right-radius: @radius;
246
+ }
247
+
248
+ .profiler-button, .profiler-controls {
249
+ border-right: 1px solid @buttonBorderColor;
250
+ }
251
+ }
252
+
253
+ &.profiler-right {
254
+ right:0px;
255
+
256
+ &.profiler-no-controls .profiler-result:last-child .profiler-button, .profiler-controls {
257
+ -webkit-border-bottom-left-radius: @radius;
258
+ -moz-border-radius-bottomleft: @radius;
259
+ border-bottom-left-radius: @radius;
260
+ }
261
+
262
+ .profiler-button, .profiler-controls {
263
+ border-left: 1px solid @buttonBorderColor;
264
+ }
265
+ }
266
+
267
+ .profiler-button, .profiler-controls {
268
+ display:none;
269
+ z-index:@zindex;
270
+ border-bottom: 1px solid @buttonBorderColor;
271
+ background-color:#fff;
272
+ padding: 4px 7px;
273
+ text-align:right;
274
+ cursor:pointer;
275
+
276
+ &.profiler-button-active {
277
+ background-color:maroon;
278
+
279
+ .profiler-number, .profiler-nuclear {
280
+ color:#fff;
281
+ font-weight:bold;
282
+ }
283
+ .profiler-unit {
284
+ color:#fff;
285
+ font-weight:normal;
286
+ }
287
+ }
288
+ }
289
+
290
+ .profiler-controls {
291
+ display: block;
292
+ font-size:12px;
293
+ font-family: @codeFonts;
294
+ cursor:default;
295
+ text-align: center;
296
+
297
+ span {
298
+ border-right: 1px solid @mutedColor;
299
+ padding-right: 5px;
300
+ margin-right: 5px;
301
+ cursor:pointer;
302
+ }
303
+
304
+ span:last-child {
305
+ border-right: none;
306
+ }
307
+ }
308
+
309
+ .profiler-popup {
310
+ display:none;
311
+ z-index:@zindex + 1;
312
+ position:absolute;
313
+ background-color:#fff;
314
+ border: 1px solid #aaa;
315
+ padding:5px 10px;
316
+ text-align:left;
317
+ line-height:18px;
318
+ overflow:auto;
319
+
320
+ .box-shadow(0px, 1px, 15px, #555);
321
+
322
+ .profiler-info {
323
+ margin-bottom:3px;
324
+ padding-bottom:2px;
325
+ border-bottom:1px solid #ddd;
326
+
327
+ .profiler-name {
328
+ font-size:110%;
329
+ font-weight:bold;
330
+ .profiler-overall-duration {
331
+ display:none;
332
+ }
333
+ }
334
+ .profiler-server-time {
335
+ font-size:95%;
336
+ }
337
+ }
338
+
339
+ .profiler-timings {
340
+
341
+ th, td {
342
+ padding-left:6px;
343
+ padding-right:6px;
344
+ }
345
+
346
+ th {
347
+ font-size:95%;
348
+ padding-bottom:3px;
349
+ }
350
+
351
+ .profiler-label {
352
+ max-width:275px;
353
+ }
354
+ }
355
+ }
356
+
357
+ .profiler-queries {
358
+ display:none;
359
+ z-index:@zindex + 3;
360
+ position:absolute;
361
+ overflow-y:auto;
362
+ overflow-x:hidden;
363
+ background-color:#fff;
364
+
365
+ th {
366
+ font-size:17px;
367
+ }
368
+ }
369
+
370
+ &.profiler-min .profiler-result {
371
+ display: none;
372
+ }
373
+
374
+ &.profiler-min .profiler-controls span {
375
+ display: none;
376
+ }
377
+
378
+ &.profiler-min .profiler-controls .profiler-min-max {
379
+ border-right: none;
380
+ padding: 0px;
381
+ margin: 0px;
382
+ }
383
+ }
384
+
385
+ // popup results' queries will be displayed in front of this
386
+ .profiler-queries-bg {
387
+ z-index:@zindex + 2;
388
+ display:none;
389
+ background:#000;
390
+ opacity:0.7;
391
+ position:absolute;
392
+ top:0px;
393
+ left:0px;
394
+ min-width:100%;
395
+ }
396
+
397
+ // used when viewing a shared, full page result
398
+ .profiler-result-full {
399
+ .profiler-result {
400
+
401
+ width:950px;
402
+ margin:30px auto;
403
+
404
+ .profiler-button {
405
+ display:none;
406
+ }
407
+
408
+ .profiler-popup {
409
+
410
+ .profiler-info {
411
+ font-size: 25px;
412
+ border-bottom:1px solid @mutedColor;
413
+ padding-bottom:3px;
414
+ margin-bottom:25px;
415
+
416
+ .profiler-overall-duration {
417
+ padding-right:20px;
418
+ font-size:80%;
419
+ color:#888;
420
+ }
421
+ }
422
+
423
+ .profiler-timings {
424
+ td, th {
425
+ padding-left:8px;
426
+ padding-right:8px;
427
+ }
428
+ th {
429
+ padding-bottom:7px;
430
+ }
431
+ td {
432
+ font-size:14px;
433
+ padding-bottom:4px;
434
+
435
+ &:first-child {
436
+ padding-left:10px;
437
+ }
438
+ }
439
+
440
+ .profiler-label {
441
+ max-width:550px;
442
+ }
443
+ }
444
+ }
445
+
446
+ .profiler-queries {
447
+ margin:25px 0;
448
+ table {
449
+ width:100%;
450
+ }
451
+ th {
452
+ font-size:16px;
453
+ color:#555;
454
+ line-height:20px;
455
+ }
456
+
457
+ td {
458
+ padding:15px 10px;
459
+ text-align:left;
460
+ }
461
+
462
+ .profiler-info div {
463
+ text-align:right;
464
+ margin-bottom:5px;
465
+ }
466
+ }
467
+ }
468
+ }
data/UI/includes.tmpl ADDED
@@ -0,0 +1,195 @@
1
+ <script id="profilerTemplate" type="text/x-jquery-tmpl">
2
+
3
+ <div class="profiler-result">
4
+
5
+ <div class="profiler-button {{if HasDuplicateSqlTimings}}profiler-warning{{/if}}">
6
+ {{if HasDuplicateSqlTimings}}<span class="profiler-nuclear">!</span>{{/if}}
7
+ <span class="profiler-number">
8
+ ${MiniProfiler.formatDuration(DurationMilliseconds)} <span class="profiler-unit">ms</span>
9
+ </span>
10
+ </div>
11
+
12
+ <div class="profiler-popup">
13
+ <div class="profiler-info">
14
+ <span class="profiler-name">
15
+ ${Name} <span class="profiler-overall-duration">(${MiniProfiler.formatDuration(DurationMilliseconds)} ms)</span>
16
+ </span>
17
+ <span class="profiler-server-time">${MachineName} on ${MiniProfiler.renderDate(Started)}</span>
18
+ </div>
19
+ <div class="profiler-output">
20
+ <table class="profiler-timings">
21
+ <thead>
22
+ <tr>
23
+ <th></th>
24
+ <th>duration (ms)</th>
25
+ <th class="profiler-duration-with-children">with children (ms)</th>
26
+ <th class="time-from-start">from start (ms)</th>
27
+ {{if HasSqlTimings}}
28
+ <th colspan="2">query time (ms)</th>
29
+ {{/if}}
30
+ </tr>
31
+ </thead>
32
+ <tbody>
33
+ {{tmpl(Root) "#timingTemplate"}}
34
+ </tbody>
35
+ <tfoot>
36
+ <tr>
37
+ <td colspan="3">
38
+ {{if !ClientTimings}}
39
+ {{tmpl "#linksTemplate"}}
40
+ {{/if}}
41
+ <a class="profiler-toggle-duration-with-children" title="toggles column with aggregate child durations">show time with children</a>
42
+ </td>
43
+ {{if HasSqlTimings}}
44
+ <td colspan="2" class="profiler-number profiler-percent-in-sql" title="${MiniProfiler.getSqlTimingsCount(Root)} queries spent ${MiniProfiler.formatDuration(DurationMillisecondsInSql)} ms of total request time">
45
+ ${MiniProfiler.formatDuration(DurationMillisecondsInSql / DurationMilliseconds * 100)}
46
+ <span class="profiler-unit">% in sql</span>
47
+ </td>
48
+ {{/if}}
49
+ </tr>
50
+ </tfoot>
51
+ </table>
52
+ {{if ClientTimings}}
53
+ <table class="profiler-timings profiler-client-timings">
54
+ <thead>
55
+ <tr>
56
+ <th>client event</th>
57
+ <th>duration (ms)</th>
58
+ <th>from start (ms)</th>
59
+ </tr>
60
+ </thead>
61
+ <tbody>
62
+ {{each MiniProfiler.getClientTimings(ClientTimings)}}
63
+ <tr class="{{if $value.isTrivial }}profiler-trivial{{/if}}">
64
+ <td class="profiler-label">${$value.name}</td>
65
+ <td class="profiler-duration">
66
+ {{if $value.duration >= 0}}
67
+ <span class="profiler-unit"></span>${MiniProfiler.formatDuration($value.duration)}
68
+ {{/if}}
69
+ </td>
70
+ <td class="profiler-duration time-from-start">
71
+ <span class="profiler-unit">+</span>${MiniProfiler.formatDuration($value.start)}
72
+ </td>
73
+ </tr>
74
+ {{/each}}
75
+ </tbody>
76
+ <tfoot>
77
+ <td colspan="3">
78
+ {{tmpl "#linksTemplate"}}
79
+ </td>
80
+ </tfoot>
81
+ </table>
82
+ {{/if}}
83
+ </div>
84
+ </div>
85
+
86
+ {{if HasSqlTimings}}
87
+ <div class="profiler-queries">
88
+ <table>
89
+ <thead>
90
+ <tr>
91
+ <th style="text-align:right">step<br />time from start<br />query type<br />duration</th>
92
+ <th style="text-align:left">call stack<br />query</th>
93
+ </tr>
94
+ </thead>
95
+ <tbody>
96
+ {{each(i, s) MiniProfiler.getSqlTimings(Root)}}
97
+ {{tmpl({ g:s.prevGap }) "#sqlGapTemplate"}}
98
+ {{tmpl({ i:i, s:s }) "#sqlTimingTemplate"}}
99
+ {{if s.nextGap}}
100
+ {{tmpl({ g:s.nextGap }) "#sqlGapTemplate"}}
101
+ {{/if}}
102
+ {{/each}}
103
+ </tbody>
104
+ </table>
105
+ <p class="profiler-trivial-gap-container">
106
+ <a class="profiler-toggle-trivial-gaps" href="#">show trivial gaps</a>
107
+ </p>
108
+ </div>
109
+ {{/if}}
110
+
111
+ </div>
112
+
113
+ </script>
114
+
115
+ <script id="linksTemplate" type="text/x-jquery-tmpl">
116
+ <a href="${MiniProfiler.shareUrl(Id)}" class="profiler-share-profiler-results" target="_blank">share</a>
117
+ {{if HasTrivialTimings}}
118
+ <a class="profiler-toggle-trivial" data-show-on-load="${HasAllTrivialTimings}" title="toggles any rows with &lt; ${TrivialDurationThresholdMilliseconds} ms">
119
+ show trivial
120
+ </a>
121
+ {{/if}}
122
+ </script>
123
+
124
+ <script id="timingTemplate" type="text/x-jquery-tmpl">
125
+
126
+ <tr class="{{if IsTrivial }}profiler-trivial{{/if}}" data-timing-id="${Id}">
127
+ <td class="profiler-label" title="{{if Name && Name.length > 45 }}${Name}{{/if}}">
128
+ <span class="profiler-indent">${MiniProfiler.renderIndent(Depth)}</span> ${Name.slice(0,45)}{{if Name && Name.length > 45 }}...{{/if}}
129
+ </td>
130
+ <td class="profiler-duration" title="duration of this step without any children's durations">
131
+ ${MiniProfiler.formatDuration(DurationWithoutChildrenMilliseconds)}
132
+ </td>
133
+ <td class="profiler-duration profiler-duration-with-children" title="duration of this step and its children">
134
+ ${MiniProfiler.formatDuration(DurationMilliseconds)}
135
+ </td>
136
+ <td class="profiler-duration time-from-start" title="time elapsed since profiling started">
137
+ <span class="profiler-unit">+</span>${MiniProfiler.formatDuration(StartMilliseconds)}
138
+ </td>
139
+
140
+ {{if HasSqlTimings}}
141
+ <td class="profiler-duration {{if HasDuplicateSqlTimings}}profiler-warning{{/if}}" title="{{if HasDuplicateSqlTimings}}duplicate queries detected - {{/if}}${ExecutedReaders} reader, ${ExecutedScalars} scalar, ${ExecutedNonQueries} non-query statements executed">
142
+ <a class="profiler-queries-show">
143
+ {{if HasDuplicateSqlTimings}}<span class="profiler-nuclear">!</span>{{/if}}
144
+ ${SqlTimings.length} <span class="profiler-unit">sql</span>
145
+ </a>
146
+ </td>
147
+ <td class="profiler-duration" title="aggregate duration of all queries in this step (excludes children)">
148
+ ${MiniProfiler.formatDuration(SqlTimingsDurationMilliseconds)}
149
+ </td>
150
+ {{/if}}
151
+
152
+ </tr>
153
+
154
+ {{if HasChildren}}
155
+ {{each Children}}
156
+ {{tmpl($value) "#timingTemplate"}}
157
+ {{/each}}
158
+ {{/if}}
159
+
160
+ </script>
161
+
162
+ <script id="sqlTimingTemplate" type="text/x-jquery-tmpl">
163
+
164
+ <tr class="{{if i % 2 == 1}}profiler-odd{{/if}}" data-timing-id="${s.ParentTimingId}">
165
+ <td class="profiler-info">
166
+ <div>${s.ParentTimingName}</div>
167
+ <div class="profiler-number"><span class="profiler-unit">T+</span>${MiniProfiler.formatDuration(s.StartMilliseconds)} <span class="profiler-unit">ms</span></div>
168
+ <div>
169
+ {{if s.IsDuplicate}}<span class="profiler-warning">DUPLICATE</span>{{/if}}
170
+ ${MiniProfiler.renderExecuteType(s.ExecuteType)}
171
+ </div>
172
+ <div title="{{if s.ExecuteType == 3}}first result fetched: ${s.FirstFetchDurationMilliseconds}ms{{/if}}">${MiniProfiler.formatDuration(s.DurationMilliseconds)} <span class="profiler-unit">ms</span></div>
173
+ </td>
174
+ <td>
175
+ <div class="query">
176
+ <pre class="profiler-stack-trace">${s.StackTraceSnippet}</pre>
177
+ <pre class="prettyprint lang-sql"><code>${s.FormattedCommandString} </code></pre>
178
+ </div>
179
+ </td>
180
+ </tr>
181
+
182
+ </script>
183
+
184
+ <script id="sqlGapTemplate" type="text/x-jquery-tmpl">
185
+
186
+ <tr class="profiler-gap-info{{if g.duration < 4}} profiler-trivial-gaps{{/if}}">
187
+ <td class="profiler-info">
188
+ ${g.duration} <span class="profiler-unit">ms</span>
189
+ </td>
190
+ <td class="query">
191
+ <div>${g.topReason.name} &mdash; ${g.topReason.duration.toFixed(2)} <span class="profiler-unit">ms</span></div>
192
+ </td>
193
+ </tr>
194
+
195
+ </script>