rack-mini-profiler 0.1.3 → 0.1.8
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.
- data/CHANGELOG +15 -0
- data/README.md +18 -0
- data/lib/html/includes.css +75 -1
- data/lib/html/includes.js +14 -2
- data/lib/html/includes.less +1 -1
- data/lib/html/profile_handler.js +9 -9
- data/lib/mini_profiler/client_timer_struct.rb +38 -3
- data/lib/mini_profiler/config.rb +2 -1
- data/lib/mini_profiler/context.rb +10 -0
- data/lib/mini_profiler/page_timer_struct.rb +7 -3
- data/lib/mini_profiler/profiler.rb +161 -144
- data/lib/mini_profiler/profiling_methods.rb +73 -0
- data/lib/mini_profiler/request_timer_struct.rb +39 -8
- data/lib/mini_profiler/sql_timer_struct.rb +13 -2
- data/lib/mini_profiler/storage/file_store.rb +8 -7
- data/lib/mini_profiler/storage/memory_store.rb +0 -4
- data/lib/mini_profiler_rails/railtie.rb +41 -2
- data/lib/patches/sql_patches.rb +154 -34
- data/lib/rack-mini-profiler.rb +3 -3
- data/rack-mini-profiler.gemspec +3 -4
- metadata +6 -6
- data/lib/html/MiniProfilerHandler.cs +0 -419
- data/lib/mini_profiler/body_add_proxy.rb +0 -45
    
        data/CHANGELOG
    CHANGED
    
    | @@ -15,3 +15,18 @@ | |
| 15 15 | 
             
            	* Added option to display full backtraces pp=full-backtrace
         | 
| 16 16 | 
             
            	* Cleaned up railties, got rid of the post authorize callback
         | 
| 17 17 | 
             
            	* Version 0.1.3
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            12-July-2012 - Sam 
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              * Fixed incorrect profiling steps (was not indenting or measuring start time right
         | 
| 22 | 
            +
            	* Implemented native PG and MySql2 interceptors, this gives way more accurate times
         | 
| 23 | 
            +
            	* Refactored context so its a proper class and not a hash 
         | 
| 24 | 
            +
            	* Added some more client probing built in to rails
         | 
| 25 | 
            +
            	* More tests
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            18-July-2012 - Sam 
         | 
| 28 | 
            +
              
         | 
| 29 | 
            +
              * Added First Paint time for chrome
         | 
| 30 | 
            +
              * Bug fix to ensure non Rails installs have mini profiler
         | 
| 31 | 
            +
              * Version 0.1.7
         | 
| 32 | 
            +
             | 
    
        data/README.md
    CHANGED
    
    | @@ -47,6 +47,24 @@ class MyApp < Sinatra::Base | |
| 47 47 | 
             
            end
         | 
| 48 48 | 
             
            ```
         | 
| 49 49 |  | 
| 50 | 
            +
            ## Storage
         | 
| 51 | 
            +
             | 
| 52 | 
            +
            By default, rack-mini-profiler stores its results in a memory store: 
         | 
| 53 | 
            +
             | 
| 54 | 
            +
            ```ruby 
         | 
| 55 | 
            +
            # our default
         | 
| 56 | 
            +
            Rack::MiniProfiler.config.storage = Rack::MiniProfiler::MemoryStore
         | 
| 57 | 
            +
            ```
         | 
| 58 | 
            +
             | 
| 59 | 
            +
            There are 2 other available storage engines, `RedisStore` and `FileStore`. 
         | 
| 60 | 
            +
             | 
| 61 | 
            +
            MemoryStore is stores results in a processes heap - something that does not work well in a multi process environment. 
         | 
| 62 | 
            +
            FileStore stores results in the file system - something that may not work well in a multi machine environment. 
         | 
| 63 | 
            +
             | 
| 64 | 
            +
            Additionally you may implement an AbstractStore for your own provider. 
         | 
| 65 | 
            +
             | 
| 66 | 
            +
            Rails hooks up a FileStore for all environments. 
         | 
| 67 | 
            +
             | 
| 50 68 | 
             
            ## Running the Specs
         | 
| 51 69 |  | 
| 52 70 | 
             
            ```
         | 
    
        data/lib/html/includes.css
    CHANGED
    
    | @@ -1 +1,75 @@ | |
| 1 | 
            -
            .profiler-result,.profiler-queries{color:#555;line-height:1;font-size:12px;}.profiler-result pre,.profiler-queries pre,.profiler-result code,.profiler-queries code,.profiler-result label,.profiler-queries label,.profiler-result table,.profiler-queries table,.profiler-result tbody,.profiler-queries tbody,.profiler-result thead,.profiler-queries thead,.profiler-result tfoot,.profiler-queries tfoot,.profiler-result tr,.profiler-queries tr,.profiler-result th,.profiler-queries th,.profiler-result td,.profiler-queries td{margin:0;padding:0;border:0;font-size:100%;font:inherit;vertical-align:baseline;background-color:transparent;overflow:visible;max-height:none;}.profiler-result table,.profiler-queries table{border-collapse:collapse;border-spacing:0;}.profiler-result a,.profiler-queries a,.profiler-result a:hover,.profiler-queries a:hover{cursor:pointer;color:#07c;}.profiler-result a,.profiler-queries a{text-decoration:none;}.profiler-result a:hover,.profiler-queries a:hover{text-decoration:underline;}.profiler-result{font-family:Helvetica,Arial,sans-serif;}.profiler-result .profiler-toggle-duration-with-children{float:right;}.profiler-result table.profiler-client-timings{margin-top:10px;}.profiler-result .profiler-label{color:#555;overflow:hidden;text-overflow:ellipsis;}.profiler-result .profiler-unit{color:#aaa;}.profiler-result .profiler-trivial{display:none;}.profiler-result .profiler-trivial td,.profiler-result .profiler-trivial td *{color:#aaa !important;}.profiler-result pre,.profiler-result code,.profiler-result .profiler-number,.profiler-result .profiler-unit{font-family:Consolas,monospace,serif;}.profiler-result .profiler-number{color:#111;}.profiler-result .profiler-info{text-align:right;}.profiler-result .profiler-info .profiler-name{float:left;}.profiler-result .profiler-info .profiler-server-time{white-space:nowrap;}.profiler-result .profiler-timings th{background-color:#fff;color:#aaa;text-align:right;}.profiler-result .profiler-timings th,.profiler-result .profiler-timings td{white-space:nowrap;}.profiler-result .profiler-timings .profiler-duration-with-children{display:none;}.profiler-result .profiler-timings .profiler-duration{font-family:Consolas,monospace,serif;color:#111;text-align:right;}.profiler-result .profiler-timings .profiler-indent{letter-spacing:4px;}.profiler-result .profiler-timings .profiler-queries-show .profiler-number,.profiler-result .profiler-timings .profiler-queries-show .profiler-unit{color:#07c;}.profiler-result .profiler-timings .profiler-queries-duration{padding-left:6px;}.profiler-result .profiler-timings .profiler-percent-in-sql{white-space:nowrap;text-align:right;}.profiler-result .profiler-timings tfoot td{padding-top:10px;text-align:right;}.profiler-result .profiler-timings tfoot td a{font-size:95%;display:inline-block;margin-left:12px;}.profiler-result .profiler-timings tfoot td a:first-child{float:left;margin-left:0px;}.profiler-result .profiler-queries{font-family:Helvetica,Arial,sans-serif;}.profiler-result .profiler-queries .profiler-stack-trace{margin-bottom:15px;}.profiler-result .profiler-queries pre{font-family:Consolas,monospace,serif;white-space:pre-wrap;}.profiler-result .profiler-queries th{background-color:#fff;border-bottom:1px solid #555;font-weight:bold;padding:15px;white-space:nowrap;}.profiler-result .profiler-queries td{padding:15px;text-align:left;background-color:#fff;}.profiler-result .profiler-queries td:last-child{padding-right:25px;}.profiler-result .profiler-queries .profiler-odd td{background-color:#e5e5e5;}.profiler-result .profiler-queries .profiler-since-start,.profiler-result .profiler-queries .profiler-duration{text-align:right;}.profiler-result .profiler-queries .profiler-info div{text-align:right;margin-bottom:5px;}.profiler-result .profiler-queries .profiler-gap-info,.profiler-result .profiler-queries .profiler-gap-info td{background-color:#ccc;}.profiler-result .profiler-queries .profiler-gap-info .profiler-unit{color:#777;}.profiler-result .profiler-queries .profiler-gap-info .profiler-info{text-align:right;}.profiler-result .profiler-queries .profiler-gap-info.profiler-trivial-gaps{display:none;}.profiler-result .profiler-queries .profiler-trivial-gap-container{text-align:center;}.profiler-result .profiler-queries .str{color:maroon;}.profiler-result .profiler-queries .kwd{color:#00008b;}.profiler-result .profiler-queries .com{color:gray;}.profiler-result .profiler-queries .typ{color:#2b91af;}.profiler-result .profiler-queries .lit{color:maroon;}.profiler-result .profiler-queries .pun{color:#000;}.profiler-result .profiler-queries .pln{color:#000;}.profiler-result .profiler-queries .tag{color:maroon;}.profiler-result .profiler-queries .atn{color:red;}.profiler-result .profiler-queries .atv{color:blue;}.profiler-result .profiler-queries .dec{color:purple;}.profiler-result .profiler-warning,.profiler-result .profiler-warning *,.profiler-result .profiler-warning .profiler-queries-show,.profiler-result .profiler-warning .profiler-queries-show .profiler-unit{color:#f00;}.profiler-result .profiler-warning:hover,.profiler-result .profiler-warning *:hover,.profiler-result .profiler-warning .profiler-queries-show:hover,.profiler-result .profiler-warning .profiler-queries-show .profiler-unit:hover{color:#f00;}.profiler-result .profiler-nuclear{color:#f00;font-weight:bold;padding-right:2px;}.profiler-result .profiler-nuclear:hover{color:#f00;}.profiler-results{z-index:2147483643;position:fixed;top:0px;}.profiler-results.profiler-left{left:0px;}.profiler-results.profiler-left.profiler-no-controls .profiler-result:last-child .profiler-button,.profiler-results.profiler-left .profiler-controls{-webkit-border-bottom-right-radius:10px;-moz-border-radius-bottomright:10px;border-bottom-right-radius:10px;}.profiler-results.profiler-left .profiler-button,.profiler-results.profiler-left .profiler-controls{border-right:1px solid #888;}.profiler-results.profiler-right{right:0px;}.profiler-results.profiler-right.profiler-no-controls .profiler-result:last-child .profiler-button,.profiler-results.profiler-right .profiler-controls{-webkit-border-bottom-left-radius:10px;-moz-border-radius-bottomleft:10px;border-bottom-left-radius:10px;}.profiler-results.profiler-right .profiler-button,.profiler-results.profiler-right .profiler-controls{border-left:1px solid #888;}.profiler-results .profiler-button,.profiler-results .profiler-controls{display:none;z-index:2147483640;border-bottom:1px solid #888;background-color:#fff;padding:4px 7px;text-align:right;cursor:pointer;}.profiler-results .profiler-button.profiler-button-active,.profiler-results .profiler-controls.profiler-button-active{background-color:maroon;}.profiler-results .profiler-button.profiler-button-active .profiler-number,.profiler-results .profiler-controls.profiler-button-active .profiler-number,.profiler-results .profiler-button.profiler-button-active .profiler-nuclear,.profiler-results .profiler-controls.profiler-button-active .profiler-nuclear{color:#fff;font-weight:bold;}.profiler-results .profiler-button.profiler-button-active .profiler-unit,.profiler-results .profiler-controls.profiler-button-active .profiler-unit{color:#fff;font-weight:normal;}.profiler-results .profiler-controls{display:block;font-size:12px;font-family:Consolas,monospace,serif;cursor:default;text-align:center;}.profiler-results .profiler-controls span{border-right:1px solid #aaa;padding-right:5px;margin-right:5px;cursor:pointer;}.profiler-results .profiler-controls span:last-child{border-right:none;}.profiler-results .profiler-popup{display:none;z-index:2147483641;position:absolute;background-color:#fff;border:1px solid #aaa;padding:5px 10px;text-align:left;line-height:18px;overflow:auto;-moz-box-shadow:0px 1px 15px #555;-webkit-box-shadow:0px 1px 15px #555;box-shadow:0px 1px 15px #555;}.profiler-results .profiler-popup .profiler-info{margin-bottom:3px;padding-bottom:2px;border-bottom:1px solid #ddd;}.profiler-results .profiler-popup .profiler-info .profiler-name{font-size:110%;font-weight:bold;}.profiler-results .profiler-popup .profiler-info .profiler-name .profiler-overall-duration{display:none;}.profiler-results .profiler-popup .profiler-info .profiler-server-time{font-size:95%;}.profiler-results .profiler-popup .profiler-timings th,.profiler-results .profiler-popup .profiler-timings td{padding-left:6px;padding-right:6px;}.profiler-results .profiler-popup .profiler-timings th{font-size:95%;padding-bottom:3px;}.profiler-results .profiler-popup .profiler-timings .profiler-label{max-width:275px;}.profiler-results .profiler-queries{display:none;z-index:2147483643;position:absolute;overflow-y:auto;overflow-x:hidden;background-color:#fff;}.profiler-results .profiler-queries th{font-size:17px;}.profiler-results.profiler-min .profiler-result{display:none;}.profiler-results.profiler-min .profiler-controls span{display:none;}.profiler-results.profiler-min .profiler-controls .profiler-min-max{border-right:none;padding:0px;margin:0px;}.profiler-queries-bg{z-index:2147483642;display:none;background:#000;opacity:0.7;position:absolute;top:0px;left:0px;min-width:100%;}.profiler-result-full .profiler-result{width:950px;margin:30px auto;}.profiler-result-full .profiler-result .profiler-button{display:none;}.profiler-result-full .profiler-result .profiler-popup .profiler-info{font-size:25px;border-bottom:1px solid #aaa;padding-bottom:3px;margin-bottom:25px;}.profiler-result-full .profiler-result .profiler-popup .profiler-info .profiler-overall-duration{padding-right:20px;font-size:80%;color:#888;}.profiler-result-full .profiler-result .profiler-popup .profiler-timings td,.profiler-result-full .profiler-result .profiler-popup .profiler-timings th{padding-left:8px;padding-right:8px;}.profiler-result-full .profiler-result .profiler-popup .profiler-timings th{padding-bottom:7px;}.profiler-result-full .profiler-result .profiler-popup .profiler-timings td{font-size:14px;padding-bottom:4px;}.profiler-result-full .profiler-result .profiler-popup .profiler-timings td:first-child{padding-left:10px;}.profiler-result-full .profiler-result .profiler-popup .profiler-timings .profiler-label{max-width:550px;}.profiler-result-full .profiler-result .profiler-queries{margin:25px 0;}.profiler-result-full .profiler-result .profiler-queries table{width:100%;}.profiler-result-full .profiler-result .profiler-queries th{font-size:16px;color:#555;line-height:20px;}.profiler-result-full .profiler-result .profiler-queries td{padding:15px 10px;text-align:left;}.profiler-result-full .profiler-result .profiler-queries .profiler-info div{text-align:right;margin-bottom:5px;}
         | 
| 1 | 
            +
            .profiler-result,.profiler-queries{color:#555;line-height:1;font-size:12px;}.profiler-result pre,.profiler-queries pre,.profiler-result code,.profiler-queries code,.profiler-result label,.profiler-queries label,.profiler-result table,.profiler-queries table,.profiler-result tbody,.profiler-queries tbody,.profiler-result thead,.profiler-queries thead,.profiler-result tfoot,.profiler-queries tfoot,.profiler-result tr,.profiler-queries tr,.profiler-result th,.profiler-queries th,.profiler-result td,.profiler-queries td{margin:0;padding:0;border:0;font-size:100%;font:inherit;vertical-align:baseline;background-color:transparent;overflow:visible;max-height:none;}
         | 
| 2 | 
            +
            .profiler-result table,.profiler-queries table{border-collapse:collapse;border-spacing:0;}
         | 
| 3 | 
            +
            .profiler-result a,.profiler-queries a,.profiler-result a:hover,.profiler-queries a:hover{cursor:pointer;color:#0077cc;}
         | 
| 4 | 
            +
            .profiler-result a,.profiler-queries a{text-decoration:none;}.profiler-result a:hover,.profiler-queries a:hover{text-decoration:underline;}
         | 
| 5 | 
            +
            .profiler-result{font-family:Helvetica,Arial,sans-serif;}.profiler-result .profiler-toggle-duration-with-children{float:right;}
         | 
| 6 | 
            +
            .profiler-result table.profiler-client-timings{margin-top:10px;}
         | 
| 7 | 
            +
            .profiler-result .profiler-label{color:#555555;overflow:hidden;text-overflow:ellipsis;}
         | 
| 8 | 
            +
            .profiler-result .profiler-unit{color:#aaaaaa;}
         | 
| 9 | 
            +
            .profiler-result .profiler-trivial{display:none;}.profiler-result .profiler-trivial td,.profiler-result .profiler-trivial td *{color:#aaaaaa !important;}
         | 
| 10 | 
            +
            .profiler-result pre,.profiler-result code,.profiler-result .profiler-number,.profiler-result .profiler-unit{font-family:Consolas,monospace,serif;}
         | 
| 11 | 
            +
            .profiler-result .profiler-number{color:#111111;}
         | 
| 12 | 
            +
            .profiler-result .profiler-info{text-align:right;}.profiler-result .profiler-info .profiler-name{float:left;}
         | 
| 13 | 
            +
            .profiler-result .profiler-info .profiler-server-time{white-space:nowrap;}
         | 
| 14 | 
            +
            .profiler-result .profiler-timings th{background-color:#fff;color:#aaaaaa;text-align:right;}
         | 
| 15 | 
            +
            .profiler-result .profiler-timings th,.profiler-result .profiler-timings td{white-space:nowrap;}
         | 
| 16 | 
            +
            .profiler-result .profiler-timings .profiler-duration-with-children{display:none;}
         | 
| 17 | 
            +
            .profiler-result .profiler-timings .profiler-duration{font-family:Consolas,monospace,serif;color:#111111;text-align:right;}
         | 
| 18 | 
            +
            .profiler-result .profiler-timings .profiler-indent{letter-spacing:4px;}
         | 
| 19 | 
            +
            .profiler-result .profiler-timings .profiler-queries-show .profiler-number,.profiler-result .profiler-timings .profiler-queries-show .profiler-unit{color:#0077cc;}
         | 
| 20 | 
            +
            .profiler-result .profiler-timings .profiler-queries-duration{padding-left:6px;}
         | 
| 21 | 
            +
            .profiler-result .profiler-timings .profiler-percent-in-sql{white-space:nowrap;text-align:right;}
         | 
| 22 | 
            +
            .profiler-result .profiler-timings tfoot td{padding-top:10px;text-align:right;}.profiler-result .profiler-timings tfoot td a{font-size:95%;display:inline-block;margin-left:12px;}.profiler-result .profiler-timings tfoot td a:first-child{float:left;margin-left:0px;}
         | 
| 23 | 
            +
            .profiler-result .profiler-queries{font-family:Helvetica,Arial,sans-serif;}.profiler-result .profiler-queries .profiler-stack-trace{margin-bottom:15px;}
         | 
| 24 | 
            +
            .profiler-result .profiler-queries pre{font-family:Consolas,monospace,serif;white-space:pre-wrap;}
         | 
| 25 | 
            +
            .profiler-result .profiler-queries th{background-color:#fff;border-bottom:1px solid #555;font-weight:bold;padding:15px;white-space:nowrap;}
         | 
| 26 | 
            +
            .profiler-result .profiler-queries td{padding:15px;text-align:left;background-color:#fff;}.profiler-result .profiler-queries td:last-child{padding-right:25px;}
         | 
| 27 | 
            +
            .profiler-result .profiler-queries .profiler-odd td{background-color:#e5e5e5;}
         | 
| 28 | 
            +
            .profiler-result .profiler-queries .profiler-since-start,.profiler-result .profiler-queries .profiler-duration{text-align:right;}
         | 
| 29 | 
            +
            .profiler-result .profiler-queries .profiler-info div{text-align:right;margin-bottom:5px;}
         | 
| 30 | 
            +
            .profiler-result .profiler-queries .profiler-gap-info,.profiler-result .profiler-queries .profiler-gap-info td{background-color:#ccc;}
         | 
| 31 | 
            +
            .profiler-result .profiler-queries .profiler-gap-info .profiler-unit{color:#777;}
         | 
| 32 | 
            +
            .profiler-result .profiler-queries .profiler-gap-info .profiler-info{text-align:right;}
         | 
| 33 | 
            +
            .profiler-result .profiler-queries .profiler-gap-info.profiler-trivial-gaps{display:none;}
         | 
| 34 | 
            +
            .profiler-result .profiler-queries .profiler-trivial-gap-container{text-align:center;}
         | 
| 35 | 
            +
            .profiler-result .profiler-queries .str{color:#800000;}
         | 
| 36 | 
            +
            .profiler-result .profiler-queries .kwd{color:#00008b;}
         | 
| 37 | 
            +
            .profiler-result .profiler-queries .com{color:#808080;}
         | 
| 38 | 
            +
            .profiler-result .profiler-queries .typ{color:#2b91af;}
         | 
| 39 | 
            +
            .profiler-result .profiler-queries .lit{color:#800000;}
         | 
| 40 | 
            +
            .profiler-result .profiler-queries .pun{color:#000000;}
         | 
| 41 | 
            +
            .profiler-result .profiler-queries .pln{color:#000000;}
         | 
| 42 | 
            +
            .profiler-result .profiler-queries .tag{color:#800000;}
         | 
| 43 | 
            +
            .profiler-result .profiler-queries .atn{color:#ff0000;}
         | 
| 44 | 
            +
            .profiler-result .profiler-queries .atv{color:#0000ff;}
         | 
| 45 | 
            +
            .profiler-result .profiler-queries .dec{color:#800080;}
         | 
| 46 | 
            +
            .profiler-result .profiler-warning,.profiler-result .profiler-warning *,.profiler-result .profiler-warning .profiler-queries-show,.profiler-result .profiler-warning .profiler-queries-show .profiler-unit{color:#f00;}.profiler-result .profiler-warning:hover,.profiler-result .profiler-warning *:hover,.profiler-result .profiler-warning .profiler-queries-show:hover,.profiler-result .profiler-warning .profiler-queries-show .profiler-unit:hover{color:#f00;}
         | 
| 47 | 
            +
            .profiler-result .profiler-nuclear{color:#f00;font-weight:bold;padding-right:2px;}.profiler-result .profiler-nuclear:hover{color:#f00;}
         | 
| 48 | 
            +
            .profiler-results{z-index:2147483643;position:fixed;top:0px;}.profiler-results.profiler-left{left:0px;}.profiler-results.profiler-left.profiler-no-controls .profiler-result:last-child .profiler-button,.profiler-results.profiler-left .profiler-controls{-webkit-border-bottom-right-radius:10px;-moz-border-radius-bottomright:10px;border-bottom-right-radius:10px;}
         | 
| 49 | 
            +
            .profiler-results.profiler-left .profiler-button,.profiler-results.profiler-left .profiler-controls{border-right:1px solid #888888;}
         | 
| 50 | 
            +
            .profiler-results.profiler-right{right:0px;}.profiler-results.profiler-right.profiler-no-controls .profiler-result:last-child .profiler-button,.profiler-results.profiler-right .profiler-controls{-webkit-border-bottom-left-radius:10px;-moz-border-radius-bottomleft:10px;border-bottom-left-radius:10px;}
         | 
| 51 | 
            +
            .profiler-results.profiler-right .profiler-button,.profiler-results.profiler-right .profiler-controls{border-left:1px solid #888888;}
         | 
| 52 | 
            +
            .profiler-results .profiler-button,.profiler-results .profiler-controls{display:none;z-index:2147483640;border-bottom:1px solid #888888;background-color:#fff;padding:4px 7px;text-align:right;cursor:pointer;}.profiler-results .profiler-button.profiler-button-active,.profiler-results .profiler-controls.profiler-button-active{background-color:maroon;}.profiler-results .profiler-button.profiler-button-active .profiler-number,.profiler-results .profiler-controls.profiler-button-active .profiler-number,.profiler-results .profiler-button.profiler-button-active .profiler-nuclear,.profiler-results .profiler-controls.profiler-button-active .profiler-nuclear{color:#fff;font-weight:bold;}
         | 
| 53 | 
            +
            .profiler-results .profiler-button.profiler-button-active .profiler-unit,.profiler-results .profiler-controls.profiler-button-active .profiler-unit{color:#fff;font-weight:normal;}
         | 
| 54 | 
            +
            .profiler-results .profiler-controls{display:block;font-size:12px;font-family:Consolas,monospace,serif;cursor:default;text-align:center;}.profiler-results .profiler-controls span{border-right:1px solid #aaaaaa;padding-right:5px;margin-right:5px;cursor:pointer;}
         | 
| 55 | 
            +
            .profiler-results .profiler-controls span:last-child{border-right:none;}
         | 
| 56 | 
            +
            .profiler-results .profiler-popup{display:none;z-index:2147483641;position:absolute;background-color:#fff;border:1px solid #aaa;padding:5px 10px;text-align:left;line-height:18px;overflow:auto;-moz-box-shadow:0px 1px 15px #555555;-webkit-box-shadow:0px 1px 15px #555555;box-shadow:0px 1px 15px #555555;}.profiler-results .profiler-popup .profiler-info{margin-bottom:3px;padding-bottom:2px;border-bottom:1px solid #ddd;}.profiler-results .profiler-popup .profiler-info .profiler-name{font-size:110%;font-weight:bold;}.profiler-results .profiler-popup .profiler-info .profiler-name .profiler-overall-duration{display:none;}
         | 
| 57 | 
            +
            .profiler-results .profiler-popup .profiler-info .profiler-server-time{font-size:95%;}
         | 
| 58 | 
            +
            .profiler-results .profiler-popup .profiler-timings th,.profiler-results .profiler-popup .profiler-timings td{padding-left:6px;padding-right:6px;}
         | 
| 59 | 
            +
            .profiler-results .profiler-popup .profiler-timings th{font-size:95%;padding-bottom:3px;}
         | 
| 60 | 
            +
            .profiler-results .profiler-popup .profiler-timings .profiler-label{max-width:275px;}
         | 
| 61 | 
            +
            .profiler-results .profiler-queries{display:none;z-index:2147483643;position:absolute;overflow-y:auto;overflow-x:hidden;background-color:#fff;}.profiler-results .profiler-queries th{font-size:17px;}
         | 
| 62 | 
            +
            .profiler-results.profiler-min .profiler-result{display:none;}
         | 
| 63 | 
            +
            .profiler-results.profiler-min .profiler-controls span{display:none;}
         | 
| 64 | 
            +
            .profiler-results.profiler-min .profiler-controls .profiler-min-max{border-right:none;padding:0px;margin:0px;}
         | 
| 65 | 
            +
            .profiler-queries-bg{z-index:2147483642;display:none;background:#000;opacity:0.7;position:absolute;top:0px;left:0px;min-width:100%;}
         | 
| 66 | 
            +
            .profiler-result-full .profiler-result{width:950px;margin:30px auto;}.profiler-result-full .profiler-result .profiler-button{display:none;}
         | 
| 67 | 
            +
            .profiler-result-full .profiler-result .profiler-popup .profiler-info{font-size:25px;border-bottom:1px solid #aaaaaa;padding-bottom:3px;margin-bottom:25px;}.profiler-result-full .profiler-result .profiler-popup .profiler-info .profiler-overall-duration{padding-right:20px;font-size:80%;color:#888;}
         | 
| 68 | 
            +
            .profiler-result-full .profiler-result .profiler-popup .profiler-timings td,.profiler-result-full .profiler-result .profiler-popup .profiler-timings th{padding-left:8px;padding-right:8px;}
         | 
| 69 | 
            +
            .profiler-result-full .profiler-result .profiler-popup .profiler-timings th{padding-bottom:7px;}
         | 
| 70 | 
            +
            .profiler-result-full .profiler-result .profiler-popup .profiler-timings td{font-size:14px;padding-bottom:4px;}.profiler-result-full .profiler-result .profiler-popup .profiler-timings td:first-child{padding-left:10px;}
         | 
| 71 | 
            +
            .profiler-result-full .profiler-result .profiler-popup .profiler-timings .profiler-label{max-width:550px;}
         | 
| 72 | 
            +
            .profiler-result-full .profiler-result .profiler-queries{margin:25px 0;}.profiler-result-full .profiler-result .profiler-queries table{width:100%;}
         | 
| 73 | 
            +
            .profiler-result-full .profiler-result .profiler-queries th{font-size:16px;color:#555;line-height:20px;}
         | 
| 74 | 
            +
            .profiler-result-full .profiler-result .profiler-queries td{padding:15px 10px;text-align:left;}
         | 
| 75 | 
            +
            .profiler-result-full .profiler-result .profiler-queries .profiler-info div{text-align:right;margin-bottom:5px;}
         | 
    
        data/lib/html/includes.js
    CHANGED
    
    | @@ -100,6 +100,18 @@ var MiniProfiler = (function ($) { | |
| 100 100 | 
             
                                    copy.navigation.redirectCount = clientPerformance.navigation.redirectCount;
         | 
| 101 101 | 
             
                                }
         | 
| 102 102 | 
             
                                clientPerformance = copy;
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                                // hack to add chrome timings 
         | 
| 105 | 
            +
                                if (window.chrome && window.chrome.loadTimes) {
         | 
| 106 | 
            +
                                  var chromeTimes = window.chrome.loadTimes(); 
         | 
| 107 | 
            +
                                  if (chromeTimes.firstPaintTime) {
         | 
| 108 | 
            +
                                    clientPerformance.timing["First Paint Time"] = Math.round(chromeTimes.firstPaintTime * 1000);
         | 
| 109 | 
            +
                                  }
         | 
| 110 | 
            +
                                  if (chromeTimes.firstPaintTime) {
         | 
| 111 | 
            +
                                    clientPerformance.timing["First Paint After Load Time"] = Math.round(chromeTimes.firstPaintAfterLoadTime * 1000);
         | 
| 112 | 
            +
                                  }
         | 
| 113 | 
            +
             | 
| 114 | 
            +
                                }
         | 
| 103 115 | 
             
                            }
         | 
| 104 116 | 
             
                        }
         | 
| 105 117 |  | 
| @@ -593,7 +605,7 @@ var MiniProfiler = (function ($) { | |
| 593 605 |  | 
| 594 606 | 
             
                        for (var i = 0; i < clientTimings.Timings.length; i++) {
         | 
| 595 607 | 
             
                            t = clientTimings.Timings[i];
         | 
| 596 | 
            -
                            var trivial = t.Name != "Dom Complete" && t.Name != "Response";
         | 
| 608 | 
            +
                            var trivial = t.Name != "Dom Complete" && t.Name != "Response" && t.Name != "First Paint Time";
         | 
| 597 609 | 
             
                            trivial = t.Duration < 2 ? trivial : false;
         | 
| 598 610 | 
             
                            list.push(
         | 
| 599 611 | 
             
                            {
         | 
| @@ -811,4 +823,4 @@ PR_TAG:"tag",PR_TYPE:S}})() | |
| 811 823 | 
             
            PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["str",/^(?:"(?:[^\"\\]|\\.)*"|'(?:[^\'\\]|\\.)*')/,null,"\"'"]],[["com",/^(?:--[^\r\n]*|\/\*[\s\S]*?(?:\*\/|$))/],["kwd",/^(?:ADD|ALL|ALTER|AND|ANY|AS|ASC|AUTHORIZATION|BACKUP|BEGIN|BETWEEN|BREAK|BROWSE|BULK|BY|CASCADE|CASE|CHECK|CHECKPOINT|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMN|COMMIT|COMPUTE|CONSTRAINT|CONTAINS|CONTAINSTABLE|CONTINUE|CONVERT|CREATE|CROSS|CURRENT|CURRENT_DATE|CURRENT_TIME|CURRENT_TIMESTAMP|CURRENT_USER|CURSOR|DATABASE|DBCC|DEALLOCATE|DECLARE|DEFAULT|DELETE|DENY|DESC|DISK|DISTINCT|DISTRIBUTED|DOUBLE|DROP|DUMMY|DUMP|ELSE|END|ERRLVL|ESCAPE|EXCEPT|EXEC|EXECUTE|EXISTS|EXIT|FETCH|FILE|FILLFACTOR|FOR|FOREIGN|FREETEXT|FREETEXTTABLE|FROM|FULL|FUNCTION|GOTO|GRANT|GROUP|HAVING|HOLDLOCK|IDENTITY|IDENTITYCOL|IDENTITY_INSERT|IF|IN|INDEX|INNER|INSERT|INTERSECT|INTO|IS|JOIN|KEY|KILL|LEFT|LIKE|LINENO|LOAD|NATIONAL|NOCHECK|NONCLUSTERED|NOT|NULL|NULLIF|OF|OFF|OFFSETS|ON|OPEN|OPENDATASOURCE|OPENQUERY|OPENROWSET|OPENXML|OPTION|OR|ORDER|OUTER|OVER|PERCENT|PLAN|PRECISION|PRIMARY|PRINT|PROC|PROCEDURE|PUBLIC|RAISERROR|READ|READTEXT|RECONFIGURE|REFERENCES|REPLICATION|RESTORE|RESTRICT|RETURN|REVOKE|RIGHT|ROLLBACK|ROWCOUNT|ROWGUIDCOL|RULE|SAVE|SCHEMA|SELECT|SESSION_USER|SET|SETUSER|SHUTDOWN|SOME|STATISTICS|SYSTEM_USER|TABLE|TEXTSIZE|THEN|TO|TOP|TRAN|TRANSACTION|TRIGGER|TRUNCATE|TSEQUAL|UNION|UNIQUE|UPDATE|UPDATETEXT|USE|USER|VALUES|VARYING|VIEW|WAITFOR|WHEN|WHERE|WHILE|WITH|WRITETEXT)(?=[^\w-]|$)/i,
         | 
| 812 824 | 
             
            null],["lit",/^[+-]?(?:0x[\da-f]+|(?:(?:\.\d+|\d+(?:\.\d*)?)(?:e[+\-]?\d+)?))/i],["pln",/^[a-z_][\w-]*/i],["pun",/^[^\w\t\n\r \xA0\"\'][^\w\t\n\r \xA0+\-\"\']*/]]),["sql"])
         | 
| 813 825 |  | 
| 814 | 
            -
            ;
         | 
| 826 | 
            +
            ;
         | 
    
        data/lib/html/includes.less
    CHANGED
    
    
    
        data/lib/html/profile_handler.js
    CHANGED
    
    | @@ -1,6 +1,6 @@ | |
| 1 | 
            -
            <script type="text/javascript"> | 
| 1 | 
            +
            <script type="text/javascript">
         | 
| 2 2 | 
             
                (function(){{
         | 
| 3 | 
            -
                    var init = function() {{ | 
| 3 | 
            +
                    var init = function() {{
         | 
| 4 4 | 
             
                            var load = function(s,f){{
         | 
| 5 5 | 
             
                                var sc = document.createElement('script');
         | 
| 6 6 | 
             
                                sc.async = 'async';
         | 
| @@ -14,8 +14,8 @@ | |
| 14 14 | 
             
                                }};
         | 
| 15 15 |  | 
| 16 16 | 
             
                                document.getElementsByTagName('head')[0].appendChild(sc);
         | 
| 17 | 
            -
                            }}; | 
| 18 | 
            -
             | 
| 17 | 
            +
                            }};
         | 
| 18 | 
            +
             | 
| 19 19 | 
             
                            var initMp = function(){{
         | 
| 20 20 | 
             
                                load('{path}includes.js?v={version}',function(){{
         | 
| 21 21 | 
             
                                    MiniProfiler.init({{
         | 
| @@ -32,18 +32,18 @@ | |
| 32 32 | 
             
                                    }});
         | 
| 33 33 | 
             
                                }});
         | 
| 34 34 | 
             
                            }};
         | 
| 35 | 
            -
                            if ({useExistingjQuery}) {{
         | 
| 35 | 
            +
                            if ({useExistingjQuery} && typeof(jQuery) === 'function') {{
         | 
| 36 36 | 
             
                                jQueryMP = jQuery;
         | 
| 37 37 | 
             
                                initMp();
         | 
| 38 38 | 
             
                            }} else {{
         | 
| 39 39 | 
             
                                load('{path}jquery.1.7.1.js?v={version}', initMp);
         | 
| 40 40 | 
             
                            }}
         | 
| 41 | 
            -
             | 
| 41 | 
            +
             | 
| 42 42 | 
             
                    }};
         | 
| 43 43 |  | 
| 44 | 
            -
                    var w = 0; | 
| 44 | 
            +
                    var w = 0;
         | 
| 45 45 | 
             
                    var f = false;
         | 
| 46 | 
            -
                    var deferInit = function(){{ | 
| 46 | 
            +
                    var deferInit = function(){{
         | 
| 47 47 | 
             
                        if (f) return;
         | 
| 48 48 | 
             
                        if (window.performance && window.performance.timing && window.performance.timing.loadEventEnd == 0 && w < 10000){{
         | 
| 49 49 | 
             
                            setTimeout(deferInit, 100);
         | 
| @@ -59,4 +59,4 @@ | |
| 59 59 | 
             
                    var o = window.onload;
         | 
| 60 60 | 
             
                    window.onload = function(){{if(o)o; deferInit()}};
         | 
| 61 61 | 
             
                }})();
         | 
| 62 | 
            -
            </script>
         | 
| 62 | 
            +
            </script>
         | 
| @@ -6,11 +6,24 @@ module Rack | |
| 6 6 | 
             
                # This class holds the client timings
         | 
| 7 7 | 
             
                class ClientTimerStruct < TimerStruct
         | 
| 8 8 |  | 
| 9 | 
            +
                  def self.init_instrumentation
         | 
| 10 | 
            +
                    "<script type=\"text/javascript\">mPt=function(){var t=[];return{t:t,probe:function(n){t.push({d:new Date(),n:n})}}}()</script>"
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
                  
         | 
| 13 | 
            +
                  def self.instrument(name,orig)
         | 
| 14 | 
            +
                    probe = "<script>mPt.probe('#{name}')</script>"
         | 
| 15 | 
            +
                    wrapped = probe
         | 
| 16 | 
            +
                    wrapped << orig 
         | 
| 17 | 
            +
                    wrapped << probe 
         | 
| 18 | 
            +
                    wrapped
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
             | 
| 9 22 | 
             
                  def initialize(env={})
         | 
| 10 23 | 
             
                    super
         | 
| 11 24 | 
             
                  end
         | 
| 12 25 |  | 
| 13 | 
            -
                  def init_from_form_data(env, page_struct)
         | 
| 26 | 
            +
                  def self.init_from_form_data(env, page_struct)
         | 
| 14 27 | 
             
                    timings = []
         | 
| 15 28 | 
             
                    clientTimes, clientPerf, baseTime = nil 
         | 
| 16 29 | 
             
                    form = env['rack.request.form_hash']
         | 
| @@ -21,6 +34,26 @@ module Rack | |
| 21 34 | 
             
                    baseTime = clientTimes['navigationStart'].to_i if clientTimes
         | 
| 22 35 | 
             
                    return unless clientTimes && baseTime 
         | 
| 23 36 |  | 
| 37 | 
            +
                    probes = form['clientProbes']
         | 
| 38 | 
            +
                    translated = {}
         | 
| 39 | 
            +
                    if probes && probes != "null"
         | 
| 40 | 
            +
                      probes.each do |id, val|
         | 
| 41 | 
            +
                        name = val["n"]
         | 
| 42 | 
            +
                        translated[name] ||= {} 
         | 
| 43 | 
            +
                        if translated[name][:start]
         | 
| 44 | 
            +
                          translated[name][:finish] = val["d"]
         | 
| 45 | 
            +
                        else 
         | 
| 46 | 
            +
                          translated[name][:start] = val["d"]
         | 
| 47 | 
            +
                        end
         | 
| 48 | 
            +
                      end
         | 
| 49 | 
            +
                    end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                    translated.each do |name, data|
         | 
| 52 | 
            +
                      h = {"Name" => name, "Start" => data[:start].to_i - baseTime}
         | 
| 53 | 
            +
                      h["Duration"] = data[:finish].to_i - data[:start].to_i if data[:finish]
         | 
| 54 | 
            +
                      timings.push(h)
         | 
| 55 | 
            +
                    end
         | 
| 56 | 
            +
             | 
| 24 57 | 
             
                    clientTimes.keys.find_all{|k| k =~ /Start$/ }.each do |k|
         | 
| 25 58 | 
             
                      start = clientTimes[k].to_i - baseTime 
         | 
| 26 59 | 
             
                      finish = clientTimes[k.sub(/Start$/, "End")].to_i - baseTime
         | 
| @@ -34,8 +67,10 @@ module Rack | |
| 34 67 | 
             
                      timings.push("Name" => k, "Start" => clientTimes[k].to_i - baseTime, "Duration" => -1)
         | 
| 35 68 | 
             
                    end
         | 
| 36 69 |  | 
| 37 | 
            -
                     | 
| 38 | 
            -
                     | 
| 70 | 
            +
                    rval = self.new
         | 
| 71 | 
            +
                    rval['RedirectCount'] = env['rack.request.form_hash']['clientPerformance']['navigation']['redirectCount']
         | 
| 72 | 
            +
                    rval['Timings'] = timings
         | 
| 73 | 
            +
                    rval
         | 
| 39 74 | 
             
                  end
         | 
| 40 75 | 
             
                end
         | 
| 41 76 |  | 
    
        data/lib/mini_profiler/config.rb
    CHANGED
    
    | @@ -14,7 +14,7 @@ module Rack | |
| 14 14 |  | 
| 15 15 | 
             
                attr_accessor :auto_inject, :base_url_path, :pre_authorize_cb, :position,
         | 
| 16 16 | 
             
                    :backtrace_remove, :backtrace_filter, :skip_schema_queries, 
         | 
| 17 | 
            -
                    :storage, :user_provider, :storage_instance, :storage_options, :skip_paths, :authorization_mode
         | 
| 17 | 
            +
                    :storage, :user_provider, :storage_instance, :storage_options, :skip_paths, :authorization_mode, :use_existing_jquery
         | 
| 18 18 |  | 
| 19 19 | 
             
                  def self.default
         | 
| 20 20 | 
             
                    new.instance_eval {
         | 
| @@ -30,6 +30,7 @@ module Rack | |
| 30 30 | 
             
                      @storage = MiniProfiler::MemoryStore
         | 
| 31 31 | 
             
                      @user_provider = Proc.new{|env| Rack::Request.new(env).ip}
         | 
| 32 32 | 
             
                      @authorization_mode = :allow_all
         | 
| 33 | 
            +
                      @use_existing_jquery = false
         | 
| 33 34 | 
             
                      self
         | 
| 34 35 | 
             
                    }
         | 
| 35 36 | 
             
                  end
         | 
| @@ -16,7 +16,7 @@ module Rack | |
| 16 16 | 
             
                          "Level" => 0,
         | 
| 17 17 | 
             
                          "User" => "unknown user",
         | 
| 18 18 | 
             
                          "HasUserViewed" => false,
         | 
| 19 | 
            -
                          "ClientTimings" =>  | 
| 19 | 
            +
                          "ClientTimings" => nil,
         | 
| 20 20 | 
             
                          "DurationMilliseconds" => 0,
         | 
| 21 21 | 
             
                          "HasTrivialTimings" => true,
         | 
| 22 22 | 
             
                          "HasAllTrivialTimigs" => false,
         | 
| @@ -35,15 +35,19 @@ module Rack | |
| 35 35 | 
             
                  def duration_ms
         | 
| 36 36 | 
             
                    @attributes['Root']['DurationMilliseconds']
         | 
| 37 37 | 
             
                  end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                  def root
         | 
| 40 | 
            +
                    @attributes['Root']
         | 
| 41 | 
            +
                  end
         | 
| 38 42 |  | 
| 39 43 | 
             
                  def to_json(*a)
         | 
| 40 44 | 
             
                    attribs = @attributes.merge(
         | 
| 41 45 | 
             
                      "Started" => '/Date(%d)/' % @attributes['Started'], 
         | 
| 42 46 | 
             
                      "DurationMilliseconds" => @attributes['Root']['DurationMilliseconds']
         | 
| 43 47 | 
             
                    )        
         | 
| 44 | 
            -
                    ::JSON.generate(attribs,  | 
| 48 | 
            +
                    ::JSON.generate(attribs, :max_nesting => 100)
         | 
| 45 49 | 
             
                  end
         | 
| 46 50 | 
             
                end
         | 
| 47 51 |  | 
| 48 52 | 
             
              end
         | 
| 49 | 
            -
            end
         | 
| 53 | 
            +
            end
         | 
| @@ -6,54 +6,103 @@ require 'mini_profiler/page_timer_struct' | |
| 6 6 | 
             
            require 'mini_profiler/sql_timer_struct'
         | 
| 7 7 | 
             
            require 'mini_profiler/client_timer_struct'
         | 
| 8 8 | 
             
            require 'mini_profiler/request_timer_struct'
         | 
| 9 | 
            -
            require 'mini_profiler/body_add_proxy'
         | 
| 10 9 | 
             
            require 'mini_profiler/storage/abstract_store'
         | 
| 11 10 | 
             
            require 'mini_profiler/storage/memory_store'
         | 
| 12 11 | 
             
            require 'mini_profiler/storage/redis_store'
         | 
| 13 12 | 
             
            require 'mini_profiler/storage/file_store'
         | 
| 14 13 | 
             
            require 'mini_profiler/config'
         | 
| 14 | 
            +
            require 'mini_profiler/profiling_methods'
         | 
| 15 | 
            +
            require 'mini_profiler/context'
         | 
| 15 16 |  | 
| 16 17 | 
             
            module Rack
         | 
| 17 18 |  | 
| 18 19 | 
             
            	class MiniProfiler
         | 
| 19 20 |  | 
| 20 | 
            -
            		VERSION = ' | 
| 21 | 
            -
            		@@instance = nil
         | 
| 21 | 
            +
            		VERSION = '104'.freeze
         | 
| 22 22 |  | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 23 | 
            +
                class << self 
         | 
| 24 | 
            +
                  
         | 
| 25 | 
            +
                  include Rack::MiniProfiler::ProfilingMethods
         | 
| 26 26 |  | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 27 | 
            +
                  def generate_id
         | 
| 28 | 
            +
                    rand(36**20).to_s(36)
         | 
| 29 | 
            +
                  end
         | 
| 30 30 |  | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 31 | 
            +
                  def reset_config
         | 
| 32 | 
            +
                    @config = Config.default
         | 
| 33 | 
            +
                  end
         | 
| 34 34 |  | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 35 | 
            +
                  # So we can change the configuration if we want
         | 
| 36 | 
            +
                  def config
         | 
| 37 | 
            +
                    @config ||= Config.default
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  def share_template
         | 
| 41 | 
            +
                    return @share_template unless @share_template.nil?
         | 
| 42 | 
            +
                    @share_template = ::File.read(::File.expand_path("../html/share.html", ::File.dirname(__FILE__)))
         | 
| 43 | 
            +
                  end
         | 
| 44 | 
            +
                  
         | 
| 45 | 
            +
                  def current
         | 
| 46 | 
            +
                    Thread.current[:mini_profiler_private]
         | 
| 47 | 
            +
                  end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                  def current=(c)
         | 
| 50 | 
            +
                    # we use TLS cause we need access to this from sql blocks and code blocks that have no access to env
         | 
| 51 | 
            +
                    Thread.current[:mini_profiler_private]= c
         | 
| 52 | 
            +
                  end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                  # discard existing results, don't track this request
         | 
| 55 | 
            +
                  def discard_results
         | 
| 56 | 
            +
                    self.current.discard = true if current
         | 
| 57 | 
            +
                  end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                  # user has the mini profiler cookie, only used when config.authorization_mode == :whitelist
         | 
| 60 | 
            +
                  def has_profiling_cookie?(env)
         | 
| 61 | 
            +
                    env['HTTP_COOKIE'] && env['HTTP_COOKIE'].include?("__profilin=stylin")
         | 
| 62 | 
            +
                  end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                  # remove the mini profiler cookie, only used when config.authorization_mode == :whitelist
         | 
| 65 | 
            +
                  def remove_profiling_cookie(headers)
         | 
| 66 | 
            +
                    Rack::Utils.delete_cookie_header!(headers, '__profilin')
         | 
| 67 | 
            +
                  end
         | 
| 39 68 |  | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 42 | 
            -
                   | 
| 69 | 
            +
                  def set_profiling_cookie(headers)
         | 
| 70 | 
            +
                    Rack::Utils.set_cookie_header!(headers, '__profilin', 'stylin')
         | 
| 71 | 
            +
                  end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                  def create_current(env={}, options={})
         | 
| 74 | 
            +
                    # profiling the request
         | 
| 75 | 
            +
                    self.current = Context.new
         | 
| 76 | 
            +
                    self.current.inject_js = config.auto_inject && (!env['HTTP_X_REQUESTED_WITH'].eql? 'XMLHttpRequest')
         | 
| 77 | 
            +
                    self.current.page_struct = PageTimerStruct.new(env)
         | 
| 78 | 
            +
                    self.current.current_timer = current.page_struct['Root']
         | 
| 79 | 
            +
                  end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                  def authorize_request
         | 
| 82 | 
            +
                    Thread.current[:mp_authorized] = true
         | 
| 83 | 
            +
                  end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                  def deauthorize_request
         | 
| 86 | 
            +
                    Thread.current[:mp_authorized] = nil
         | 
| 87 | 
            +
                  end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                  def request_authorized?
         | 
| 90 | 
            +
                    Thread.current[:mp_authorized]
         | 
| 91 | 
            +
                  end
         | 
| 43 92 | 
             
                end
         | 
| 44 93 |  | 
| 45 94 | 
             
            		#
         | 
| 46 95 | 
             
            		# options:
         | 
| 47 96 | 
             
            		# :auto_inject - should script be automatically injected on every html page (not xhr)
         | 
| 48 97 | 
             
            		def initialize(app, config = nil)
         | 
| 49 | 
            -
            			@@instance = self
         | 
| 50 98 | 
             
                  MiniProfiler.config.merge!(config)
         | 
| 51 99 | 
             
                  @config = MiniProfiler.config 
         | 
| 52 100 | 
             
            			@app = app
         | 
| 53 101 | 
             
            			@config.base_url_path << "/" unless @config.base_url_path.end_with? "/"
         | 
| 54 102 | 
             
                  unless @config.storage_instance
         | 
| 55 | 
            -
                    @ | 
| 103 | 
            +
                    @config.storage_instance = @config.storage.new(@config.storage_options)
         | 
| 56 104 | 
             
                  end
         | 
| 105 | 
            +
                  @storage = @config.storage_instance 
         | 
| 57 106 | 
             
            		end
         | 
| 58 107 |  | 
| 59 108 | 
             
                def user(env)
         | 
| @@ -69,7 +118,7 @@ module Rack | |
| 69 118 | 
             
                    return [404, {}, ["Request not found: #{request['id']} - user #{user(env)}"]] 
         | 
| 70 119 | 
             
                  end
         | 
| 71 120 | 
             
            			unless page_struct['HasUserViewed']
         | 
| 72 | 
            -
             | 
| 121 | 
            +
                    page_struct['ClientTimings'] = ClientTimerStruct.init_from_form_data(env, page_struct)
         | 
| 73 122 | 
             
            				page_struct['HasUserViewed'] = true
         | 
| 74 123 | 
             
                    @storage.save(page_struct) 
         | 
| 75 124 | 
             
                    @storage.set_viewed(user(env), id) 
         | 
| @@ -102,18 +151,19 @@ module Rack | |
| 102 151 | 
             
            			return [404, {}, ["Not found"]] unless ::File.exists? full_path
         | 
| 103 152 | 
             
            			f = Rack::File.new nil
         | 
| 104 153 | 
             
            			f.path = full_path
         | 
| 105 | 
            -
            			f.cache_control = "max-age:86400"
         | 
| 106 | 
            -
            			f.serving env
         | 
| 107 | 
            -
            		end
         | 
| 108 154 |  | 
| 109 | 
            -
             | 
| 110 | 
            -
             | 
| 111 | 
            -
             | 
| 155 | 
            +
                  begin 
         | 
| 156 | 
            +
                    f.cache_control = "max-age:86400"
         | 
| 157 | 
            +
                    f.serving env
         | 
| 158 | 
            +
                  rescue
         | 
| 159 | 
            +
                    # old versions of rack have a different api 
         | 
| 160 | 
            +
                    status, headers, body = f.serving
         | 
| 161 | 
            +
                    headers.merge! 'Cache-Control' => "max-age:86400"
         | 
| 162 | 
            +
                    [status, headers, body]
         | 
| 163 | 
            +
                  end
         | 
| 164 | 
            +
             | 
| 165 | 
            +
            		end
         | 
| 112 166 |  | 
| 113 | 
            -
                def self.current=(c)
         | 
| 114 | 
            -
                  # we use TLS cause we need access to this from sql blocks and code blocks that have no access to env
         | 
| 115 | 
            -
             			Thread.current['profiler.mini.private'] = c
         | 
| 116 | 
            -
                end
         | 
| 117 167 |  | 
| 118 168 | 
             
                def current
         | 
| 119 169 | 
             
                  MiniProfiler.current
         | 
| @@ -123,48 +173,11 @@ module Rack | |
| 123 173 | 
             
                  MiniProfiler.current=c
         | 
| 124 174 | 
             
                end
         | 
| 125 175 |  | 
| 126 | 
            -
                # discard existing results, don't track this request
         | 
| 127 | 
            -
                def self.discard_results
         | 
| 128 | 
            -
                  current[:discard] = true if current
         | 
| 129 | 
            -
                end
         | 
| 130 | 
            -
             | 
| 131 | 
            -
                # user has the mini profiler cookie, only used when config.authorization_mode == :whitelist
         | 
| 132 | 
            -
                def self.has_profiling_cookie?(env)
         | 
| 133 | 
            -
                  env['HTTP_COOKIE'] && env['HTTP_COOKIE'].include?("__profilin=stylin")
         | 
| 134 | 
            -
                end
         | 
| 135 | 
            -
             | 
| 136 | 
            -
                # remove the mini profiler cookie, only used when config.authorization_mode == :whitelist
         | 
| 137 | 
            -
                def self.remove_profiling_cookie(headers)
         | 
| 138 | 
            -
                  Rack::Utils.delete_cookie_header!(headers, '__profilin')
         | 
| 139 | 
            -
                end
         | 
| 140 | 
            -
             | 
| 141 | 
            -
                def self.set_profiling_cookie(headers)
         | 
| 142 | 
            -
                  Rack::Utils.set_cookie_header!(headers, '__profilin', 'stylin')
         | 
| 143 | 
            -
                end
         | 
| 144 176 |  | 
| 145 177 | 
             
                def config
         | 
| 146 178 | 
             
                  @config
         | 
| 147 179 | 
             
                end
         | 
| 148 180 |  | 
| 149 | 
            -
                def self.create_current(env={}, options={})
         | 
| 150 | 
            -
                  # profiling the request
         | 
| 151 | 
            -
                  self.current = {}
         | 
| 152 | 
            -
                  self.current['inject_js'] = config.auto_inject && (!env['HTTP_X_REQUESTED_WITH'].eql? 'XMLHttpRequest')
         | 
| 153 | 
            -
                  self.current['page_struct'] = PageTimerStruct.new(env)
         | 
| 154 | 
            -
                  self.current['current_timer'] = current['page_struct']['Root']
         | 
| 155 | 
            -
                end
         | 
| 156 | 
            -
             | 
| 157 | 
            -
                def self.authorize_request
         | 
| 158 | 
            -
                  Thread.current[:mp_authorized] = true
         | 
| 159 | 
            -
                end
         | 
| 160 | 
            -
             | 
| 161 | 
            -
                def self.deauthorize_request
         | 
| 162 | 
            -
                  Thread.current[:mp_authorized] = nil
         | 
| 163 | 
            -
                end
         | 
| 164 | 
            -
             | 
| 165 | 
            -
                def self.request_authorized?
         | 
| 166 | 
            -
                  Thread.current[:mp_authorized]
         | 
| 167 | 
            -
                end
         | 
| 168 181 |  | 
| 169 182 | 
             
            		def call(env)
         | 
| 170 183 | 
             
                  status = headers = body = nil
         | 
| @@ -174,12 +187,12 @@ module Rack | |
| 174 187 | 
             
                            (@config.skip_paths && @config.skip_paths.any?{ |p| path[0,p.length] == p}) ||
         | 
| 175 188 | 
             
                            env["QUERY_STRING"] =~ /pp=skip/ 
         | 
| 176 189 |  | 
| 177 | 
            -
                  has_profiling_cookie =  | 
| 190 | 
            +
                  has_profiling_cookie = MiniProfiler.has_profiling_cookie?(env)
         | 
| 178 191 |  | 
| 179 192 | 
             
                  if skip_it || (@config.authorization_mode == :whitelist && !has_profiling_cookie)
         | 
| 180 193 | 
             
                    status,headers,body = @app.call(env)
         | 
| 181 194 | 
             
                    if !skip_it && @config.authorization_mode == :whitelist && !has_profiling_cookie && MiniProfiler.request_authorized? 
         | 
| 182 | 
            -
                       | 
| 195 | 
            +
                      MiniProfiler.set_profiling_cookie(headers) 
         | 
| 183 196 | 
             
                    end
         | 
| 184 197 | 
             
                    return [status,headers,body]
         | 
| 185 198 | 
             
                  end
         | 
| @@ -188,34 +201,38 @@ module Rack | |
| 188 201 | 
             
            			return serve_html(env) if env['PATH_INFO'].start_with? @config.base_url_path
         | 
| 189 202 |  | 
| 190 203 | 
             
                  MiniProfiler.create_current(env, @config)
         | 
| 191 | 
            -
             | 
| 192 204 | 
             
                  MiniProfiler.deauthorize_request if @config.authorization_mode == :whitelist
         | 
| 193 205 | 
             
                  if env["QUERY_STRING"] =~ /pp=no-backtrace/
         | 
| 194 | 
            -
                    current | 
| 206 | 
            +
                    current.skip_backtrace = true
         | 
| 195 207 | 
             
                  elsif env["QUERY_STRING"] =~ /pp=full-backtrace/
         | 
| 196 | 
            -
                    current | 
| 208 | 
            +
                    current.full_backtrace = true
         | 
| 197 209 | 
             
                  end
         | 
| 198 210 |  | 
| 199 211 | 
             
                  done_sampling = false
         | 
| 200 212 | 
             
                  quit_sampler = false
         | 
| 201 213 | 
             
                  backtraces = nil
         | 
| 214 | 
            +
                  missing_stacktrace = false
         | 
| 202 215 | 
             
                  if env["QUERY_STRING"] =~ /pp=sample/
         | 
| 203 216 | 
             
                    backtraces = []
         | 
| 204 217 | 
             
                    t = Thread.current
         | 
| 205 218 | 
             
                    Thread.new {
         | 
| 206 | 
            -
                       | 
| 207 | 
            -
             | 
| 208 | 
            -
                         | 
| 209 | 
            -
             | 
| 210 | 
            -
             | 
| 211 | 
            -
             | 
| 212 | 
            -
             | 
| 213 | 
            -
                         | 
| 214 | 
            -
                        i  | 
| 215 | 
            -
             | 
| 216 | 
            -
             | 
| 219 | 
            +
                      begin
         | 
| 220 | 
            +
                        require 'stacktrace' rescue nil
         | 
| 221 | 
            +
                        if !t.respond_to? :stacktrace
         | 
| 222 | 
            +
                          missing_stacktrace = true
         | 
| 223 | 
            +
                          quit_sampler = true 
         | 
| 224 | 
            +
                          return
         | 
| 225 | 
            +
                        end
         | 
| 226 | 
            +
                        i = 10000 # for sanity never grab more than 10k samples 
         | 
| 227 | 
            +
                        while i > 0
         | 
| 228 | 
            +
                          break if done_sampling
         | 
| 229 | 
            +
                          i -= 1
         | 
| 230 | 
            +
                          backtraces << t.stacktrace
         | 
| 231 | 
            +
                          sleep 0.001
         | 
| 232 | 
            +
                        end
         | 
| 233 | 
            +
                      ensure
         | 
| 234 | 
            +
                        quit_sampler = true
         | 
| 217 235 | 
             
                      end
         | 
| 218 | 
            -
                      quit_sampler = true
         | 
| 219 236 | 
             
                    }
         | 
| 220 237 | 
             
                  end
         | 
| 221 238 |  | 
| @@ -230,14 +247,14 @@ module Rack | |
| 230 247 | 
             
                    end
         | 
| 231 248 | 
             
                  end
         | 
| 232 249 |  | 
| 233 | 
            -
                  skip_it = current | 
| 250 | 
            +
                  skip_it = current.discard
         | 
| 234 251 | 
             
                  if (config.authorization_mode == :whitelist && !MiniProfiler.request_authorized?)
         | 
| 235 252 | 
             
                    MiniProfiler.remove_profiling_cookie(headers)
         | 
| 236 253 | 
             
                    skip_it = true
         | 
| 237 254 | 
             
                  end
         | 
| 238 255 |  | 
| 239 256 | 
             
                  return [status,headers,body] if skip_it
         | 
| 240 | 
            -
             | 
| 257 | 
            +
             | 
| 241 258 | 
             
                  # we must do this here, otherwise current[:discard] is not being properly treated
         | 
| 242 259 | 
             
                  if env["QUERY_STRING"] =~ /pp=env/
         | 
| 243 260 | 
             
                    body.close if body.respond_to? :close
         | 
| @@ -249,11 +266,12 @@ module Rack | |
| 249 266 | 
             
                    return help
         | 
| 250 267 | 
             
                  end
         | 
| 251 268 |  | 
| 252 | 
            -
                  page_struct = current | 
| 269 | 
            +
                  page_struct = current.page_struct
         | 
| 253 270 | 
             
            			page_struct['Root'].record_time((Time.now - start) * 1000)
         | 
| 254 271 |  | 
| 255 272 | 
             
                  if backtraces
         | 
| 256 273 | 
             
                    body.close if body.respond_to? :close
         | 
| 274 | 
            +
                    return help(:stacktrace) if missing_stacktrace
         | 
| 257 275 | 
             
                    return analyze(backtraces, page_struct)
         | 
| 258 276 | 
             
                  end
         | 
| 259 277 |  | 
| @@ -265,30 +283,44 @@ module Rack | |
| 265 283 | 
             
                  # inject headers, script
         | 
| 266 284 | 
             
            			if status == 200
         | 
| 267 285 |  | 
| 286 | 
            +
                    # mini profiler is meddling with stuff, we can not cache cause we will get incorrect data
         | 
| 287 | 
            +
                    # Rack::ETag has already inserted some nonesense in the chain
         | 
| 288 | 
            +
                    headers.delete('ETag')
         | 
| 289 | 
            +
                    headers.delete('Date')
         | 
| 290 | 
            +
                    headers['Cache-Control'] = 'must-revalidate, private, max-age=0'
         | 
| 291 | 
            +
             | 
| 268 292 | 
             
            				# inject header
         | 
| 269 293 | 
             
                    if headers.is_a? Hash
         | 
| 270 294 | 
             
                      headers['X-MiniProfiler-Ids'] = ids_json(env)
         | 
| 271 295 | 
             
                    end
         | 
| 272 296 |  | 
| 273 297 | 
             
            				# inject script
         | 
| 274 | 
            -
            				if current | 
| 298 | 
            +
            				if current.inject_js \
         | 
| 275 299 | 
             
            					&& headers.has_key?('Content-Type') \
         | 
| 276 300 | 
             
            					&& !headers['Content-Type'].match(/text\/html/).nil? then
         | 
| 277 | 
            -
            					 | 
| 301 | 
            +
            					
         | 
| 302 | 
            +
                      response = Rack::Response.new([], status, headers)
         | 
| 303 | 
            +
                      script = self.get_profile_script(env)
         | 
| 304 | 
            +
                      if String === body
         | 
| 305 | 
            +
                        response.write inject(body,script)
         | 
| 306 | 
            +
                      else
         | 
| 307 | 
            +
                        body.each { |fragment| response.write inject(fragment, script) }
         | 
| 308 | 
            +
                      end
         | 
| 309 | 
            +
                      body.close if body.respond_to? :close
         | 
| 310 | 
            +
                      return response.finish
         | 
| 278 311 | 
             
            				end
         | 
| 279 312 | 
             
            			end
         | 
| 280 313 |  | 
| 281 | 
            -
                  # mini profiler is meddling with stuff, we can not cache cause we will get incorrect data
         | 
| 282 | 
            -
                  # Rack::ETag has already inserted some nonesense in the chain
         | 
| 283 | 
            -
                  headers.delete('ETag')
         | 
| 284 | 
            -
                  headers.delete('Date')
         | 
| 285 | 
            -
                  headers['Cache-Control'] = 'must-revalidate, private, max-age=0'
         | 
| 286 314 | 
             
            			[status, headers, body]
         | 
| 287 315 | 
             
                ensure
         | 
| 288 316 | 
             
                  # Make sure this always happens
         | 
| 289 317 | 
             
                  current = nil
         | 
| 290 318 | 
             
            		end
         | 
| 291 319 |  | 
| 320 | 
            +
                def inject(fragment, script)
         | 
| 321 | 
            +
                  fragment.sub(/<\/body>/i, script + "</body>") 
         | 
| 322 | 
            +
                end
         | 
| 323 | 
            +
             | 
| 292 324 | 
             
                def dump_env(env)
         | 
| 293 325 | 
             
                  headers = {'Content-Type' => 'text/plain'}
         | 
| 294 326 | 
             
                  body = "" 
         | 
| @@ -298,7 +330,7 @@ module Rack | |
| 298 330 | 
             
                  [200, headers, [body]]
         | 
| 299 331 | 
             
                end
         | 
| 300 332 |  | 
| 301 | 
            -
                def help
         | 
| 333 | 
            +
                def help(category = nil)
         | 
| 302 334 | 
             
                  headers = {'Content-Type' => 'text/plain'}
         | 
| 303 335 | 
             
                  body = "Append the following to your query string:
         | 
| 304 336 |  | 
| @@ -309,24 +341,48 @@ module Rack | |
| 309 341 | 
             
              pp=full-backtrace : enable full backtrace for SQL executed
         | 
| 310 342 | 
             
              pp=sample : sample stack traces and return a report isolating heavy usage (requires the stacktrace gem)
         | 
| 311 343 | 
             
            "
         | 
| 312 | 
            -
                   | 
| 344 | 
            +
                  if (category == :stacktrace)
         | 
| 345 | 
            +
                    body = "pp=stacktrace requires the stacktrace gem - add gem 'stacktrace' to your Gemfile"
         | 
| 346 | 
            +
                  end
         | 
| 347 | 
            +
                
         | 
| 313 348 | 
             
                  [200, headers, [body]]
         | 
| 314 349 | 
             
                end
         | 
| 315 350 |  | 
| 316 351 | 
             
                def analyze(traces, page_struct)
         | 
| 317 352 | 
             
                  headers = {'Content-Type' => 'text/plain'}
         | 
| 318 353 | 
             
                  body = "Collected: #{traces.count} stack traces. Duration(ms): #{page_struct.duration_ms}"
         | 
| 354 | 
            +
             | 
| 355 | 
            +
                  seen = {}
         | 
| 356 | 
            +
                  fulldump = ""
         | 
| 319 357 | 
             
                  traces.each do |trace| 
         | 
| 320 | 
            -
                     | 
| 358 | 
            +
                    fulldump << "\n\n"
         | 
| 359 | 
            +
                    distinct = {}
         | 
| 321 360 | 
             
                    trace.each do |frame|
         | 
| 322 | 
            -
                       | 
| 361 | 
            +
                      name = "#{frame.klass} #{frame.method}"
         | 
| 362 | 
            +
                      unless distinct[name]
         | 
| 363 | 
            +
                        distinct[name] = true
         | 
| 364 | 
            +
                        seen[name] ||= 0
         | 
| 365 | 
            +
                        seen[name] += 1
         | 
| 366 | 
            +
                      end
         | 
| 367 | 
            +
                      fulldump << name << "\n"
         | 
| 368 | 
            +
                    end
         | 
| 369 | 
            +
                  end
         | 
| 370 | 
            +
             | 
| 371 | 
            +
                  body << "\n\nStack Trace Analysis\n"
         | 
| 372 | 
            +
                  seen.to_a.sort{|x,y| y[1] <=> x[1]}.each do |name, count|
         | 
| 373 | 
            +
                    if count > traces.count / 10
         | 
| 374 | 
            +
                      body << "#{name} x #{count}\n"
         | 
| 323 375 | 
             
                    end
         | 
| 324 376 | 
             
                  end
         | 
| 377 | 
            +
                  
         | 
| 378 | 
            +
                  body << "\n\n\nRaw traces \n"
         | 
| 379 | 
            +
                  body << fulldump
         | 
| 380 | 
            +
             | 
| 325 381 | 
             
                  [200, headers, [body]]
         | 
| 326 382 | 
             
                end
         | 
| 327 383 |  | 
| 328 384 | 
             
                def ids_json(env)
         | 
| 329 | 
            -
                  ids = [current | 
| 385 | 
            +
                  ids = [current.page_struct["Id"]] + (@storage.get_unviewed_ids(user(env)) || [])
         | 
| 330 386 | 
             
                  ::JSON.generate(ids.uniq)
         | 
| 331 387 | 
             
                end
         | 
| 332 388 |  | 
| @@ -345,9 +401,9 @@ module Rack | |
| 345 401 | 
             
            			showChildren = false
         | 
| 346 402 | 
             
            			maxTracesToShow = 10
         | 
| 347 403 | 
             
            			showControls = false
         | 
| 348 | 
            -
            			currentId = current | 
| 404 | 
            +
            			currentId = current.page_struct["Id"]
         | 
| 349 405 | 
             
            			authorized = true
         | 
| 350 | 
            -
             | 
| 406 | 
            +
            			useExistingjQuery = @config.use_existing_jquery
         | 
| 351 407 | 
             
            			# TODO : cache this snippet 
         | 
| 352 408 | 
             
            			script = IO.read(::File.expand_path('../html/profile_handler.js', ::File.dirname(__FILE__)))
         | 
| 353 409 | 
             
            			# replace the variables
         | 
| @@ -357,52 +413,13 @@ module Rack | |
| 357 413 | 
             
            			end
         | 
| 358 414 | 
             
            			# replace the '{{' and '}}''
         | 
| 359 415 | 
             
            			script.gsub!(/\{\{/, '{').gsub!(/\}\}/, '}')
         | 
| 360 | 
            -
            			current | 
| 416 | 
            +
            			current.inject_js = false
         | 
| 361 417 | 
             
            			script
         | 
| 362 418 | 
             
            		end
         | 
| 363 419 |  | 
| 364 420 | 
             
            		# cancels automatic injection of profile script for the current page
         | 
| 365 421 | 
             
            		def cancel_auto_inject(env)
         | 
| 366 | 
            -
            		  current | 
| 367 | 
            -
            		end
         | 
| 368 | 
            -
             | 
| 369 | 
            -
            		# perform a profiling step on given block
         | 
| 370 | 
            -
            		def self.step(name)
         | 
| 371 | 
            -
                  if current
         | 
| 372 | 
            -
                    old_timer = current['current_timer']
         | 
| 373 | 
            -
                    new_step = RequestTimerStruct.new(name, current['page_struct'])
         | 
| 374 | 
            -
                    current['current_timer'] = new_step
         | 
| 375 | 
            -
                    new_step['Name'] = name
         | 
| 376 | 
            -
                    start = Time.now
         | 
| 377 | 
            -
                    result = yield if block_given?
         | 
| 378 | 
            -
                    new_step.record_time((Time.now - start)*1000)
         | 
| 379 | 
            -
                    old_timer.add_child(new_step)
         | 
| 380 | 
            -
                    current['current_timer'] = old_timer
         | 
| 381 | 
            -
                    result
         | 
| 382 | 
            -
                  else
         | 
| 383 | 
            -
                    yield if block_given?
         | 
| 384 | 
            -
                  end
         | 
| 385 | 
            -
            		end
         | 
| 386 | 
            -
             | 
| 387 | 
            -
                def self.profile_method(klass, method, &blk)
         | 
| 388 | 
            -
                  default_name = klass.to_s + " " + method.to_s
         | 
| 389 | 
            -
                  with_profiling = (method.to_s + "_with_mini_profiler").intern
         | 
| 390 | 
            -
                  without_profiling = (method.to_s + "_without_mini_profiler").intern
         | 
| 391 | 
            -
                  
         | 
| 392 | 
            -
                  klass.send :alias_method, without_profiling, method
         | 
| 393 | 
            -
                  klass.send :define_method, with_profiling do |*args, &orig|
         | 
| 394 | 
            -
                    name = default_name 
         | 
| 395 | 
            -
                    name = blk.bind(self).call(*args) if blk
         | 
| 396 | 
            -
                    ::Rack::MiniProfiler.step name do 
         | 
| 397 | 
            -
                      self.send without_profiling, *args, &orig
         | 
| 398 | 
            -
                    end
         | 
| 399 | 
            -
                  end
         | 
| 400 | 
            -
                  klass.send :alias_method, method, with_profiling
         | 
| 401 | 
            -
                end
         | 
| 402 | 
            -
             | 
| 403 | 
            -
            		def record_sql(query, elapsed_ms)
         | 
| 404 | 
            -
                  c = current
         | 
| 405 | 
            -
            			c['current_timer'].add_sql(query, elapsed_ms, c['page_struct'], c['skip-backtrace'], c['full-backtrace']) if (c && c['current_timer'])
         | 
| 422 | 
            +
            		  current.inject_js = false
         | 
| 406 423 | 
             
            		end
         | 
| 407 424 |  | 
| 408 425 | 
             
            	end
         |