Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plugin Meta Extractor: Initial version #805

Merged
merged 57 commits into from
May 3, 2024
Merged

Plugin Meta Extractor: Initial version #805

merged 57 commits into from
May 3, 2024

Conversation

mckn
Copy link
Collaborator

@mckn mckn commented Mar 6, 2024

What is this?

The Plugin Meta Extractor (@grafana/plugin-meta-extractor) is a new package that can be used to extract meta-information from the plugin's source code. The goal is to be able to automatically generate static information about the plugin without needing the plugin-dev to care about these (e.g. extension point information).
View README
PR for adding the plugin to our webpack config

What kind of meta-data?

Currently we only extract basic information about the extensions that the plugin registers.

Supported plugin format

The tool currently only recognises extensions that are registered in the following format:

// src/module.ts
export const plugin = new AppPlugin<{}>()
  .setRootPage(App)
  .configureExtensionLink<PluginExtensionPanelContext>({ 
    // ...
  })
  .configureExtensionLink<PluginExtensionPanelContext>({ 
    // ...
  });

How does it work?

It uses the typescript AST to find usages of the functions that register extensions. The package also exposes a Webpack plugin that can be used to generate a meta-info file during the build of the plugin.

How to use it?

CLI

  1. Check out the branch
  2. Install dependencies - npm install
  3. Go to the package - cd packages/plugin-meta-extractor
  4. Build the package - npm run build
  5. Run the binary - ./dist/bin/run.js ~/my-grafana-plugin/src/module.ts _(prints to the console)
  6. Use npm link to depend on the local version of the package while developing

Code

import { extractPluginMeta } from '@grafana/plugin-meta-extractor';

const entryPoint = `${PLUGIN_ROOT}/src/module.ts`;
const pluginMeta = extractPluginMeta(entryPoint); // see the format of the data below

Webpack

import { GrafanaPluginMetaExtractor } from '@grafana/plugin-meta-extractor';

export default {
 // ...
 plugins: [
  // updates the `generated` property of the plugin.json in the dist directory
  new GrafanaPluginMetaExtractor(),
  // ...
  ]
};

What data does it give back?

It always returns with a valid JSON in the following format:

{
  "extensions": [
    {
      "type": "link",
      "extensionPointId": "grafana/dashboard/panel/menu",
      "title": "Open from time series or pie charts (path)",
      "description": "This link will only be visible on time series and pie charts"
    },
    {
      "type": "link",
      "extensionPointId": "grafana/dashboard/panel/menu",
      "title": "Open from time series or pie charts (onClick)",
      "description": "This link will only be visible on time series and pie charts"
    }
  ]
}

Todo

  • Use the webpack config entry parameter and handle the different scenarios
    • A single string: entry: "./module.ts"
    • An array of strings: entry: ["./module.ts", "./datasource/module.ts"]
    • An object of entries: entry: { module: "./module.ts" }
    • A promise resolving any of the above
  • Test it with all plugin versions (app, panel, datasource)
  • Only update the plugin.json if necessary
📦 Published PR as canary version: Canary Versions

✨ Test out this PR locally via:

npm install @grafana/plugin-meta-extractor@0.0.1-canary.805.f998cc3.0
# or 
yarn add @grafana/plugin-meta-extractor@0.0.1-canary.805.f998cc3.0

@mckn mckn changed the title Creating PME tool to extract information from frontend part of plugins PME: First version of the plugin meta extractor tool Mar 6, 2024
@mckn mckn added the no-changelog Don't include in changelog and version calculations label Mar 7, 2024
@leventebalogh leventebalogh changed the title PME: First version of the plugin meta extractor tool Plugin Meta Extractor: Initial version Apr 9, 2024
@grafana grafana deleted a comment from github-actions bot Apr 9, 2024
@leventebalogh leventebalogh marked this pull request as ready for review April 9, 2024 14:27
@leventebalogh leventebalogh requested a review from a team as a code owner April 9, 2024 14:27
@leventebalogh leventebalogh requested review from jackw and removed request for a team April 9, 2024 14:27
@grafana grafana deleted a comment from github-actions bot Apr 9, 2024
Copy link

github-actions bot commented Apr 10, 2024

Hello! 👋 This repository uses Auto for releasing packages using PR labels.

✨ This PR can be merged and will trigger a new patch release.
NOTE: When merging a PR with the release label please avoid merging another PR. For further information see here.

Copy link
Collaborator

@jackw jackw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work on this @mckn and @leventebalogh ! 👏

I've left a few comments for consideration.

packages/pme/package.json Outdated Show resolved Hide resolved
packages/plugin-meta-extractor/README.md Outdated Show resolved Hide resolved
packages/plugin-meta-extractor/README.md Outdated Show resolved Hide resolved
packages/plugin-meta-extractor/package.json Outdated Show resolved Hide resolved
packages/plugin-meta-extractor/tsconfig.json Outdated Show resolved Hide resolved
packages/plugin-meta-extractor/src/webpack-plugin.ts Outdated Show resolved Hide resolved
packages/plugin-meta-extractor/src/webpack-plugin.ts Outdated Show resolved Hide resolved
packages/plugin-meta-extractor/src/webpack-plugin.ts Outdated Show resolved Hide resolved
packages/plugin-meta-extractor/src/webpack-plugin.ts Outdated Show resolved Hide resolved
packages/plugin-meta-extractor/src/webpack-plugin.ts Outdated Show resolved Hide resolved
Copy link
Contributor

@sunker sunker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think this looks really cool. Awesome work on this!
Some high level questions from me.

In real world scenarios today, can it be the case that an app plugin conditionally configures an extension? For example only registering an extension link in case a certain feature toggle is enabled. In that case, will it be problematic that extensions are extracted at build time rather than runtime?

If I understand correctly, we can traverse the AST also in the case the entry file is a javascript file. So in theory we could support extraction also for javascript plugins? It seems we use the typechecker in a few places in the code. Are we targeting typescript plugins only?

I understand this is still in experimental phase, but I'm curious to know how this fits into the story around registering extensions. Do you think using this tool to extract extensions built time could become a requirement, or would we support extracting them runtime too? How does this relate to the reactive extensions registry feature (that is not merged yet)?

@marefr
Copy link
Member

marefr commented Apr 10, 2024

Are you imagine the generated content to go into the plugin.json or how are you imagine this to be consumed within grafana?

@leventebalogh
Copy link
Collaborator

leventebalogh commented Apr 10, 2024

@sunker Thanks for the questions!

In real world scenarios today, can it be the case that an app plugin conditionally configures an extension? For example only registering an extension link in case a certain feature toggle is enabled. In that case, will it be problematic that extensions are extracted at build time rather than runtime?

Unfortunately we don't yet support every dynamic pattern with this tool for registering extensions from a plugin (we only support basic chained method calls on the AppPlugin instance at this point) - however we are planning to do so in the future.
The plugin.generated.json file that we generate will only give information to Grafana core about when a plugin should be preloaded. In case a plugin uses some runtime conditions to decide if it registers an extension, the tool should record the static meta-data for the extension regardless, which means that the plugin will always be preloaded for that extension-point, and it can decide during runtime if it registers the extension.

(Something like this can also be done in the chained-method-call pattern: returning undefined from the configure() function of the extension will hide the extension.)

If I understand correctly, we can traverse the AST also in the case the entry file is a javascript file. So in theory we could support extraction also for javascript plugins? It seems we use the typechecker in a few places in the code. Are we targeting typescript plugins only?

I am afraid this will only work properly for plugins written in typescript at this point (module.ts / module.tsx).

I understand this is still in experimental phase, but I'm curious to know how this fits into the story around registering extensions. Do you think using this tool to extract extensions built time could become a requirement, or would we support extracting them runtime too? How does this relate to the reactive extensions registry feature (that is not merged yet)?

This tool is planned to be used seamlessly in our plugin build configuration that is provided by create-plugin, however the meta-info it generates will only be used to decide when a plugin should be preloaded. (Plugins will still be able to dynamically register an extension point, for these scenarios - at least for now - we will always need to preload the plugin.)

@leventebalogh
Copy link
Collaborator

@marefr

Are you imagine the generated content to go into the plugin.json or how are you imagine this to be consumed within grafana?

Hmm, after discussing this with @jackw and @mckn we decided to not put it in plugin.json, but to create a separate file - for now called plugin.generated.json -, just to make plugin devs more aware that this is something that shouldn't be edited manually.

Copy link
Collaborator Author

@mckn mckn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this looks great! A question regarding the webpack plugin. Will it update the plugin.json in the /dist folder or the one in /src?

packages/plugin-meta-extractor/src/webpack-plugin.ts Outdated Show resolved Hide resolved
@leventebalogh
Copy link
Collaborator

I think this looks great! A question regarding the webpack plugin. Will it update the plugin.json in the /dist folder or the one in /src?

That's a good question. It only updates the one in the /dist folder and leaves the one in /src intact. (When running npm run dev it updates the one in the dist folder on every code change.)

@leventebalogh leventebalogh requested a review from jackw May 2, 2024 11:00
Copy link
Collaborator

@jackw jackw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome work on this @mckn and @leventebalogh . 🚀

packages/plugin-meta-extractor/README.md Outdated Show resolved Hide resolved
packages/plugin-meta-extractor/README.md Outdated Show resolved Hide resolved
packages/plugin-meta-extractor/README.md Outdated Show resolved Hide resolved
packages/plugin-meta-extractor/src/bin/run.ts Outdated Show resolved Hide resolved
packages/plugin-meta-extractor/README.md Outdated Show resolved Hide resolved
leventebalogh and others added 5 commits May 3, 2024 08:17
Co-authored-by: Jack Westbrook <jack.westbrook@gmail.com>
Co-authored-by: Jack Westbrook <jack.westbrook@gmail.com>
Co-authored-by: Jack Westbrook <jack.westbrook@gmail.com>
Co-authored-by: Jack Westbrook <jack.westbrook@gmail.com>
Co-authored-by: Jack Westbrook <jack.westbrook@gmail.com>
@leventebalogh leventebalogh merged commit bc81c06 into main May 3, 2024
17 checks passed
@leventebalogh leventebalogh deleted the mckn/pme-tool branch May 3, 2024 07:04
@grafana-plugins-platform-bot
Copy link

🚀 PR was released in @grafana/create-plugin@4.9.1, @grafana/plugin-meta-extractor@0.0.1 🚀

@grafana-plugins-platform-bot grafana-plugins-platform-bot bot added the released This issue/pull request has been released. label May 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
patch Increment the patch version when merged release Create a release when this pr is merged released This issue/pull request has been released.
Projects
Development

Successfully merging this pull request may close these issues.

None yet

6 participants