Attribute Macro grafana_plugin_sdk::main

source ·
#[main]
Expand description

Generates a main function that starts a Plugin with the returned service struct.

When applied to a function that returns a struct implementing one or more of the various Service traits, #[main] will create an async runtime and a Plugin, then attach the desired services

The returned struct must be Clone so that it can be used to handle multiple services.

Attributes

services

The services attribute takes a list of services that the plugin should expose. At least one service must be specified. Possible options are:

Example:

#[grafana_plugin_sdk::main(
    services(data, diagnostics, resource, stream),
)]
async fn plugin() -> Plugin {
    Plugin
}

init_subscriber

The init_subscriber attribute indicates whether a tracing subscriber should be initialized automatically using Plugin::init_subscriber. Unless this is being done in the annotated plugin function, this should generally be set to true.

This must be a boolean.

Example

#[grafana_plugin_sdk::main(
    services(resource),
    init_subscriber = true,
)]
async fn plugin() -> Plugin {
    Plugin
}

shutdown_handler

The shutdown_handler attribute indicates that a shutdown handler should be exposed using Plugin::shutdown_handler

This must be a string which can be parsed as a [SocketAddr][std::net::SocketAddr] using SocketAddr::parse.

Example

#[grafana_plugin_sdk::main(
    services(resource),
    shutdown_handler = "127.0.0.1:10001",
)]
async fn plugin() -> Plugin {
    Plugin
}

Macro expansion

The following example shows what the #[main] macro expands to:

use std::sync::Arc;

use grafana_plugin_sdk::backend;
use thiserror::Error;

#[derive(Clone)]
struct Plugin;

#[derive(Debug, Error)]
enum ResourceError {
    #[error("HTTP error: {0}")]
    Http(#[from] http::Error),

    #[error("Path not found")]
    NotFound,
}

impl backend::ErrIntoHttpResponse for ResourceError {}

#[backend::async_trait]
impl backend::ResourceService for Plugin {
    type Error = ResourceError;
    type InitialResponse = Vec<u8>;
    type Stream = backend::BoxResourceStream<Self::Error>;
    async fn call_resource(&self, r: backend::CallResourceRequest) -> Result<(Self::InitialResponse, Self::Stream), Self::Error> {
        todo!()
    }
}

#[grafana_plugin_sdk::main(
    services(resource),
    init_subscriber = true,
    shutdown_handler = "127.0.0.1:10001",
)]
async fn plugin() -> Plugin {
    Plugin
}

expands to:


fn main() -> Result<(), Box<dyn std::error::Error>> {
    let fut = async {
        let listener = ::grafana_plugin_sdk::backend::initialize().await?;
        let service = Plugin;
        ::grafana_plugin_sdk::backend::Plugin::new()
            .resource_service(service.clone())
            .init_subscriber(true)
            .shutdown_handler("127.0.0.1:10001".parse().expect("could not parse shutdown handler as SocketAddr"))
            .start(listener)
            .await?;
        Ok::<_, Box<dyn std::error::Error>>(())
    };
    tokio::runtime::Builder::new_multi_thread()
        .thread_name("grafana-plugin-worker-thread")
        .enable_all()
        .build()
        .expect("create tokio runtime")
        .block_on(fut)?;
    Ok(())
}