Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions pyinstrument/profiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,5 +114,7 @@ def get_renderer_class(name):
return renderers.ConsoleRenderer
elif name == 'html':
return renderers.HTMLRenderer
elif name == 'json':
return renderers.JSONRenderer
else:
return object_with_import_path(name)
16 changes: 16 additions & 0 deletions pyinstrument/renderers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
import abc
import os
import json
from . import six

class Renderer(object):
Expand Down Expand Up @@ -128,6 +129,21 @@ def render_frame(self, frame):
result += '</div></div>'

return result

def _json_frame(frame):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be a method on the JSONRenderer object?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No problem

return {
'function': frame.function,
'file_path': frame.file_path_short,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the interests of creating a generally useful solution, I'd rather this was called file_path_short, in case we want to add file_path in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool

'line_no': frame.line_no,
'time': frame.time(),
'children': [_json_frame(frame) for frame in frame.children]
}

class JSONRenderer(Renderer):
preferred_recorder = 'time_aggregating'

def render(self, frame):
return json.dumps(_json_frame(frame))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might be nice to add indent=2 to make the output prettier on the terminal

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I though about it: many outputs can generate big outputs so adding spacing chars would increase their size significantly. Maybe this should be another renderer / CLI option?
If you go the UNIX way you can always do: python -m pyinstrument script.py | python -m json.tool

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. I don't agree. JSON is a really verbose format. All those repeated key names! All those numbers written out as strings.

The big advantage of JSON is human-readability - you can look at it and quickly understand it. To strip indentation is to lose that.

If size becomes a meaningful issue the right answer would be to remove frames with tiny durations, or use something like Protobuf.

(Re. piping through python -m json.tool - it's a good idea, but I don't think the burden of a good user experience should be on the user)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, will add



class colors_enabled:
Expand Down