grafana-foundation-sdk


Namegrafana-foundation-sdk JSON
Version 1715606166!10.4.0 PyPI version JSON
download
home_pageNone
SummaryA set of tools, types and libraries for building and manipulating Grafana objects.
upload_time2024-05-13 13:17:41
maintainerNone
docs_urlNone
authorGrafana Labs
requires_python>=3.11
licenseNone
keywords grafana logs metrics observability sdk traces
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Grafana Foundation SDK – Python

A set of tools, types and *builder libraries* for building and manipulating Grafana objects in Python.

> [!NOTE]
> This branch contains **types and builders generated for Grafana v10.4.x.**
> Other supported versions of Grafana can be found at [this repository's root](https://github.com/grafana/grafana-foundation-sdk/).

## Installing

```shell
python3 -m pip install 'grafana_foundation_sdk==1715606166!10.4.0'
```

## Example usage

### Building a dashboard

```python
from grafana_foundation_sdk.builders.dashboard import Dashboard, Row
from grafana_foundation_sdk.builders.prometheus import Dataquery as PrometheusQuery
from grafana_foundation_sdk.builders.timeseries import Panel as Timeseries
from grafana_foundation_sdk.cog.encoder import JSONEncoder
from grafana_foundation_sdk.models.common import TimeZoneBrowser

def build_dashboard() -> Dashboard:
    builder = (
        Dashboard("[TEST] Node Exporter / Raspberry")
        .uid("test-dashboard-raspberry")
        .tags(["generated", "raspberrypi-node-integration"])

        .refresh("1m")
        .time("now-30m", "now")
        .timezone(TimeZoneBrowser)

        .with_row(Row("Overview"))
        .with_panel(
            Timeseries()
            .title("Network Received")
            .unit("bps")
            .min_val(0)
            .with_target(
                PrometheusQuery()
                .expr('rate(node_network_receive_bytes_total{job="integrations/raspberrypi-node", device!="lo"}[$__rate_interval]) * 8')
                .legend_format("{{ device }}")
            )
        )
    )

    return builder


if __name__ == '__main__':
    dashboard = build_dashboard().build()
    encoder = JSONEncoder(sort_keys=True, indent=2)

    print(encoder.encode(dashboard))
```

### Unmarshaling a dashboard

```python
import json

from grafana_foundation_sdk.cog.plugins import register_default_plugins
from grafana_foundation_sdk.models.dashboard import Dashboard as DashboardModel


if __name__ == '__main__':
    # Required to correctly unmarshal panels and dataqueries
    register_default_plugins()

    with open("dashboard.json", "r") as f:
        decoded_dashboard = DashboardModel.from_json(json.load(f))
        print(decoded_dashboard)
```

### Defining a custom query type

While the SDK ships with support for all core datasources and their query types,
it can be extended for private/third-party plugins.

To do so, define a type and a builder for the custom query:

```python
# src/customquery.py
from typing import Any, Optional, Self

from grafana_foundation_sdk.cog import variants as cogvariants
from grafana_foundation_sdk.cog import runtime as cogruntime
from grafana_foundation_sdk.cog import builder


class CustomQuery(cogvariants.Dataquery):
    # ref_id and hide are expected on all queries
    ref_id: Optional[str]
    hide: Optional[bool]

    # query is specific to the CustomQuery type
    query: str

    def __init__(self, query: str, ref_id: Optional[str] = None, hide: Optional[bool] = None):
        self.query = query
        self.ref_id = ref_id
        self.hide = hide

    def to_json(self) -> dict[str, object]:
        payload: dict[str, object] = {
            "query": self.query,
        }
        if self.ref_id is not None:
            payload["refId"] = self.ref_id
        if self.hide is not None:
            payload["hide"] = self.hide
        return payload

    @classmethod
    def from_json(cls, data: dict[str, Any]) -> Self:
        args: dict[str, Any] = {}

        if "query" in data:
            args["query"] = data["query"]
        if "refId" in data:
            args["ref_id"] = data["refId"]
        if "hide" in data:
            args["hide"] = data["hide"]

        return cls(**args)


def custom_query_variant_config() -> cogruntime.DataqueryConfig:
    return cogruntime.DataqueryConfig(
        # datasource plugin ID
        identifier="custom-query",
        from_json_hook=CustomQuery.from_json,
    )


class CustomQueryBuilder(builder.Builder[CustomQuery]):
    _internal: CustomQuery

    def __init__(self, query: str):
        self._internal = CustomQuery(query=query)

    def build(self) -> CustomQuery:
        return self._internal

    def ref_id(self, ref_id: str) -> Self:
        self._internal.ref_id = ref_id

        return self

    def hide(self, hide: bool) -> Self:
        self._internal.hide = hide

        return self
```

Register the type with cog, and use it as usual to build a dashboard:

```python
from grafana_foundation_sdk.builders.dashboard import Dashboard, Row
from grafana_foundation_sdk.builders.timeseries import Panel as Timeseries
from grafana_foundation_sdk.cog.encoder import JSONEncoder
from grafana_foundation_sdk.cog.plugins import register_default_plugins
from grafana_foundation_sdk.cog.runtime import register_dataquery_variant

from src.customquery import custom_query_variant_config, CustomQueryBuilder


if __name__ == '__main__':
    # Required to correctly unmarshal panels and dataqueries
    register_default_plugins()

    # This lets cog know about the newly created query type and how to unmarshal it.
    register_dataquery_variant(custom_query_variant_config())

    dashboard = (
        Dashboard("Custom query type")
        .uid("test-custom-query")
        .refresh("1m")
        .time("now-30m", "now")

        .with_row(Row("Overview"))
        .with_panel(
            Timeseries()
            .title("Sample panel")
            .with_target(
                CustomQueryBuilder("query here")
            )
        )
    ).build()

    print(JSONEncoder(sort_keys=True, indent=2).encode(dashboard))
```

### Defining a custom panel type

While the SDK ships with support for all core panels, it can be extended for
private/third-party plugins.

To do so, define a type and a builder for the custom panel's options:

```python
# src/custompanel.py
from typing import Any, Self

from grafana_foundation_sdk.cog import builder
from grafana_foundation_sdk.cog import runtime as cogruntime
from grafana_foundation_sdk.builders.dashboard import Panel as PanelBuilder
from grafana_foundation_sdk.models import dashboard


class CustomPanelOptions:
    make_beautiful: bool

    def __init__(self, make_beautiful: bool = False):
        self.make_beautiful = make_beautiful

    def to_json(self) -> dict[str, object]:
        return {
            "makeBeautiful": self.make_beautiful,
        }

    @classmethod
    def from_json(cls, data: dict[str, Any]) -> Self:
        args: dict[str, Any] = {}

        if "makeBeautiful" in data:
            args["make_beautiful"] = data["makeBeautiful"]

        return cls(**args)


def custom_panel_variant_config() -> cogruntime.PanelCfgConfig:
    return cogruntime.PanelCfgConfig(
        # plugin ID
        identifier="custom-panel",
        options_from_json_hook=CustomPanelOptions.from_json,
    )


class CustomPanelBuilder(PanelBuilder, builder.Builder[dashboard.Panel]):
    def __init__(self):
        super().__init__()
        # plugin ID
        self._internal.type_val = "custom-panel"

    def make_beautiful(self) -> Self:
        if self._internal.options is None:
            self._internal.options = CustomPanelOptions()

        assert isinstance(self._internal.options, CustomPanelOptions)

        self._internal.options.make_beautiful = True

        return self
```

Register the type with cog, and use it as usual to build a dashboard:

```python
from grafana_foundation_sdk.builders.dashboard import Dashboard, Row
from grafana_foundation_sdk.cog.encoder import JSONEncoder
from grafana_foundation_sdk.cog.plugins import register_default_plugins
from grafana_foundation_sdk.cog.runtime import register_panelcfg_variant

from src.custompanel import custom_panel_variant_config, CustomPanelBuilder


if __name__ == '__main__':
    # Required to correctly unmarshal panels and dataqueries
    register_default_plugins()

    # This lets cog know about the newly created panel type and how to unmarshal it.
    register_panelcfg_variant(custom_panel_variant_config())

    dashboard = (
        Dashboard("Custom panel type")
        .uid("test-custom-panel")
        .refresh("1m")
        .time("now-30m", "now")

        .with_row(Row("Overview"))
        .with_panel(
            CustomPanelBuilder()
            .title("Sample panel")
            .make_beautiful()
        )
    ).build()

    print(JSONEncoder(sort_keys=True, indent=2).encode(dashboard))
```

## Maturity

> [!WARNING]
> The code in this repository should be considered experimental. Documentation is only
available alongside the code. It comes with no support, but we are keen to receive
feedback and suggestions on how to improve it, though we cannot commit
to resolution of any particular issue.

Grafana Labs defines experimental features as follows:

> Projects and features in the Experimental stage are supported only by the Engineering
teams; on-call support is not available. Documentation is either limited or not provided
outside of code comments. No SLA is provided.
>
> Experimental projects or features are primarily intended for open source engineers who
want to participate in ensuring systems stability, and to gain consensus and approval
for open source governance projects.
>
> Projects and features in the Experimental phase are not meant to be used in production
environments, and the risks are unknown/high.

## License

[Apache 2.0 License](./LICENSE)

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "grafana-foundation-sdk",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.11",
    "maintainer_email": null,
    "keywords": "grafana, logs, metrics, observability, sdk, traces",
    "author": "Grafana Labs",
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/16/cb/5efdd9eba3938a667a28cc888fc33bd2a0bfc6f23131bba264161357abdf/grafana_foundation_sdk-1715606166!10.4.0.tar.gz",
    "platform": null,
    "description": "# Grafana Foundation SDK \u2013 Python\n\nA set of tools, types and *builder libraries* for building and manipulating Grafana objects in Python.\n\n> [!NOTE]\n> This branch contains **types and builders generated for Grafana v10.4.x.**\n> Other supported versions of Grafana can be found at [this repository's root](https://github.com/grafana/grafana-foundation-sdk/).\n\n## Installing\n\n```shell\npython3 -m pip install 'grafana_foundation_sdk==1715606166!10.4.0'\n```\n\n## Example usage\n\n### Building a dashboard\n\n```python\nfrom grafana_foundation_sdk.builders.dashboard import Dashboard, Row\nfrom grafana_foundation_sdk.builders.prometheus import Dataquery as PrometheusQuery\nfrom grafana_foundation_sdk.builders.timeseries import Panel as Timeseries\nfrom grafana_foundation_sdk.cog.encoder import JSONEncoder\nfrom grafana_foundation_sdk.models.common import TimeZoneBrowser\n\ndef build_dashboard() -> Dashboard:\n    builder = (\n        Dashboard(\"[TEST] Node Exporter / Raspberry\")\n        .uid(\"test-dashboard-raspberry\")\n        .tags([\"generated\", \"raspberrypi-node-integration\"])\n\n        .refresh(\"1m\")\n        .time(\"now-30m\", \"now\")\n        .timezone(TimeZoneBrowser)\n\n        .with_row(Row(\"Overview\"))\n        .with_panel(\n            Timeseries()\n            .title(\"Network Received\")\n            .unit(\"bps\")\n            .min_val(0)\n            .with_target(\n                PrometheusQuery()\n                .expr('rate(node_network_receive_bytes_total{job=\"integrations/raspberrypi-node\", device!=\"lo\"}[$__rate_interval]) * 8')\n                .legend_format(\"{{ device }}\")\n            )\n        )\n    )\n\n    return builder\n\n\nif __name__ == '__main__':\n    dashboard = build_dashboard().build()\n    encoder = JSONEncoder(sort_keys=True, indent=2)\n\n    print(encoder.encode(dashboard))\n```\n\n### Unmarshaling a dashboard\n\n```python\nimport json\n\nfrom grafana_foundation_sdk.cog.plugins import register_default_plugins\nfrom grafana_foundation_sdk.models.dashboard import Dashboard as DashboardModel\n\n\nif __name__ == '__main__':\n    # Required to correctly unmarshal panels and dataqueries\n    register_default_plugins()\n\n    with open(\"dashboard.json\", \"r\") as f:\n        decoded_dashboard = DashboardModel.from_json(json.load(f))\n        print(decoded_dashboard)\n```\n\n### Defining a custom query type\n\nWhile the SDK ships with support for all core datasources and their query types,\nit can be extended for private/third-party plugins.\n\nTo do so, define a type and a builder for the custom query:\n\n```python\n# src/customquery.py\nfrom typing import Any, Optional, Self\n\nfrom grafana_foundation_sdk.cog import variants as cogvariants\nfrom grafana_foundation_sdk.cog import runtime as cogruntime\nfrom grafana_foundation_sdk.cog import builder\n\n\nclass CustomQuery(cogvariants.Dataquery):\n    # ref_id and hide are expected on all queries\n    ref_id: Optional[str]\n    hide: Optional[bool]\n\n    # query is specific to the CustomQuery type\n    query: str\n\n    def __init__(self, query: str, ref_id: Optional[str] = None, hide: Optional[bool] = None):\n        self.query = query\n        self.ref_id = ref_id\n        self.hide = hide\n\n    def to_json(self) -> dict[str, object]:\n        payload: dict[str, object] = {\n            \"query\": self.query,\n        }\n        if self.ref_id is not None:\n            payload[\"refId\"] = self.ref_id\n        if self.hide is not None:\n            payload[\"hide\"] = self.hide\n        return payload\n\n    @classmethod\n    def from_json(cls, data: dict[str, Any]) -> Self:\n        args: dict[str, Any] = {}\n\n        if \"query\" in data:\n            args[\"query\"] = data[\"query\"]\n        if \"refId\" in data:\n            args[\"ref_id\"] = data[\"refId\"]\n        if \"hide\" in data:\n            args[\"hide\"] = data[\"hide\"]\n\n        return cls(**args)\n\n\ndef custom_query_variant_config() -> cogruntime.DataqueryConfig:\n    return cogruntime.DataqueryConfig(\n        # datasource plugin ID\n        identifier=\"custom-query\",\n        from_json_hook=CustomQuery.from_json,\n    )\n\n\nclass CustomQueryBuilder(builder.Builder[CustomQuery]):\n    _internal: CustomQuery\n\n    def __init__(self, query: str):\n        self._internal = CustomQuery(query=query)\n\n    def build(self) -> CustomQuery:\n        return self._internal\n\n    def ref_id(self, ref_id: str) -> Self:\n        self._internal.ref_id = ref_id\n\n        return self\n\n    def hide(self, hide: bool) -> Self:\n        self._internal.hide = hide\n\n        return self\n```\n\nRegister the type with cog, and use it as usual to build a dashboard:\n\n```python\nfrom grafana_foundation_sdk.builders.dashboard import Dashboard, Row\nfrom grafana_foundation_sdk.builders.timeseries import Panel as Timeseries\nfrom grafana_foundation_sdk.cog.encoder import JSONEncoder\nfrom grafana_foundation_sdk.cog.plugins import register_default_plugins\nfrom grafana_foundation_sdk.cog.runtime import register_dataquery_variant\n\nfrom src.customquery import custom_query_variant_config, CustomQueryBuilder\n\n\nif __name__ == '__main__':\n    # Required to correctly unmarshal panels and dataqueries\n    register_default_plugins()\n\n    # This lets cog know about the newly created query type and how to unmarshal it.\n    register_dataquery_variant(custom_query_variant_config())\n\n    dashboard = (\n        Dashboard(\"Custom query type\")\n        .uid(\"test-custom-query\")\n        .refresh(\"1m\")\n        .time(\"now-30m\", \"now\")\n\n        .with_row(Row(\"Overview\"))\n        .with_panel(\n            Timeseries()\n            .title(\"Sample panel\")\n            .with_target(\n                CustomQueryBuilder(\"query here\")\n            )\n        )\n    ).build()\n\n    print(JSONEncoder(sort_keys=True, indent=2).encode(dashboard))\n```\n\n### Defining a custom panel type\n\nWhile the SDK ships with support for all core panels, it can be extended for\nprivate/third-party plugins.\n\nTo do so, define a type and a builder for the custom panel's options:\n\n```python\n# src/custompanel.py\nfrom typing import Any, Self\n\nfrom grafana_foundation_sdk.cog import builder\nfrom grafana_foundation_sdk.cog import runtime as cogruntime\nfrom grafana_foundation_sdk.builders.dashboard import Panel as PanelBuilder\nfrom grafana_foundation_sdk.models import dashboard\n\n\nclass CustomPanelOptions:\n    make_beautiful: bool\n\n    def __init__(self, make_beautiful: bool = False):\n        self.make_beautiful = make_beautiful\n\n    def to_json(self) -> dict[str, object]:\n        return {\n            \"makeBeautiful\": self.make_beautiful,\n        }\n\n    @classmethod\n    def from_json(cls, data: dict[str, Any]) -> Self:\n        args: dict[str, Any] = {}\n\n        if \"makeBeautiful\" in data:\n            args[\"make_beautiful\"] = data[\"makeBeautiful\"]\n\n        return cls(**args)\n\n\ndef custom_panel_variant_config() -> cogruntime.PanelCfgConfig:\n    return cogruntime.PanelCfgConfig(\n        # plugin ID\n        identifier=\"custom-panel\",\n        options_from_json_hook=CustomPanelOptions.from_json,\n    )\n\n\nclass CustomPanelBuilder(PanelBuilder, builder.Builder[dashboard.Panel]):\n    def __init__(self):\n        super().__init__()\n        # plugin ID\n        self._internal.type_val = \"custom-panel\"\n\n    def make_beautiful(self) -> Self:\n        if self._internal.options is None:\n            self._internal.options = CustomPanelOptions()\n\n        assert isinstance(self._internal.options, CustomPanelOptions)\n\n        self._internal.options.make_beautiful = True\n\n        return self\n```\n\nRegister the type with cog, and use it as usual to build a dashboard:\n\n```python\nfrom grafana_foundation_sdk.builders.dashboard import Dashboard, Row\nfrom grafana_foundation_sdk.cog.encoder import JSONEncoder\nfrom grafana_foundation_sdk.cog.plugins import register_default_plugins\nfrom grafana_foundation_sdk.cog.runtime import register_panelcfg_variant\n\nfrom src.custompanel import custom_panel_variant_config, CustomPanelBuilder\n\n\nif __name__ == '__main__':\n    # Required to correctly unmarshal panels and dataqueries\n    register_default_plugins()\n\n    # This lets cog know about the newly created panel type and how to unmarshal it.\n    register_panelcfg_variant(custom_panel_variant_config())\n\n    dashboard = (\n        Dashboard(\"Custom panel type\")\n        .uid(\"test-custom-panel\")\n        .refresh(\"1m\")\n        .time(\"now-30m\", \"now\")\n\n        .with_row(Row(\"Overview\"))\n        .with_panel(\n            CustomPanelBuilder()\n            .title(\"Sample panel\")\n            .make_beautiful()\n        )\n    ).build()\n\n    print(JSONEncoder(sort_keys=True, indent=2).encode(dashboard))\n```\n\n## Maturity\n\n> [!WARNING]\n> The code in this repository should be considered experimental. Documentation is only\navailable alongside the code. It comes with no support, but we are keen to receive\nfeedback and suggestions on how to improve it, though we cannot commit\nto resolution of any particular issue.\n\nGrafana Labs defines experimental features as follows:\n\n> Projects and features in the Experimental stage are supported only by the Engineering\nteams; on-call support is not available. Documentation is either limited or not provided\noutside of code comments. No SLA is provided.\n>\n> Experimental projects or features are primarily intended for open source engineers who\nwant to participate in ensuring systems stability, and to gain consensus and approval\nfor open source governance projects.\n>\n> Projects and features in the Experimental phase are not meant to be used in production\nenvironments, and the risks are unknown/high.\n\n## License\n\n[Apache 2.0 License](./LICENSE)\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "A set of tools, types and libraries for building and manipulating Grafana objects.",
    "version": "1715606166!10.4.0",
    "project_urls": {
        "Homepage": "https://github.com/grafana/grafana-foundation-sdk",
        "Issues": "https://github.com/grafana/grafana-foundation-sdk/issues",
        "Repository": "https://github.com/grafana/grafana-foundation-sdk.git"
    },
    "split_keywords": [
        "grafana",
        " logs",
        " metrics",
        " observability",
        " sdk",
        " traces"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "10c9b4fa2b9369298a36f48c2117a96158ffb13b61e1d58299261317492fcf87",
                "md5": "0b254a1d0210a1e5d4da5cb123420388",
                "sha256": "c6073b5d55c163bb16473ef9a99eb171127e75f637c700a5a05a1c009b0066f4"
            },
            "downloads": -1,
            "filename": "grafana_foundation_sdk-1715606166!10.4.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "0b254a1d0210a1e5d4da5cb123420388",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.11",
            "size": 290904,
            "upload_time": "2024-05-13T13:17:39",
            "upload_time_iso_8601": "2024-05-13T13:17:39.683766Z",
            "url": "https://files.pythonhosted.org/packages/10/c9/b4fa2b9369298a36f48c2117a96158ffb13b61e1d58299261317492fcf87/grafana_foundation_sdk-1715606166!10.4.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "16cb5efdd9eba3938a667a28cc888fc33bd2a0bfc6f23131bba264161357abdf",
                "md5": "12e9ef3155bfd0b7eaf3e21d030acd36",
                "sha256": "daf68a12ed9271ad7085b20481f69e849ccfe8cef98a92e20cb5005f405487ad"
            },
            "downloads": -1,
            "filename": "grafana_foundation_sdk-1715606166!10.4.0.tar.gz",
            "has_sig": false,
            "md5_digest": "12e9ef3155bfd0b7eaf3e21d030acd36",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.11",
            "size": 198361,
            "upload_time": "2024-05-13T13:17:41",
            "upload_time_iso_8601": "2024-05-13T13:17:41.057057Z",
            "url": "https://files.pythonhosted.org/packages/16/cb/5efdd9eba3938a667a28cc888fc33bd2a0bfc6f23131bba264161357abdf/grafana_foundation_sdk-1715606166!10.4.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-05-13 13:17:41",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "grafana",
    "github_project": "grafana-foundation-sdk",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "grafana-foundation-sdk"
}
        
Elapsed time: 0.25173s