<!DOCTYPE html>
<html>
<head>
    <title>Locust for {{ locustfile }}</title>
    <link rel="stylesheet" type="text/css" href="./static/css/application.css?v={{ version }}" media="screen">
    <link rel="shortcut icon" href="./static/img/favicon.ico" type="image/x-icon"/>
    {% block extended_head %}
    {% endblock extended_head %}
</head>
<body class="{{state}}">
    <div class="top">
        <div class="top-content container">
            <img src="./static/img/logo.png?v={{ version }}" class="logo" />
            <div class="boxes">
                <div class="top_box box_url">
                    <div class="label">HOST</div>
                    <div class="value" id="host_url">
                        {{ host or "" }}
                    </div>
                </div>
                <div class="top_box box_status">
                    <div class="label">STATUS</div>
                    <div class="value" id="status_text">
                        {{state}}
                    </div>
                    <div class="user_count">
                        <span id="userCount">{{user_count}}</span> users
                    </div>
                    <a href="#" class="new-test" id="new-test">New test</a>
                    <a href="#" class="edit-test" id="edit-test">Edit</a>
                </div>
                {% if is_distributed %}
                    <div class="top_box box_workers" id="box_workers">
                        <div class="label">WORKERS</div>
                        <div class="value" id="workerCount">{{worker_count}}</div>
                    </div>
                {% endif %}
                <div class="top_box box_rps box_running" id="box_rps">
                    <div class="label">RPS</div>
                    <div class="value" id="total_rps">0</div>
                </div>
                <div class="top_box box_fail box_running" id="box_fail">
                    <div class="label">FAILURES</div>
                    <div class="value"><span id="fail_ratio"></span>%</div>
                </div>
                <div class="top_box box_stop box_running" id="box_stop">
                    <a href="./stop" class="stop-button"><i></i>STOP</a>
                    <a href="./stats/reset" class="reset-button">Reset<br>Stats</a>
                </div>
            </div>
            <div style="clear:both;"></div>
        </div>
    </div>
    
    <div class="dialogs">
        <div class="dialog start" id="start">
            <div style="position:relative;">
                <a href="#" class="close_link">Close</a>
            </div>
            <div class="padder">
                <h2>Start new load test</h2>
                <form action="./swarm" method="POST" id="swarm_form">
                    {% if is_shape %}
                        <label for="user_count">Number of users <span style="color:#8a8a8a;">(peak concurrency)</span></label>
                        <input type="text" name="user_count" id="user_count" class="val_disabled" value="-" disabled="disabled" title="Disabled for tests using LoadTestShape class"/><br>
                        <input type="hidden" name="user_count" id="user_count" value="0"/><br>
                        <label for="spawn_rate">Spawn rate <span style="color:#8a8a8a;">(users started/second)</span></label>
                        <input type="text" name="spawn_rate" id="spawn_rate" class="val_disabled" value="-" disabled="disabled" title="Disabled for tests using LoadTestShape class"/><br>
                        <input type="hidden" name="spawn_rate" id="spawn_rate" value="0"/><br>
                    {% else %}
                        <label for="user_count">Number of users <span style="color:#8a8a8a;">(peak concurrency)</span></label>
                        <input type="text" name="user_count" id="user_count" class="val" value="{{ num_users or "1" }}" onfocus="this.select()"/><br>
                        <label for="spawn_rate">Spawn rate <span style="color:#8a8a8a;">(users started/second)</span></label>
                        <input type="text" name="spawn_rate" id="spawn_rate" class="val" value="{{ spawn_rate or "1" }}" onfocus="this.select()"/><br>
                    {% endif %}
                    <label for="host">
                        Host <span style="color:#8a8a8a;">(e.g. http://www.example.com)</span>
                        {% if override_host_warning %}
                            <span style="color:#8a8a8a; font-size:12px;">(setting this will override the host on all User classes)</span></label>
                        {% endif %}
                    </label>
                    <input type="text" name="host" id="host" class="val" autocapitalize="off" autocorrect="off" value="{{ host  or "" }}" onfocus="this.select()"/><br>
                    {% if extra_options %}<label>Custom parameters:</label>{% endif %}
                    {% for key, value in extra_options.items() %}
                        {% if not ((value is none) or (value is boolean)) %}
                            <label for="{{key}}">{{key}}</label>
                            <input type="text" name="{{key}}" id="{{key}}" class="val" value="{{value}}" /><br>
                        {% endif %}
                    {% endfor %}
                    {% set glob={'header_printed': False} %}
                    {% for key, value in extra_options.items() %}
                        {% if (value is none) or (value is boolean) %}
                            {% if not glob.header_printed %}
                                The following custom parameters can't be set in the Web UI, because it is a boolean or None type:<br>
                                {% set _ = glob.update({'header_printed':True}) %}
                            {% endif %}
                            {{key}}<br>
                        {% endif %}
                    {% endfor %}
                    <button type="submit">Start swarming</button>
                </form>
                <div style="clear:right;"></div>
            </div>
        </div>

        <div class="dialog edit" id="edit">
            <div style="position:relative;">
                <a href="#" class="close_link">Close</a>
            </div>
            <div class="padder">
                <h2>Edit running load test</h2>
                <form action="./swarm" method="POST" id="edit_form">
                    {% if is_shape %}
                        <label for="new_user_count">Number of users (peak concurrency)</label>
                        <input type="text" name="user_count" id="new_user_count" class="val_disabled"  value="-" disabled="disabled" title="Disabled for tests using LoadTestShape class"/><br>
                        <label for="spawn_rate">Spawn rate <span style="color:#8a8a8a;">(users added/stopped per second)</span></label>
                        <input type="text" name="spawn_rate" id="new_spawn_rate" class="val_disabled"  value="-" disabled="disabled" title="Disabled for tests using LoadTestShape class"/><br>
                    {% else %}
                        <label for="new_user_count">Number of users (peak concurrency)</label>
                        <input type="text" name="user_count" id="new_user_count" class="val"  value="{{ num_users or "1" }}" onfocus="this.select()"/><br>
                        <label for="spawn_rate">Spawn rate <span style="color:#8a8a8a;">(users added/stopped per second)</span></label>
                        <input type="text" name="spawn_rate" id="new_spawn_rate" class="val"  value="{{ spawn_rate or "1" }}" onfocus="this.select()"/><br>
                    {% endif %}
                    {% if is_shape %}
                        <button type="submit" disabled>Start swarming</button>
                    {% else %}
                        <button type="submit">Start swarming</button>
                    {% endif %}
                </form>
                <div style="clear:right;"></div>
            </div>
        </div>
    </div>
    
    <div class="main" id="main">
        <nav class="menu">
            <ul class="tabs container">
                <li><a href="#">Statistics</a></li>
                <li><a href="#" class="chart-tab-link">Charts</a></li>
                <li><a href="#">Failures</a></li>
                <li><a href="#">Exceptions</a></li>
                <li><a href="#">Current ratio</a></li>
                <li><a href="#">Download Data</a></li>
                {% if is_distributed %}
                    <li><a href="#">Workers</a></li>
                {% endif %}
                {% block extended_tabs %}{% endblock extended_tabs %}
            </ul>
        </nav>
        <div class="panes container">
            <div style="display:none;">
                <table id="stats" class="stats">
                    <thead>
                        <tr>
                            <th class="stats_label" href="#" data-sortkey="method">Type</th>
                            <th class="stats_label" href="#" data-sortkey="name">Name</th>
                            <th class="stats_label numeric nowrap" href="#" data-sortkey="num_requests" title="Number of successful requests"># Requests</th>
                            <th class="stats_label numeric nowrap" href="#" data-sortkey="num_failures" title="Number of failures"># Fails</th>
                            <th class="stats_label numeric" href="#" data-sortkey="median_response_time" title="Median response time">Median (ms)</th>
                            <th class="stats_label numeric" href="#" data-sortkey="ninetieth_response_time" title="Ninetieth percentile response time, because the response time greater than 100ms is rounded, you may see it greater than the max response time">90%ile (ms)</th>
                            <th class="stats_label numeric" href="#" data-sortkey="ninety_ninth_response_time"
                                title="Ninety-ninth percentile response time, because the response time greater than 100ms is rounded, you may see it greater than the max response time">
                                99%ile (ms)</th>
                            <th class="stats_label numeric" href="#" data-sortkey="avg_response_time" title="Average response time">Average (ms)</th>
                            <th class="stats_label numeric" href="#" data-sortkey="min_response_time" title="Min response time">Min (ms)</th>
                            <th class="stats_label numeric" href="#" data-sortkey="max_response_time" title="Max response time">Max (ms)</th>
                            <th class="stats_label numeric" href="#" data-sortkey="avg_content_length" title="Average response size">Average size (bytes)</th>
                            <th class="stats_label numeric" href="#" data-sortkey="current_rps" title="Current number of requests per second">Current RPS</th>
                            <th class="stats_label numeric" href="#" data-sortkey="current_fail_per_sec" title="Current number of failures per second">Current Failures/s</th>
                        </tr>
                    </thead>
                    <tbody>
                    </tbody>
                </table>
            </div>
            <div id="charts" style="display:none;">
                <div class="charts-container"></div>
            </div>
            <div style="display:none;">
                <table id="errors" class="stats">
                    <thead>
                        <th class="error_count stats_label" data-sortkey="occurrences"># fails</th>
                        <th class="stats_label" href="#" data-sortkey="method">Method</th>
                        <th class="stats_label" href="#" data-sortkey="name">Name</th>
                        <th class="error_type stats_label" data-sortkey="error">Type</th>
                    </thead>
                    <tbody>
                    </tbody>
                </table>
            </div>
            <div style="display:none;">
                <table id="exceptions" class="stats">
                    <thead>
                        <th class="exception_occurrences stats_label"># occurrences</th>
                        <th class="exception_traceback stats_label">Traceback</th>
                    </thead>
                    <tbody>
                    </tbody>
                </table>
            </div>
            <div id="tasks" style="display:none;">
                <p>Script: <span>{{ locustfile }}</span></p>
                <div class="tasks" data-tasks="{{tasks}}"></div>
            </div>
            <div style="display:none;">
                <div style="margin-top:20px;">
                    <a href="./stats/requests/csv">Download request statistics CSV</a><br>
                    {% if stats_history_enabled %}
                        <a href="./stats/requests_full_history/csv">Download full request statistics history CSV</a><br>
                    {% endif %}
                    <a href="./stats/failures/csv">Download failures CSV</a><br>
                    <a href="./exceptions/csv">Download exceptions CSV</a><br>
                    <a href="./stats/report" target="_blank">Download Report</a><br>
                </div>
            </div>
            {% if is_distributed %}
                <div style="display:none;">
                    <table class="stats" id="workers">
                        <thead>
                            <tr>
                                <th class="stats_label" href="#" data-sortkey="id">Worker</th>
                                <th class="stats_label" href="#" data-sortkey="state">State</th>
                                <th class="stats_label numeric" href="#" data-sortkey="user_count" title="Number of users on this worker"># users</th>
                                <th class="stats_label numeric" href="#" data-sortkey="cpu_usage" title="CPU usage of process">CPU usage</th>
                                <th class="stats_label numeric" href="#" data-sortkey="memory_usage" title="Memory usage of process">Memory usage</th>
                            </tr>
                        </thead>
                        <tbody>
                        </tbody>
                    </table>
                </div>
            {% endif %}
            {% block extended_panes %}{% endblock extended_panes %}
        </div>

        <div class="about" style="display:none;">
            <div style="position:relative;">
                <a href="#" class="close_link">Close</a>
            </div>
            <div class="padder">
                <h1>About</h1>
                <p>
                    The original idea for Locust was Carl Byström's who made a first proof of concept in June 2010.
                    Jonatan Heyman picked up Locust in January 2011, implemented the current concept of Locust classes
                    and made it work distributed across multiple machines.
                </p>
                <p>
                    Jonatan, Carl and Joakim Hamrén has continued the development of Locust at their job,
                    ESN Social Software, who have adopted Locust as an inhouse Open Source project.
                </p>

                <h1>Authors and Copyright</h1>
                <a href="http://cgbystrom.com/">Carl Byström</a> (<a href="https://twitter.com/cgbystrom/">@cgbystrom</a>)<br>
                <a href="http://heyman.info/">Jonatan Heyman</a> (<a href="https://twitter.com/jonatanheyman/">@jonatanheyman</a>)<br>
                Joakim Hamrén (<a href="https://twitter.com/Jahaaja/">@jahaaja</a>)<br>
                <a href="http://esn.me/">ESN Social Software</a> (<a href="https://twitter.com/uprise_ea/">@uprise_ea</a>)<br>
                Hugo Heyman (<a href="https://twitter.com/hugoheyman/">@hugoheyman</a>)


                <h1>License</h1>
                Open source licensed under the MIT license.

                <h2>Version <a href="https://github.com/locustio/locust/releases/tag/{{version}}">{{version}}</a></h2>
                <br>
                <a href="https://locust.io/">https://locust.io</a>
            </div>
        </div>
    </div>
    <nav class="footer">
        <div class="container">
            <a href="#" onclick="$('.about').fadeIn();">About</a>
        </div>
    </nav>
    <script type="text/javascript" src="./static/jquery-1.11.3.min.js"></script>
    <script type="text/javascript" src="./static/jquery.jqote2.min.js"></script>
    <script type="text/javascript" src="./static/jquery.tools.min.js"></script>
    <!-- echarts from https://github.com/ecomfe/echarts -->
    <script type="text/javascript" src="./static/echarts.common.min.js"></script>
    <!-- vintage theme of echarts -->
    <script type="text/javascript" src="./static/vintage.js"></script>
    <script type="text/x-jqote-template" id="stats-template">
        <![CDATA[
        <tr class="<%=(this.is_aggregated ? "total" : "")%>">
            <td><%= (this.method ? this.method : "") %></td>
            <td class="name" title="<%= this.name %>"><%= this.safe_name %></td>
            <td class="numeric"><%= this.num_requests %></td>
            <td class="numeric"><%= this.num_failures %></td>
            <td class="numeric"><%= Math.round(this.median_response_time) %></td>
            <td class="numeric"><%= Math.round(this.ninetieth_response_time) %></td>
            <td class="numeric"><%= Math.round(this.ninety_ninth_response_time) %></td>
            <td class="numeric"><%= Math.round(this.avg_response_time) %></td>
            <td class="numeric"><%= this.min_response_time %></td>
            <td class="numeric"><%= this.max_response_time %></td>
            <td class="numeric"><%= Math.round(this.avg_content_length) %></td>
            <td class="numeric"><%= Math.round(this.current_rps*100)/100 %></td>
            <td class="numeric"><%= Math.round(this.current_fail_per_sec*100)/100 %></td>
        </tr>
        <% alternate = !alternate; %>
        ]]>
    </script>
    <script type="text/x-jqote-template" id="errors-template">
        <![CDATA[
        <tr>
            <td><%= this.occurrences %></td>
            <td><%= this.method %></td>
            <td><%= this.name %></td>
            <td><%= function(e) { return e.replace("<", "&lt;"); }(this.error) %></td>
        </tr>
        <% alternate = !alternate; %>
        ]]>
    </script>
    <script type="text/x-jqote-template" id="exceptions-template">
        <![CDATA[
        <tr>
            <td class="occurrences"><%= this.count %></td>
            <td class="traceback" title="Occurred on: <%= this.nodes %>"><%= function(e) { return e.replace("<", "&lt;"); }(this.traceback) %>
<%= function(e) { return e.replace("<", "&lt;"); }(this.msg) %></td>
        </tr>
        <% alternate = !alternate; %>
        ]]>
    </script>
    <script type="text/x-jqote-template" id="worker-template">
        <![CDATA[
        <tr class="<%=(this.name == "Total" ? "total" : "")%>">
            <td><%= this.id %></td>
            <td><%= this.state %></td>
            <td class="numeric"><%= this.user_count %></td>
            <td class="numeric"><%= this.cpu_usage %>%</td>
            <td class="numeric"><%= formatBytes(this.memory_usage) %></td>
        </tr>
        <% alternate = !alternate; %>
        ]]>
    </script>
    <script type="text/javascript">
        {% include 'stats_data.html' %}
    </script>
    <script type="text/javascript" src="./static/chart.js?v={{ version }}"></script>
    <script type="text/javascript" src="./static/locust.js?v={{ version }}"></script>
    <script type="text/javascript" src="./static/tasks.js?v={{ version }}"></script>
    <script type="text/javascript">
        function updateTasksWithTimeout() {
            fillTasksFromRequest()
            setTimeout(updateTasksWithTimeout, 1000);
        }
        updateTasksWithTimeout()
    </script>
    {% block extended_script %}
    {% endblock extended_script %}
</body>
</html>
