Skip to content
Snippets Groups Projects
render.py 8.03 KiB
BASE_DROPDOWN_PANEL = {
    "aliasColors": {},
    "collapsed": False,
    "datasource": None,
    "fill": None,
    "fillGradient": None,
    "legend": None,
    "lines": None,
    "linewidth": None,
    "search": None,
    "stack": None,
    "tags": None,
    "targets": None,
    "type": "row",
    "xaxis": None,
    "yaxes": None,
    "yaxis": None,
}

BASE_YAXES = {
    "logBase": 1,
    "max": None,
    "min": 0,
    "show": True,
}

BASE_PANEL = {
    "bars": False,
    "collapsed": None,
    "dashLength": 10,
    "dashes": False,
    "decimals": 2,
    "fieldConfig": {"defaults": {"custom": {}}, "overrides": []},
    "fill": 1,
    "fillGradient": 10,
    "hiddenSeries": False,
    "lines": True,
    "nullPointMode": "null",
    "options": {"alertThreshold": True},
    "percentage": False,
    "pointradius": 2,
    "points": False,
    "renderer": "flot",
    "search": None,
    "seriesOverrides": [],
    "spaceLength": 10,
    "steppedLine": False,
    "tags": None,
    "thresholds": [],
    "timeFrom": None,
    "timeRegions": [],
    "timeShift": None,
    "tooltip": {"shared": True, "sort": 0, "value_type": "individual"},
    "type": "graph",
    "xaxis": {
            "buckets": None,
            "mode": "time",
            "name": None,
            "show": True,
            "values": None,
    },
    "yaxis": {"align": False, "alignLevel": None},
    "targets": [],
}

BASE_LEGEND = {
    "alignAsTable": True,
    "avg": True,
    "current": True,
    "max": True,
    "min": False,
    "rightSide": None,
    "show": True,
    "total": False,
    "values": True,
}

BASE_DASHBOARD = {
    "id": None,
    "uid": None,
    "annotations": {
        "list": [
            {
                "builtIn": 1,
                "datasource": "-- Grafana --",
                "enable": True,
                "hide": True,
                "iconColor": "rgba(0, 211, 255, 1)",
                "name": "Annotations & Alerts",
                "type": "dashboard",
            }
        ]
    },
    "editable": False,
    "gnetId": None,
    "graphTooltip": 0,
    "schemaVersion": 27,
    "style": "dark",
    "templating": {"list": []},
    "time": {"from": "now-24h", "to": "now"},
    "timepicker": {},
    "timezone": "",
    "version": 1,
    "links": [],
}

INFOBOX = {
    "datasource": None,
    "gridPos": {"h": 2, "w": 24, "x": 0, "y": 0},
    "id": 1,
    "options": {
        "content": """
            <center style="margin-top:5px;">
                INFO: The average values displayed are only mean values for timescales of 2 days or less
            </center>""",
        "mode": "html"
    },
    "pluginVersion": "8.2.5",
    "title": "",
    "type": "text",
}


def create_dropdown_panel(title, id, y, **kwargs):
    """
    Creates a dropdown panel from the given data.

    :param title: title of the dropdown panel
    :param id: id of the dropdown panel
    :param y: y of the dropdown panel
    :param kwargs: data to be used in the template

    :return: rendered dropdown panel JSON
    """
    return {
        **BASE_DROPDOWN_PANEL,
        "id": id,
        "gridPos": {"h": 1, "w": 24, "x": 0, "y": y},
        "title": title,
    }


def create_yaxes(type):
    """
    Creates the yaxes JSON for the given type, used in the panel template.

    :param type: type of yaxes to create (bits/s or errors/s)

    :return: rendered yaxes JSON
    """
    if type == "errors":
        return [
            {
                **BASE_YAXES,
                "format": "none",
                "label": "errors and discards per second",
            },
            {
                **BASE_YAXES,
                "format": "none",
                "label": "errors and discards per second",
            },
        ]
    return [
        {
            **BASE_YAXES,
            "format": "bps",
            "label": "bits per second",
        },
        {
            **BASE_YAXES,
            "format": "bps",
            "label": "bits per second",
        },
    ]


def create_panel_target(
    alias,
    select_field,
    refId,
    percentile=False,
    measurement="interface_rates",
    errors=False,
    isp=None,
    subscription=None,
    scid=None,
    interface_tag=None,
    nren=None,
    hostname=None,
    interface=None,
    **_
):
    """
    Creates a panel target from the given data.
    A panel target defines how to query data for a single timeseries.

    :param data: data to be used in the template

    :return: rendered panel target JSON
    """
    select = [{"params": [select_field], "type": "field"}]
    select.append(
        {"params": [95], "type": "percentile"}
        if percentile
        else {"params": [], "type": "max"}
    )
    if not errors:
        select.append({"params": ["*8"], "type": "math"})
    if isp:
        tags = [
            {"condition": None, "key": "tag", "operator": "=", "value": interface_tag},
            {"condition": "AND", "key": "isp", "operator": "=", "value": isp},
            {"condition": "AND", "key": "nren", "operator": "=", "value": nren},
        ]
    elif subscription:
        tags = [
            {"condition": None, "key": "hostname", "operator": "=", "value": hostname},
            {
                "condition": "AND",
                "key": "subscription",
                "operator": "=",
                "value": subscription,
            },
        ]
    elif scid:
        tags = [{"condition": None, "key": "scid", "operator": "=", "value": scid}]
    else:
        tags = [
            {
                "condition": None,
                "key": "hostname",
                "operator": "=",
                "value": hostname,
            },
            {
                "condition": "AND",
                "key": "interface_name",
                "operator": "=",
                "value": interface,
            },
        ]
    result = {
        "alias": alias,
        "groupBy": (
            []
            if percentile
            else [
                {"params": ["$__interval"], "type": "time"},
                {"params": ["null"], "type": "fill"},
            ]
        ),
        "measurement": measurement,
        "orderByTime": None,
        "policy": None,
        "refId": refId,
        "resultFormat": "time_series",
        "select": [select],
        "tags": tags,
    }
    return result


def create_panel(
    title,
    height,
    width,
    linewidth,
    y,
    id,
    datasource,
    x=0,
    alias_colors=None,
    disable_legend=False,
    stack=False,
    y_axis_type="bits",
    targets=None,
    panel_targets=None,
    is_lambda=False,
    **_
):
    """
    Creates a panel from the given data. Constructs the yaxes and panel targets
    and renders the panel template using these.

    :param data: data to be used in the template

    :return: rendered panel JSON
    """
    yaxes = create_yaxes(y_axis_type)

    interval = 5 if not is_lambda else 15

    result = {
        **BASE_PANEL,
        "aliasColors": alias_colors or {},
        "datasource": datasource,
        "gridPos": {"h": height, "w": width, "x": x, "y": y},
        "id": id,
        "interval": f"{interval}m",
        "linewidth": linewidth,
        "stack": stack,
        "title": title,
        "yaxes": yaxes,
    }
    if not disable_legend:
        result["legend"] = BASE_LEGEND

    targets = targets or []
    for target in panel_targets or []:
        targets.append(create_panel_target(**target))
    result["targets"] = targets
    return result


def render_with_aggregate_dashboard(
    nren_name, aggregate_panels, dropdown_groups, tag=None, tags=None, **_
):
    assert tag or tags
    panels = [INFOBOX, *aggregate_panels]
    for group in dropdown_groups:
        panels.append(group["dropdown"])
        panels.extend(group["panels"])

    return {
        **BASE_DASHBOARD,
        "tags": tags or [tag],
        "title": nren_name,
        "panels": panels,
    }


def render_simple_dashboard(title, tag=None, tags=None, panels=None, **_):
    assert tag or tags
    return {
        **BASE_DASHBOARD,
        "tags": tags or [tag],
        "title": title,
        "panels": [
            INFOBOX,
            *(panels or []),
        ],
    }