{{ define "content" }}

<p>
    This information is gathered from the Go runtime and represents the ongoing memory consumption
    of this process. Please refer to the <a href="https://golang.org/pkg/runtime/#MemStats">Go documentation on the MemStats type</a>
    for more information about all of these values.
</p>

<table>
    <thead>
    <tr>
        <th>Counter</th>
        <th>Value</th>
        <th>Description</th>
    </tr>
    </thead>
    <tbody>
    <tr>
        <td>HeapInuse</td>
        <td id="HeapInuse">{{.HeapInuse}} bytes</td>
        <td>Bytes in in-use spans.</td>
    </tr>

    <tr>
        <td>Total Alloc</td>
        <td id="TotalAlloc">{{.TotalAlloc}} bytes</td>
        <td>Cumulative bytes allocated for heap objects.</td>
    </tr>

    <tr>
        <td>Sys</td>
        <td id="Sys">{{.Sys}} bytes</td>
        <td>Total bytes of memory obtained from the OS.</td>
    </tr>

    <tr>
        <td>Lookups</td>
        <td id="Lookups">{{.Lookups}} lookups</td>
        <td>Number of pointer lookups performed by the runtime.</td>
    </tr>

    <tr>
        <td>Mallocs</td>
        <td id="Mallocs">{{.Mallocs}} objects</td>
        <td>Cumulative count of heap objects allocated.</td>
    </tr>

    <tr>
        <td>Frees</td>
        <td id="Frees">{{.Frees}} objects</td>
        <td>Cumulative count of heap objects freed.</td>
    </tr>

    <tr>
        <td>Live</td>
        <td id="Live">0 objects</td>
        <td>Count of live heap objects.</td>
    </tr>

    <tr>
        <td>HeapAlloc</td>
        <td id="HeapAlloc">{{.HeapAlloc}} bytes</td>
        <td>Allocated heap objects.</td>
    </tr>

    <tr>
        <td>HeapSys</td>
        <td id="HeapSys">{{.HeapSys}} bytes</td>
        <td>Heap memory obtained from the OS.</td>
    </tr>

    <tr>
        <td>HeapIdle</td>
        <td id="HeapIdle">{{.HeapIdle}} bytes</td>
        <td>Bytes in idle (unused) spans.</td>
    </tr>

    <tr>
        <td>HeapReleased</td>
        <td id="HeapReleased">{{.HeapReleased}} bytes</td>
        <td>Physical memory returned to the OS.</td>
    </tr>

    <tr>
        <td>HeapObjects</td>
        <td id="HeapObjects">{{.HeapObjects}} objects</td>
        <td>Number of allocated heap objects.</td>
    </tr>

    <tr>
        <td>StackInuse</td>
        <td id="StackInuse">{{.StackInuse}} bytes</td>
        <td>Bytes in stack spans.</td>
    </tr>

    <tr>
        <td>StackSys</td>
        <td id="StackSys">{{.StackSys}} bytes</td>
        <td>Stack memory obtained from the OS.</td>
    </tr>

    <tr>
        <td>NextGC</td>
        <td id="NextGC">{{.NextGC}} bytes</td>
        <td>Target heap size of the next GC cycle.</td>
    </tr>

    <tr>
        <td>LastGC</td>
        <td id="LastGC"></td>
        <td>The time the last garbage collection finished.</td>
    </tr>

    <script>
        // we do this so there's a useful date in the table, which avoids things shifting around during initial paint
        let d = new Date().toLocaleString();
        document.getElementById("LastGC").innerText = d;
    </script>

    <tr>
        <td>PauseTotalNs</td>
        <td id="PauseTotalNs">{{.PauseTotalNs}} ns</td>
        <td>Cumulative time spent in GC stop-the-world pauses.</td>
    </tr>

    <tr>
        <td>NumGC</td>
        <td id="NumGC">{{.NumGC}} GC cycles</td>
        <td>Completed GC cycles.</td>
    </tr>

    <tr>
        <td>NumForcedGC</td>
        <td id="NumForcedGC">{{.NumForcedGC}} GC cycles</td>
        <td>GC cycles that were forced by the application calling the GC function.</td>
    </tr>

    <tr>
        <td>GCCPUFraction</td>
        <td id="GCCPUFraction"></td>
        <td>Fraction of this program's available CPU time used by the GC since the program started.</td>
    </tr>
    </tbody>
</table>

<br>
<button class="btn btn-istio" onclick="forceCollection()">Force Garbage Collection</button>

{{ template "last-refresh" .}}

<script>
    "use strict";

    function refreshMemStats() {
        let url = window.location.protocol + "//" + window.location.host + "/memj/";

        let ajax = new XMLHttpRequest();
        ajax.onload = onload;
        ajax.onerror = onerror;
        ajax.open("GET", url, true);
        ajax.send();

        function onload() {
            if (this.status === 200) { // request succeeded
                let ms = JSON.parse(this.responseText);
                document.getElementById("HeapInuse").innerText = ms.HeapInuse.toLocaleString() + " bytes";
                document.getElementById("TotalAlloc").innerText = ms.TotalAlloc.toLocaleString() + " bytes";
                document.getElementById("Sys").innerText = ms.Sys.toLocaleString() + " bytes";
                document.getElementById("Lookups").innerText = ms.Lookups.toLocaleString() + " lookups";
                document.getElementById("Mallocs").innerText = ms.Mallocs.toLocaleString() + " objects";
                document.getElementById("Frees").innerText = ms.Frees.toLocaleString() + " objects";
                document.getElementById("Live").innerText = (ms.Mallocs - ms.Frees).toLocaleString() + " objects";
                document.getElementById("HeapAlloc").innerText = ms.HeapAlloc.toLocaleString() + " bytes";
                document.getElementById("HeapSys").innerText = ms.HeapSys.toLocaleString() + " bytes";
                document.getElementById("HeapIdle").innerText = ms.HeapIdle.toLocaleString() + " bytes";
                document.getElementById("HeapReleased").innerText = ms.HeapReleased.toLocaleString() + " bytes";
                document.getElementById("HeapObjects").innerText = ms.HeapObjects.toLocaleString() + " objects";
                document.getElementById("StackInuse").innerText = ms.StackInuse.toLocaleString() + " bytes";
                document.getElementById("StackSys").innerText = ms.StackSys.toLocaleString() + " bytes";
                document.getElementById("NextGC").innerText = ms.NextGC.toLocaleString() + " bytes";
                document.getElementById("PauseTotalNs").innerText = ms.PauseTotalNs.toLocaleString() + " ns";
                document.getElementById("NumGC").innerText = ms.NumGC.toLocaleString() + " GC cycles";
                document.getElementById("NumForcedGC").innerText = ms.NumForcedGC.toLocaleString() + " GC cycles";

                let d = new Date(ms.LastGC / 1000000).toLocaleString();
                document.getElementById("LastGC").innerText = d;

                let frac = ms.GCCPUFraction;
                if (frac < 0) {
                    frac = 0.0;
                }
                let percent = (frac * 100).toFixed(2);
                document.getElementById("GCCPUFraction").innerText = percent + "%";

                updateRefreshTime();
            }
        }

        function onerror(e) {
            console.error(e);
        }
    }

    function forceCollection() {
        let url = window.location.protocol + "//" + window.location.host + "/memj/forcecollection";

        let ajax = new XMLHttpRequest();
        ajax.onload = onload;
        ajax.onerror = onerror;
        ajax.open("PUT", url, true);
        ajax.send();

        function onload() {
        }

        function onerror(e) {
            console.error(e);
        }
    }

    refreshMemStats();
    window.setInterval(refreshMemStats, 1000);

</script>

{{ end }}
