blob: 81f6f10c3866013bc79244334816b3d309955fec [file] [log] [blame]
{% extends "base.html" %}
{% block headstuff %}{% endblock %}
{% block content %}
{% if is_shell %}
<div>
<p>
Welcome to the interactive playground!
Here you can enter and run any Python code and analyze it immediately.
{% if multithread %}
<br>
<b>WARNING!</b> The playground is not thread-safe,
but your app is using threadsafe mode.
Use at your own risk.
{% endif %}
</p>
<form method=POST action=shell>
<input type=hidden name=xsrf_token value={{xsrf_token}}>
<textarea name=script rows=10 cols=80>{{script}}</textarea>
<input type=submit value=Run>
</form>
<hr>
Output:
<pre>{{output}}</pre>
<hr>
Errors:
<pre>{{errors}}</pre>
<hr>
</div>
{% else %}
{% if not record %}
<p>Invalid or stale record key!</p>
{% endif %}
{% endif %}
{% if record %}
<div class="g-section" id="ae-stats-summary">
<dl>
<dt>
<span class="ae-stats-date">{{record.start_time_formatted}}</span><br>
<span class="ae-stats-response ae-stats-response-{{record.http_status}}">
{{record.http_status}}
</span>
</dt>
<dd>
<a {% ifequal record.http_method 'GET' %}target="_new" title="Resubmit the original request to the server" href="{{record.http_path|escape}}{{record.http_query|escape}}" {% endifequal %}>
{{record.http_method|escape}} {{record.http_path|escape}}{{record.http_query|escape}}
</a>
<br>
{{record.user_email|escape}}{% if record.is_admin %}*{% endif %}
real={{record.duration_milliseconds}}ms
api={{record.api_milliseconds}}ms
overhead={{record.overhead_walltime_milliseconds}}ms
cost={{record.combined_rpc_cost_micropennies}}
<br>
billed_ops={{record.combined_rpc_billed_ops}}
</dd>
</dl>
</div>
<div id="ae-stats-details-timeline">
<h2>Timeline</h2>
<div id="ae-body-timeline">
<div id="ae-rpc-chart">[Chart goes here]</div>
</div>
{% if record.individual_stats_size %}
<div id="ae-rpc-traces">
<div class="ae-table-title">
<div class="g-section g-tpl-50-50 g-split">
<div class="g-unit g-first"><h2>RPC Call Traces</h2></div>
<div class="g-unit" id="ae-rpc-expand-all"></div>
</div>
</div>
<table cellspacing="0" cellpadding="0" class="ae-table" id="ae-table-rpc">
<thead>
<tr>
<th>RPC</th>
</tr>
</thead>
{% for t in record.individual_stats_list %}
<tbody id="rpc{{forloop.counter}}">
<tr>
<td>
<span class="goog-inline-block ae-zippy ae-zippy-expand" id="ae-path-requests-{{forloop.counter}}"></span>
@{{t.start_offset_milliseconds}}ms
<b>{{t.service_call_name|escape}}</b>
real={{t.duration_milliseconds}}ms
api={{t.api_milliseconds}}ms
cost={{t.call_cost_microdollars}}
billed_ops=[{{t.billed_ops_str}}]
</td>
</tr>
</tbody>
<tbody>
{% if t.request_data_summary %}
<tr>
<td style="padding-left: 20px"><b>Request:</b> {{t.request_data_summary|escape}}</td>
</tr>
{% endif %}
{% if t.response_data_summary %}
<tr>
<td style="padding-left: 20px"><b>Response:</b> {{t.response_data_summary|escape}}</td>
</tr>
{% endif %}
{% if t.call_stack_size %}
<tr>
<td style="padding-left: 20px"><b>Stack:</b></td>
</tr>
{% for f in t.call_stack_list %}
<tr>
<td style="padding-left: 40px">
<span style="padding-left: 12px; text-indent: -12px" class="goog-inline-block ae-zippy-expand" id="ae-head-stack-{{forloop.parentloop.counter}}-{{forloop.counter}}">&nbsp;</span>
{% if file_url %}<a href="{{file_url}}?f={{f.class_or_file_name|escape}}&n={{f.line_number}}#n{{f.line_number|add:"-10"}}">{% endif %} {{f.class_or_file_name|escape}}:{{f.line_number}}{% if file_url %}</a>{% endif %} {{f.function_name|escape}}()
</td>
</tr>
{% if f.variables_size %}
<tr id="ae-body-stack-{{forloop.parentloop.counter}}-{{forloop.counter}}">
<td style="padding-left: 60px">{% for item in f.variables_list %}{{item.key|escape}} = {{item.value|escape}}<br>{% endfor %}
</td>
</tr>
{% endif %}{# f.variables_size #}
{% endfor %}{# t.call_stack_list #}
{% endif %}{# t.call_stack_size #}
</tbody>
{% endfor %}{# record.individual_stats_list #}
</table>
</div>
{% endif %}{# traces #}
{% endif %}
</div>
{% if rpcstats_by_count %}
<div id="ae-stats-details-rpcstats">
<h2>RPC Stats</h2>
<table cellspacing="0" cellpadding="0" class="ae-table" id="ae-table-rpcstats">
<tbody>
<tr>
<td>service.call</td>
<td align="right">#RPCs</td>
<td align="right">real time</td>
<td align="right">api time</td>
<td align="right">Cost</td>
<td align="right">Billed Ops</td>
</tr>
{% for item in rpcstats_by_count %}
<tr>
<td>{{item.0|escape}}</td>
<td align="right">{{item.1|escape}}</td>
<td align="right">{{item.2}}ms</td>
<td align="right">{{item.3}}ms</td>
<td align="right">{{item.4}}</td>
<td align="right">{{item.5}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}{# rpcstats_by_count #}
{% if record.cgi_env_size %}
<div id="ae-stats-details-cgienv">
<h2>CGI Environment</h2>
<table cellspacing="0" cellpadding="0" class="ae-table" id="ae-table-cgienv">
<tbody>
{% for item in record.cgi_env_list %}
<tr>
<td align="right" valign="top">{{item.key|escape}}=</td>
<td valign="top">{{item.value|escape}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}{# record.cgi_env_size #}
{% if sys.path %}
<div id="ae-stats-details-syspath">
<h2>sys.path</h2>
<table cellspacing="0" cellpadding="0" class="ae-table" id="ae-table-syspath">
<tbody>
<tr>
<td colspan="2">
<i>Note:</i> sys.path is not saved with the request;
this is the <i>current</i> sys.path.
</td>
</tr>
<tr>
</tr>
{% for item in sys.path %}
<tr>
<td align="right" valign="top">{{forloop.counter0}}:</td>
<td valign="top">{{item|escape}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}{# sys.path #}
{% endblock %}
{% block tailstuff %}
<script>
var rpcZippyMaker = new ae.Stats.MakeZippys('ae-table-rpc',
'ae-rpc-expand-all');
var rpcZippys = rpcZippyMaker.getZippys();
{% for t in record.individual_stats_list %}
{% for f in t.call_stack_list %}
{% if f.variables_size %}
new goog.ui.Zippy(
'ae-head-stack-{{forloop.parentloop.counter}}-{{forloop.counter}}',
'ae-body-stack-{{forloop.parentloop.counter}}-{{forloop.counter}}',
false);
{% endif %}
{% endfor %}
{% endfor %}
</script>
<script>
var detailsTabs_ = new ae.Stats.Details.Tabs(['timeline', 'rpcstats',
'cgienv', 'syspath']);
</script>
<script>
function timelineClickHandler(zippyIndex, hash) {
rpcZippyMaker.getExpandCollapse().setExpanded(false);
rpcZippys[zippyIndex].setExpanded(true);
var headlineIndex = parseInt(zippyIndex, 10) + 1;
var zippyLine = document.getElementById('ae-path-requests-' + headlineIndex);
zippyLine.scrollIntoView(true);
}
function renderChart() {
var chart = new Gantt();
{% for t in record.individual_stats_list %}
chart.add_bar('{{t.service_call_name|escape}}',
{{t.start_offset_milliseconds}}, {{t.duration_milliseconds}},
{{t.api_milliseconds}},
'{{t.duration_milliseconds}}ms{% if t.api_milliseconds %} ({{t.api_milliseconds}}ms api){% endif %}',
'javascript:timelineClickHandler(\'{{forloop.counter0}}\');');
{% endfor %}
chart.add_bar('<b>RPC Total</b>', 0, {{real_total}}, {{api_total}},
'{{real_total}}ms{% if api_total %} ({{api_total}}ms api){% endif %}',
'');
chart.add_bar('<b>Grand Total</b>', 0, {{record.duration_milliseconds}}, 0,
'{{record.duration_milliseconds}}ms', '');
document.getElementById('ae-rpc-chart').innerHTML = chart.draw();
}
renderChart();
</script>
{% endblock %}