Skip to content

Commit

Permalink
Merge pull request #8 from boris-42/html_report
Browse files Browse the repository at this point in the history
Html report
  • Loading branch information
boris-42 committed Apr 2, 2015
2 parents 562d371 + cb5b3f5 commit 1ea4d2a
Show file tree
Hide file tree
Showing 14 changed files with 28,400 additions and 14 deletions.
27 changes: 21 additions & 6 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,36 @@ Syntax:

.. code-block::
profimp [import_module_line]
profimp [import_module_line] [--html]
Samples:

.. code-block::
profimp "import re"
or
profimp "import collections"
profimp "from somemoudle import something"
prpfimp --html "import multiprocessing"
Pretty HTML reports
-------------------

if you run prpfimp with --html key you will get pretty html output

.. code-block::
profimp "import collections"
.. image:: doc/source/images/collections_import_trace.png
:alt: American Gothic
:width: 650 px


Results
-------
Raw JSON Results
----------------

In output you will see something like:

Expand Down
Binary file added doc/source/images/collections_import_trace.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 13 additions & 4 deletions profimp/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,15 @@
right decisions.
Syntax:
profimp [import_module_line]
profimp [import_module_line] [--html]
Samples:
profimp "import re"
or
profimp "import collections"
profimp "from somemoudle import something"
prpfimp --html "import multiprocessing"
"""


Expand All @@ -58,6 +59,14 @@ def main():
elif len(sys.argv) == 2:
report = reports.to_json(trace_module(sys.argv[1]))
sys.stdout.write(report)
elif len(sys.argv) == 3:
if "--html" in sys.argv[1:]:
arg_pos = 1 if sys.argv[1] != "--html" else 2
report = reports.to_html(trace_module(sys.argv[arg_pos]))
sys.stdout.write(report)
else:
print_help()
raise SystemExit("Wrong input arguments: %s" % sys.argv)
else:
print_help()
raise SystemExit("Wrong input arguments: %s" % sys.argv)
Expand Down
24 changes: 23 additions & 1 deletion profimp/reports.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,30 @@
# License for the specific language governing permissions and limitations
# under the License.

import os
import json


def _normalize(results, started_at=None):
started_at = started_at or results["started_at"]

results["started_at"] = (results["started_at"] - started_at) * 1000.0
results["finished_at"] = (results["finished_at"] - started_at) * 1000.0

for child in results["children"]:
_normalize(child, started_at=started_at)

return results


def to_json(results):
return json.dumps(results.to_dict(), indent=2)
return json.dumps(_normalize(results.to_dict()), indent=2)


def to_html(results):
template_path = os.path.join(
os.path.dirname(__file__), "templates", "report.tpl")

with open(template_path) as html_template:
report = html_template.read()
return report.replace("{{DATA}}", to_json(results))
162 changes: 162 additions & 0 deletions profimp/templates/report.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
<!doctype html>
<html ng-app="Application">

<head>
<script> var TraceData = {{DATA}} </script>

<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.min.js"></script>
<script src="https://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.11.0.js"></script>

<style>
.trace {
min-width: 900px;
}
.trace tr.active-true {
background-color: #D9EDF7!important;
}
.trace tr td {
white-space: nowrap;
padding: 2px;
border-right: 1px solid #eee;
}
.trace tr td.level{
width: 100px;
}
.import_line{
width: 450px;
max-width: 450px;
overflow: scroll;
}
.import_line span{
font-size: 10px;
}
.trace .level {
width: 10%;
font-weight: bold;
}
.bold {
font-weight: bold;
}
div.duration {
width: 25px;
margin: 0px;
padding: 0px;
background-color: #C6F3DD;
border-radius: 4px;
font-size: 10px;
}
div.duration div{
padding-top: 4px;
padding-bottom: 4px;
text-align: center;
}
</style>
<script type="text/ng-template" id="tree_item_renderer.html">
<div>
<table class="trace cursor_pointer_on_hover">
<tr class="active-{{hover}}"
ng-init="hover=false"
ng-mouseenter="hover=true"
ng-mouseleave="hover=false">
<td class="level"
style="padding-left:{{data.level * 5}}px;">
<button type="button"
class="btn btn-default btn-xs"
ng-disabled="data.is_leaf"
ng-click="data.hide_children=!data.hide_children">
<span class="glyphicon glyphicon-{{ (data.is_leaf) ? 'minus' : ((data.hide_children) ? 'plus': 'minus')}}"></span>
{{data.level || 0}}
</button>
</td>
<td class="{{ is_important(data) ? 'bold' : ''}} import_line" >
<span>{{data.input_line_prefix}} {{data.import_line}}</span>
</td>
<td ng-click="display(data);" class="text-center">
<div class="duration" style="width: {{get_width(data)}}%; margin-left: {{get_started(data)}}%">
<div>{{data.duration.toFixed(2)}} ms</div>
</div>
</td>
</tr>
</table>
<div ng-hide="data.hide_children">
<div ng-repeat="data in data.children"
ng-include="'tree_item_renderer.html'">
</div>
</div>
</div>
</script>
<script>
angular.module("Application", ['ui.bootstrap']);
function ProfilerCtlr($scope, $modal) {
var convert_input = function(input, full_duration){
input.is_leaf = !input.children.length
input.input_line_prefix = Array(input.level + 1).join("-")
input.hide_children = full_duration > 10 * input.duration ? true : false;
for (var i = 0; i < input.children.length; i++)
convert_input(input.children[i], full_duration);
return input;
}
$scope.get_width = function(data){
var duration = (data.duration) * 100.0 / $scope.tree[0].duration;
return (duration >= 0.5) ? duration : 0.5;
}
$scope.get_started = function(data) {
return data.started_at * 100.0 / $scope.tree[0].duration;
}
$scope.is_important = function(data) {
// we assume that point is important if import takes more then 10 ms
return data.duration > 10;
}
$scope.tree = [convert_input(TraceData, TraceData.duration)];
}
</script>
</head>
<body>
<div ng-controller="ProfilerCtlr">
<table>
</table>
<table class="trace">
<tr class="bold text-left" style="border-bottom: solid 1px gray">
<td class="level">Level</td>
<td class="import_line">Import line</td>
<td>Duration</td>
</tr>
</table>
<div ng-repeat="data in tree" ng-include="'tree_item_renderer.html'"></div>
</div>
</body>
</html>
Loading

0 comments on commit 1ea4d2a

Please sign in to comment.