rstgroup / zf-grafana-module
Integration with Grafana API.
Requires
- php: ^5.6 || ^7
- doctrine/dbal: ^2.5
- php-http/client-implementation: ^1
- php-http/httplug: ^1.1
- php-http/message-factory: ^1.0
- php-http/message-factory-implementation: ^1
- webmozart/assert: ^1.2
- zendframework/zend-mvc-console: ^1.1
Requires (Dev)
- guzzlehttp/psr7: ^1.4
- mikey179/vfsstream: ^1.6
- php-http/message: ^1.6
- phpunit/dbunit: ^2.0
- phpunit/phpunit: ^5.7
This package is not auto-updated.
Last update: 2020-01-10 16:38:44 UTC
README
This module contains integration with Grafana tool via it's HTTP APIs.
Installation
composer require rstgroup/zf-grafana-module
..and then add the module to your app using ZF system configuration (config/application.config.php
):
return [ 'modules' => [ 'RstGroup\ZfGrafanaModule', ], ]
The last step is providing database connection and HTTP client to allow the library to communicate with other services. Use aliasing functionality of Zend's Service Manager to define:
\RstGroup\ZfGrafanaModule\Repository\DashboardApiRepositoryFactory::HTTP_CLIENT_SERVICE
HTTP client that implementsHttp\Client\HttpClient
interface\RstGroup\ZfGrafanaModule\Repository\DashboardApiRepositoryFactory::REQUEST_FACTORY_SERVICE
request factory used to create HTTP requests\RstGroup\ZfGrafanaModule\Repository\DbalMetadataRepositoryFactory::SERVICE_CONNECTION
Doctrine DBAL Connection to database where the dashboard's metadata will be stored\RstGroup\ZfGrafanaModule\Repository\DbalIdMappingRepositoryFactory::SERVICE_CONNECTION
Doctrine DBAL Connection to database where the dashboard's ID mapping will be stored
Dashboards
Module gives you functionality to automatically synchronize your dashboards with given Grafana instance.
Usage
Module provides CLI command:
php public/index.php grafana migrate
There is currently no param required. All the information about dashboards is fetched from app's configuration.
Defining dashboards to sync
By default, script scans through build/dashboards
directory, looking for .json
files with dashboard definition.
The directory to search can be easily changed in config file, here's the example:
return [ 'dashboard-migrations' => [ 'repositories' => [ \RstGroup\ZfGrafanaModule\Repository\FilesystemDirectoryRepository::class => [ 'path' => 'path/to/your/directory', ], ], ], ];
Custom dashboard definition source
It's also possible to store dashboard definitions elsewhere. To do it, you need to do two things:
-
Implement your own
DashboardApiRepository
, define it in Zend's Service Manager and configure module to use it:return [ 'service_manager' => [ 'factories' => [ MyOwnRepository::class => MyOwnRepositoryFactory::class, ] ], 'dashboard-migrations' => [ 'source-repository' => [ 'service' => MyOwnRepository::class, ] ] ]
-
Implement your own
DashboardIdsProvider
, that will return the IDs to fetch from your custom repository. Then just alias your custom provider by the interface name:return [ 'service_manager' => [ 'aliases' => [ \RstGroup\ZfGrafanaModule\Controller\Helper\DashboardIdsProvider::class => \Your\Custom\Provider::class, ]; ] ];
Defining remote repository
To make synchronizing work, you need to pass Grafana API basic URL and API key. These values should be passed to app's configuration via config files (or, better, in Consul, if your app can fetch configuration from it!):
return [ 'dashboard-migrations' => [ 'repositories' => [ \RstGroup\ZfGrafanaModule\Repository\DashboardApiRepository::class => [ 'url' => 'http://url.to.grafana.com/api', 'api-key' => 'grafana-api-key', ], ], ], ];
The next thing you need is HTTP Client (which implements PSR's client interface) and HTTP message factory implementation (see http://docs.php-http.org/en/latest/message/message-factory.html)
You should pass those in you app's configuration, aliasing predefined service names, like in the example below:
return [ 'service_manager' => [ 'aliases' => [ \RstGroup\ZfGrafanaModule\Repository\DashboardApiRepositoryFactory::HTTP_CLIENT_SERVICE => \Http\Adapter\Guzzle6\Client::class, \RstGroup\ZfGrafanaModule\Repository\DashboardApiRepositoryFactory::REQUEST_FACTORY_SERVICE => \Http\Message\MessageFactory\GuzzleMessageFactory::class, ] ] ];
Metadata
Why is there any metadata?
The module needs to store Dashboard's metadata. It's because of Grafana API, which generates additional identifiers and parameters for published dashboards.
First of these is dashboard's SLUG. The slug is a textual, URL-safe representation of dashboard's Title. Slug is used in API as the required parameter in GET requests and thus can be trated as identifier.
Second one is Dashboard's ID, generated right after dashboard creation. The ID is a positive integer. It is used in update
request (POST
) and has to be provided as dashboard definition (inside of JSON), thus also can be treat as dashboard's
identifier - the second, less important one :))
The next metadata parameter is dashboard's VERSION - after each update, the version is incremented. If you try to update your dashboard with the one with lower version number - API will refuse the change.
The last parameter is SCHEMA VERSION, which determines the version of definition schema itself, so Grafana instances are able to determine if it's up-to-date enough to parse given dashboard definition.
Storage
By default - metadata is stored in MySQL database, thus the Doctrine DBAL Connection should be aliased for mapper to work:
return [ 'service_manager' => [ 'aliases' => [ \RstGroup\ZfGrafanaModule\Repository\DbalIdMappingRepositoryFactory::SERVICE_CONNECTION => 'Your\Doctrine\Dbal\Connection' ] ] ]
The table should follow the definition below:
CREATE TABLE dashboard_metadata ( dashboard_id VARCHAR(255) NOT NULL PRIMARY KEY, grafana_id INT NOT NULL, dashboard_version INT NOT NULL, dashboard_schema_version INT DEFAULT NULL ) DEFAULT CHARACTER SET 'utf8';
ID mapping
Because the SLUG is created on the Grafana API's side, there is a need for keeping the local -> remote ID mapping.
By default, the local identifier of dashboard is its definition's filename. Mapping is stored in the database, thus the Doctrine DBAL Connection should be aliased for mapper to work:
return [ 'service_manager' => [ 'aliases' => [ \RstGroup\ZfGrafanaModule\Repository\DbalIdMappingRepositoryFactory::SERVICE_CONNECTION => 'Your\Doctrine\Dbal\Connection' ] ] ]
The mapping table should follow the definition:
CREATE TABLE dashboard_id_mapping ( local_id VARCHAR(255) NOT NULL PRIMARY KEY, remote_id VARCHAR(255) NOT NULL ) DEFAULT CHARACTER SET 'utf8';