blob: 33822f3056d341d150cff9653a8de18619c3b4ab [file] [log] [blame]
{% extends "base.html" %}
{% block head %}
<title>Anomaly Detection Function Debugger</title>
<link type="text/css" rel="stylesheet" href="{{static_dir}}/main_style.css">
<script src="{{static_dir}}/jquery_flot_bundle.js"></script>
<script type="text/javascript">CLOSURE_NO_DEPS = true;</script>
<style>
/* The content container contains all the content after the title. */
#content {
margin-left: 20px;
}
/* This class is applied to segment endpoint revision labels. */
.label {
background-color: white;
border: 2px solid #f90;
padding: 2px;
position: absolute;
z-index: 1000;
}
code {
font-weight: bold;
}
</style>
{% endblock %}
{% block content %}
<h1>Anomaly Detection Function Debugger</h1>
<div id="content">
<p>This page shows the results of running the anomaly detection function
on some test data for some anomaly threshold configuration.</p>
{% if plot_data and lookup %}
<p>The test data series is shown in <strong
style="color:#666">grey</strong>. The segment and segment endpoints
are shown in <strong style="color:#f90">orange</strong>; if a
revision is specified, a <strong style="color:blue">blue</strong>
line is also shown indicating the position of the revision.
Above each detected anomaly is a label showing the revision number
and percent change from the median before the anomaly to the median
after the anomaly.</p>
<div id="plot" style="width: 800px; height: 400px"></div>
{% endif %}
{% if error %}
<p class="error">{{error}}</p>
{% endif %}
<!-- Form for changing query parameters. -->
<form method="GET">
<table>
<tr>
<td><label>Test path:</label></td>
<td><input type="text" name="test_path" size="100" value="{{test_path}}"></td>
</tr>
<tr>
<td><label>Target revision:</label></td>
<td><input type="text" name="rev" placeholder="280000" value="{{rev}}"></td>
</tr>
<tr>
<td><label>Number of points before:</label></td>
<td><input type="text" name="num_before" placeholder="50" value="{{num_before}}"></td>
</tr>
<tr>
<td><label>Number of points after:</label></td>
<td><input type="text" name="num_after" placeholder="10" value="{{num_after}}"></td>
</tr>
</table>
<p>Sheriff: {{sheriff_name}}</p>
<label>Threshold configuration: {{config_name}}<br>
<textarea name="config" rows="7" cols="60">{{config_json|safe}}</textarea>
</label>
<input type="submit" value="Update">
</form>
<h2>About the threshold parameters</h2>
<ul>
<li><code>max_window_size</code> is the number of points that's
analyzed at once, aka the "window". A larger window size generally means
that more points before a change-point are considered. The window size
must be at least twice as big as the <code>min_segment_size</code>.</li>
<li><code>min_segment_size</code> determines how many points must
be on either side of the change-point before an alert is fired. A
larger value makes it less sensitive to noise, but it also increases
the time before an alert is fired.</li>
<li><code>min_relative_change</code> is the minimum "regression size"
that's reported. For example, to disallow alerts for a change of less
than 5%, this can be set to 0.05.</li>
<li><code>min_absolute_change</code> sets a threshold on the absolute
numerical difference before and after an anomaly.</li>
<li><code>multiple_of_std_dev</code> is the only threshold
that directly takes noise into account. It was originally set
to 3.0 because, if the points within each "segment" have a normal
distribution, then a new point that is more than 3 standard deviations
from the mean has a 0.03 probability of belonging to that segment,
which strongly indicates that should belong to a new segment.
In general, a higher value means less sensitivity to noise.</li>
</ul>
{% if csv_url %}
<p><a href="{{csv_url}}">Download data as CSV</a></p>
{% endif %}
{% if graph_url %}
<p><a href="{{graph_url}}">See graph</a></p>
{% endif %}
{% if stored_anomalies %}
<h3>Recent Anomaly entities in the datastore for this test:</h3>
<table border="1">
<thead>
<tr>
<th>End Revision</th>
<th>Bug ID</th>
<th>Median before anomaly</th>
<th>Median after anomaly</th>
<th>Percent changed</th>
<th>Timestamp</th>
</tr>
</thead>
<tbody>
{% for alert in stored_anomalies %}
<tr>
<td>{{alert.revision}}</td>
<td>{{alert.bug_id}}</td>
<td>{{alert.median_before}}</td>
<td>{{alert.median_after}}</td>
<td>{{alert.percent_changed}}</td>
<td>{{alert.timestamp}}</td>
</tr>
{% endfor %}
</table>
{% endif %}
</div>
{% if plot_data and lookup %}
<script src="{{static_dir}}/debug_alert_bin.js"></script>
<script>
// Array with data series in Flot format. Expected series are:
// [0] Chart data series.
// [1] Anomaly points.
// [2..] Segments and their medians.
var DATA = {{plot_data|safe}};
// Map of indexes to revision numbers.
var LOOKUP = {{lookup|safe}};
// Information returned from the anomaly detection algorithm.
var ANOMALIES = {{anomalies|safe}};
{% if rev %}var REVISION = {{rev}};{% endif %}
</script>
{% endif %}
{% endblock %}