grafana / grafana-plugin-sdk-go

A Go SDK for building backend plugins for Grafana
Apache License 2.0
217 stars 65 forks source link

Provide a capability / interface for trigger a config reload #1043

Open jkroepke opened 3 months ago

jkroepke commented 3 months ago

What would you like to be added:

I'm develop an Grafana App and I have no clue, what happens, if the user updates the settings at admin panel. I guess, the setting will be saved on Grafana side, but not propagated to the plugin.

Having if a interface where implement I can implement a configReload function, would be great.

_ backend.ConfigReloadHandler    = (*App)(nil)

I the code, I can see a NeedsUpdate function, no clue what it does.

https://github.com/grafana/grafana-plugin-sdk-go/blob/aac004c586d9f54a78755aeaaae2f660a734edc0/backend/app/instance_provider.go#L61

Why is this needed:

Reading the https://grafana.com/developers/plugin-tools/key-concepts/backend-plugins/#caching-and-connection-pooling It's recommend to setup the client on init and re-use it every time.

But, if settings are updated by admin, I have to re-create some clients on reload.

wbrowne commented 3 months ago

Hi @jkroepke.

if the user updates the settings at admin panel. I guess, the setting will be saved on Grafana side, but not propagated to the plugin.

Where are you storing settings? Inside jsonData / secureJsonData? Please see below which shows a demonstration of the instance factory function (NewApp), which is invoked when settings are changed.

package main

func main() {
    if err := app.Manage("myorg-withbackend-app", plugin.NewApp, app.ManageOpts{}); err != nil {
        log.DefaultLogger.Error(err.Error())
        os.Exit(1)
    }
}
package plugin

// NewApp creates a new example *App instance. This function will be invoked every time there is an update 
// to the `Updated` timestamp of the `AppInstanceSettings` (controlled by Grafana)
func NewApp(_ context.Context, _ backend.AppInstanceSettings) (instancemgmt.Instance, error) {
    var app App

    mux := http.NewServeMux()
    app.registerRoutes(mux)
    app.CallResourceHandler = httpadapter.New(mux)

    return &app, nil
}

// Dispose here tells plugin SDK that plugin wants to clean up resources when a new instance
// created.
func (a *App) Dispose() {
    // cleanup
}

// CheckHealth handles health checks sent from Grafana to the plugin.
func (a *App) CheckHealth(_ context.Context, _ *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
    return &backend.CheckHealthResult{
        Status:  backend.HealthStatusOk,
        Message: "ok",
    }, nil
}
jkroepke commented 2 months ago

Where are you storing settings? Inside jsonData / secureJsonData?

Yes.

I'm a bit aware that Grafana invoke Dispose/NewApp on config change. But from plugin point of view, that a full restart rather an a soft-reload.

For example, the app holds some long-living requests/connection and they should not interrupt on config-change.