-- This Source Code Form is subject to the terms of the Mozilla Public
-- License, v. 2.0. If a copy of the MPL was not distributed with this
-- file, You can obtain one at http://mozilla.org/MPL/2.0/.

--[[
Graphs the Heka memory statistics using the heka.memstat message generated by
pipeline/report.go.

Config:

- sec_per_row (uint, optional, default 60)
    Sets the size of each bucket (resolution in seconds) in the sliding window.

- rows (uint, optional, default 1440)
    Sets the size of the sliding window i.e., 1440 rows representing 60 seconds
    per row is a 24 sliding hour window with 1 minute resolution.

- anomaly_config(string) - (see :ref:`sandbox_anomaly_module`)

*Example Heka Configuration*

.. code-block:: ini

    [HekaMemstat]
    type = "SandboxFilter"
    filename = "lua_filters/heka_memstat.lua"
    ticker_interval = 60
    preserve_data = true
    message_matcher = "Type == 'heka.memstat'"

--]]

local alert      = require "alert"
local annotation = require "annotation"
local anomaly    = require "anomaly"
require "circular_buffer"

local title          = "Stats"
local rows           = read_config("rows") or 1440
local sec_per_row    = read_config("sec_per_row") or 60
local anomaly_config = anomaly.parse_config(read_config("anomaly_config"))
annotation.set_prune(title, rows * sec_per_row * 1e9)

stats = circular_buffer.new(rows, 6, sec_per_row)
local HEAP_SYS      = stats:set_header(1, "HeapSys"     , "B"    , "max")
local HEAP_ALLOC    = stats:set_header(2, "HeapAlloc"   , "B"    , "max")
local HEAP_IDLE     = stats:set_header(3, "HeapIdle"    , "B"    , "max")
local HEAP_INUSE    = stats:set_header(4, "HeapInuse"   , "B"    , "max")
local HEAP_RELEASED = stats:set_header(5, "HeapReleased", "B"    , "max")
local HEAP_OBJECTS  = stats:set_header(6, "HeapObjects" , "count", "max")

function process_message ()
    local ts = read_message("Timestamp")

    stats:set(ts, HEAP_SYS       , read_message("Fields[HeapSys]"))
    stats:set(ts, HEAP_ALLOC     , read_message("Fields[HeapAlloc]"))
    stats:set(ts, HEAP_IDLE      , read_message("Fields[HeapIdle]"))
    stats:set(ts, HEAP_INUSE     , read_message("Fields[HeapInuse]"))
    stats:set(ts, HEAP_RELEASED  , read_message("Fields[HeapReleased]"))
    stats:set(ts, HEAP_OBJECTS   , read_message("Fields[HeapObjects]"))
    return 0
end

function timer_event(ns)
    if anomaly_config then
        if not alert.throttled(ns) then
            local msg, annos = anomaly.detect(ns, title, stats, anomaly_config)
            if msg then
                annotation.concat(title, annos)
                alert.send(ns, msg)
            end
        end
        inject_payload("cbuf", title, annotation.prune(title, ns), stats)
    else
        inject_payload("cbuf", title, stats)
    end
end
