Nested datasource plugin with backend

Hello,
I’d like to create an app plugin with nested datasource with backend plugin and nested panel plugin. I’ve already developed datasource plugin with its own backend. In the guide:

there is a note:
“each nested data source can have its own backend, independent of the app plugin’s backend.”
How to do it?
I’m not able to find any example of hot to include datasource bakend code into an app backend code.

Follow this part of the guide Work with nested plugins | Grafana Plugin Tools

in short: bootstrap a new data source plugin and copy some of the files into your app. That’s it.

If the nested datasource has a backend, Grafana will pick it up and start it.

Hi,

the guide only says to rename the src directory of the datasource plugin and copy it into the src directory of the app.

When you scaffold a datasource plugin as described in the guide, the backend is in the pkg directory, which is outside the src directory.

The guide doesn’t describe where to place the pkg directory and how to build the backend afterwards.

If you put the pkg directory in the renamed source directory , you can’t build it, since the plugin.json isn’t in the src directory, if you use the magefile to build it.

Can you please tell me where to put the backend part of a nested datasource plugin that grafana can pick it up and build it, using the addition build utilities that are recommended by them?

1 Like

Thanks @reilaen, you pointed exactly my case. Has anyone idea how to cope with it?

Hi @reilaen apologies for taking a while to get back to you. you are right we don’t have instructions about this in the guide. It is a more involved process and we don’t have many plugins doing this:

To bundle a backend datasource into an app you do this:

  • generate an app without backend
  • generate a datasource with backend (separate folder)
  • copy the datasource src inside the app/src, rename it to datasource (important, inside src not on the root)
  • Copy the datasource plugin.json inside app/datasource
  • copy the datasource pkg inside app (the root)
  • copy go.mod, go.sum and Magefile.go from the datasource to the app root
  • modify the app src/plugin.json to include the datasource:
 "includes": [
     {
      "type": "datasource",
      "name": "nested data source",
      "path": "datasource/plugin.json" // your datasource plugin-json, notice is relative to src
    },
  ],

Now you can build the datasource backend with mage as usual.

Here’s an example of how an app with a bundle datasource with backend looks like:

❯ echo ${PWD##*/} && tree . -I node_modules
academo-test-app
.
├── CHANGELOG.md
├── dist )
│   ├── datasource
│   │   ├── gpx_test_darwin_amd64
│   │   ├── gpx_test_darwin_arm64
│   │   ├── gpx_test_linux_amd64
│   │   ├── gpx_test_linux_arm
│   │   ├── gpx_test_linux_arm64
│   │   └── gpx_test_windows_amd64.exe
│   └── go_plugin_build_manifest
├── docker-compose.yaml
├── go.mod
├── go.sum
├── jest.config.js
├── jest-setup.js
├── LICENSE
├── Magefile.go
├── package.json
├── package-lock.json
├── pkg
│   ├── main.go
│   ├── models
│   │   └── settings.go
│   └── plugin
│       ├── datasource.go
│       └── datasource_test.go
├── playwright.config.ts
├── provisioning
│   └── plugins
│       ├── apps.yaml
│       └── README.md
├── README.md
├── src
│   ├── components
│   │   ├── App
│   │   │   ├── App.test.tsx
│   │   │   └── App.tsx
│   │   ├── AppConfig
│   │   │   ├── AppConfig.test.tsx
│   │   │   └── AppConfig.tsx
│   │   └── testIds.ts
│   ├── constants.ts
│   ├── datasource
│   │   ├── components
│   │   │   ├── ConfigEditor.tsx
│   │   │   ├── img
│   │   │   │   └── logo.svg
│   │   │   └── QueryEditor.tsx
│   │   ├── datasource.ts
│   │   ├── module.ts
│   │   ├── plugin.json
│   │   ├── README.md
│   │   └── types.ts
│   ├── img
│   │   └── logo.svg
│   ├── module.tsx
│   ├── pages
│   │   ├── PageFour.tsx
│   │   ├── PageOne.tsx
│   │   ├── PageThree.tsx
│   │   └── PageTwo.tsx
│   ├── plugin.json
│   ├── README.md
│   └── utils
│       └── utils.routing.ts
├── tests
│   ├── appConfig.spec.ts
│   ├── appNavigation.spec.ts
│   └── fixtures.ts
└── tsconfig.json

The dist folder is generated by mage of course. notice the backend will take the name from the pattern defined in src/datasource/plugin.json

Here’s the src/plugin.json

❯ cat -p src/plugin.json
{
  "$schema": "https://raw.githubusercontent.com/grafana/grafana/main/docs/sources/developers/plugins/plugin.schema.json",
  "type": "app",
  "name": "Test",
  "id": "academo-test-app",
  "info": {
    "keywords": ["app"],
    "description": "",
    "author": {
      "name": "Academo"
    },
    "logos": {
      "small": "img/logo.svg",
      "large": "img/logo.svg"
    },
    "screenshots": [],
    "version": "%VERSION%",
    "updated": "%TODAY%"
  },
  "includes": [
     {
      "type": "datasource",
      "name": "nested data source",
      "path": "datasource/plugin.json"
    },
  ],
  "dependencies": {
    "grafanaDependency": ">=10.4.0",
    "plugins": []
  }
}

and the datasource plugin.json

❯ cat -p src/datasource/plugin.json
{
  "$schema": "https://raw.githubusercontent.com/grafana/grafana/main/docs/sources/developers/plugins/plugin.schema.json",
  "type": "datasource",
  "name": "Test",
  "id": "academo-test-datasource",
  "metrics": true,
  "backend": true,
  "executable": "gpx_test",
  "info": {
    "description": "",
    "author": {
      "name": "Academo"
    },
    "keywords": ["datasource"],
    "logos": {
      "small": "img/logo.svg",
      "large": "img/logo.svg"
    },
    "links": [],
    "screenshots": [],
    "version": "%VERSION%",
    "updated": "%TODAY%"
  }
}

Let me know how this goes for you.

We’ll consider updating the guide with an advance section

Finally. the zabbix datasource is a known datasource with a bundled backend plugin GitHub - grafana/grafana-zabbix: Zabbix plugin for Grafana dashboard