The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
grafana/public/app/features/plugins/extensions/usePluginComponents.tsx

79 lines
2.7 KiB

import { useMemo } from 'react';
import { useObservable } from 'react-use';
Plugin Extensions: Require meta-data to be defined in `plugin.json` during development mode (#93429) * feat: add extensions to the backend plugin model * feat: update the frontend plugin types * feat(pluginContext): return a `null` if there is no context found This will be necessary to understand if a certain hook is running inside a plugin context or not. * feat: add utility functions for checking extension configs * tests: fix failing tests due to the type updates * feat(AddedComponentsRegistry): validate plugin meta-info * feat(AddedLinksRegistry): validate meta-info * feat(ExposedComponentsRegistry): validate meta-info * feat(usePluginComponent): add meta-info validation * feat(usePluginComponents): add meta-info validation * feat(usePluginLinks): add meta-info validation * fix: only validate meta-info in registries if dev mode is enabled * tests: add unit tests for the restrictions functionality * tests: fix Go tests * fix(tests): revert accidental changes * fix: run goimports * fix: api tests * add nested app so that meta data can bested e2e tested * refactor(types): extract the ExtensionInfo into a separate type * refactor(extensions/utils): use Array.prototype.some() instead of .find() * refactor(usePluginLinks): update warning message * feat(usePluginExtensions()): validate plugin meta-info * Wip * fix(e2e): E2E tests for extensions * fix(extensions): allow multiple "/" slashes in the extension point id * fix(extensions/validators): stop validating the plugin id pattern --------- Co-authored-by: Erik Sundell <erik.sundell87@gmail.com>
8 months ago
import { usePluginContext } from '@grafana/data';
import {
UsePluginComponentOptions,
UsePluginComponentsResult,
} from '@grafana/runtime/src/services/pluginExtensions/getPluginExtensions';
import { useAddedComponentsRegistry } from './ExtensionRegistriesContext';
import * as errors from './errors';
PluginExtension: Added debug log (#94146) * wip * add simple scenes object with logs panel * return hardcoded log message from runtime ds * simplify log entry * use log in links registry * wired the log together. * wip * Connected the extensions log to the runtime datasource to steam logs * wired the other registies. * implemented child function. * set right field type on labels * set meta type * using the logger in various places. * added type of onclick. * removed time picker. * removed imports. * passing log to functions where they are needed. * moved scene into admin page. * minor improvement to the message. * added possibility to update query with values based on the data. * added filter suppoert. * wip * wip * fixed so extension points are displayed. * use log level from grafana data * fixed bugs with the filtering. * Fixed some logs. * only register extensions page in development mode. * fixed filtering. * added on click debug log. * PluginExtensions: Add debug log to Grafana (Rewrite to scenes-react) (#93954) * refactoring. * simplify it even more. * Update public/app/features/plugins/extensions/logs/LogViewer.tsx Co-authored-by: Erik Sundell <erik.sundell87@gmail.com> * used VizGridLayout instead of VizGrid component. * Fixed feedback and fixed bug in filtering logic. * fixed another nit. * empty string instead of title. * Added tests and fixed error. * added test file. * regenerated yarn.lock * Update public/app/features/plugins/extensions/logs/filterTransformation.test.ts Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com> * fixed nit. * more nits. * added more test cases. * simplified filtering logic. * removed unused dep. * defined broadcast channel in jest setup. * added tests for datasource. * fixed failed tests. * fixed tests. * fixing go lint issue. * silent go lint. * fixed lint issue. --------- Co-authored-by: Erik Sundell <erik.sundell87@gmail.com> Co-authored-by: Torkel Ödegaard <torkel@grafana.com> Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com>
7 months ago
import { log } from './logs/log';
import { useLoadAppPlugins } from './useLoadAppPlugins';
import { getExtensionPointPluginDependencies, isGrafanaDevMode } from './utils';
import { isExtensionPointIdValid, isExtensionPointMetaInfoMissing } from './validators';
// Returns an array of component extensions for the given extension point
export function usePluginComponents<Props extends object = {}>({
limitPerPlugin,
extensionPointId,
}: UsePluginComponentOptions): UsePluginComponentsResult<Props> {
const registry = useAddedComponentsRegistry();
const registryState = useObservable(registry.asObservable());
Plugin Extensions: Require meta-data to be defined in `plugin.json` during development mode (#93429) * feat: add extensions to the backend plugin model * feat: update the frontend plugin types * feat(pluginContext): return a `null` if there is no context found This will be necessary to understand if a certain hook is running inside a plugin context or not. * feat: add utility functions for checking extension configs * tests: fix failing tests due to the type updates * feat(AddedComponentsRegistry): validate plugin meta-info * feat(AddedLinksRegistry): validate meta-info * feat(ExposedComponentsRegistry): validate meta-info * feat(usePluginComponent): add meta-info validation * feat(usePluginComponents): add meta-info validation * feat(usePluginLinks): add meta-info validation * fix: only validate meta-info in registries if dev mode is enabled * tests: add unit tests for the restrictions functionality * tests: fix Go tests * fix(tests): revert accidental changes * fix: run goimports * fix: api tests * add nested app so that meta data can bested e2e tested * refactor(types): extract the ExtensionInfo into a separate type * refactor(extensions/utils): use Array.prototype.some() instead of .find() * refactor(usePluginLinks): update warning message * feat(usePluginExtensions()): validate plugin meta-info * Wip * fix(e2e): E2E tests for extensions * fix(extensions): allow multiple "/" slashes in the extension point id * fix(extensions/validators): stop validating the plugin id pattern --------- Co-authored-by: Erik Sundell <erik.sundell87@gmail.com>
8 months ago
const pluginContext = usePluginContext();
const { isLoading: isLoadingAppPlugins } = useLoadAppPlugins(getExtensionPointPluginDependencies(extensionPointId));
return useMemo(() => {
Plugin Extensions: Require meta-data to be defined in `plugin.json` during development mode (#93429) * feat: add extensions to the backend plugin model * feat: update the frontend plugin types * feat(pluginContext): return a `null` if there is no context found This will be necessary to understand if a certain hook is running inside a plugin context or not. * feat: add utility functions for checking extension configs * tests: fix failing tests due to the type updates * feat(AddedComponentsRegistry): validate plugin meta-info * feat(AddedLinksRegistry): validate meta-info * feat(ExposedComponentsRegistry): validate meta-info * feat(usePluginComponent): add meta-info validation * feat(usePluginComponents): add meta-info validation * feat(usePluginLinks): add meta-info validation * fix: only validate meta-info in registries if dev mode is enabled * tests: add unit tests for the restrictions functionality * tests: fix Go tests * fix(tests): revert accidental changes * fix: run goimports * fix: api tests * add nested app so that meta data can bested e2e tested * refactor(types): extract the ExtensionInfo into a separate type * refactor(extensions/utils): use Array.prototype.some() instead of .find() * refactor(usePluginLinks): update warning message * feat(usePluginExtensions()): validate plugin meta-info * Wip * fix(e2e): E2E tests for extensions * fix(extensions): allow multiple "/" slashes in the extension point id * fix(extensions/validators): stop validating the plugin id pattern --------- Co-authored-by: Erik Sundell <erik.sundell87@gmail.com>
8 months ago
// For backwards compatibility we don't enable restrictions in production or when the hook is used in core Grafana.
const enableRestrictions = isGrafanaDevMode() && pluginContext;
const components: Array<React.ComponentType<Props>> = [];
const extensionsByPlugin: Record<string, number> = {};
Plugin Extensions: Require meta-data to be defined in `plugin.json` during development mode (#93429) * feat: add extensions to the backend plugin model * feat: update the frontend plugin types * feat(pluginContext): return a `null` if there is no context found This will be necessary to understand if a certain hook is running inside a plugin context or not. * feat: add utility functions for checking extension configs * tests: fix failing tests due to the type updates * feat(AddedComponentsRegistry): validate plugin meta-info * feat(AddedLinksRegistry): validate meta-info * feat(ExposedComponentsRegistry): validate meta-info * feat(usePluginComponent): add meta-info validation * feat(usePluginComponents): add meta-info validation * feat(usePluginLinks): add meta-info validation * fix: only validate meta-info in registries if dev mode is enabled * tests: add unit tests for the restrictions functionality * tests: fix Go tests * fix(tests): revert accidental changes * fix: run goimports * fix: api tests * add nested app so that meta data can bested e2e tested * refactor(types): extract the ExtensionInfo into a separate type * refactor(extensions/utils): use Array.prototype.some() instead of .find() * refactor(usePluginLinks): update warning message * feat(usePluginExtensions()): validate plugin meta-info * Wip * fix(e2e): E2E tests for extensions * fix(extensions): allow multiple "/" slashes in the extension point id * fix(extensions/validators): stop validating the plugin id pattern --------- Co-authored-by: Erik Sundell <erik.sundell87@gmail.com>
8 months ago
const pluginId = pluginContext?.meta.id ?? '';
PluginExtension: Added debug log (#94146) * wip * add simple scenes object with logs panel * return hardcoded log message from runtime ds * simplify log entry * use log in links registry * wired the log together. * wip * Connected the extensions log to the runtime datasource to steam logs * wired the other registies. * implemented child function. * set right field type on labels * set meta type * using the logger in various places. * added type of onclick. * removed time picker. * removed imports. * passing log to functions where they are needed. * moved scene into admin page. * minor improvement to the message. * added possibility to update query with values based on the data. * added filter suppoert. * wip * wip * fixed so extension points are displayed. * use log level from grafana data * fixed bugs with the filtering. * Fixed some logs. * only register extensions page in development mode. * fixed filtering. * added on click debug log. * PluginExtensions: Add debug log to Grafana (Rewrite to scenes-react) (#93954) * refactoring. * simplify it even more. * Update public/app/features/plugins/extensions/logs/LogViewer.tsx Co-authored-by: Erik Sundell <erik.sundell87@gmail.com> * used VizGridLayout instead of VizGrid component. * Fixed feedback and fixed bug in filtering logic. * fixed another nit. * empty string instead of title. * Added tests and fixed error. * added test file. * regenerated yarn.lock * Update public/app/features/plugins/extensions/logs/filterTransformation.test.ts Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com> * fixed nit. * more nits. * added more test cases. * simplified filtering logic. * removed unused dep. * defined broadcast channel in jest setup. * added tests for datasource. * fixed failed tests. * fixed tests. * fixing go lint issue. * silent go lint. * fixed lint issue. --------- Co-authored-by: Erik Sundell <erik.sundell87@gmail.com> Co-authored-by: Torkel Ödegaard <torkel@grafana.com> Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com>
7 months ago
const pointLog = log.child({
pluginId,
extensionPointId,
});
Plugin Extensions: Require meta-data to be defined in `plugin.json` during development mode (#93429) * feat: add extensions to the backend plugin model * feat: update the frontend plugin types * feat(pluginContext): return a `null` if there is no context found This will be necessary to understand if a certain hook is running inside a plugin context or not. * feat: add utility functions for checking extension configs * tests: fix failing tests due to the type updates * feat(AddedComponentsRegistry): validate plugin meta-info * feat(AddedLinksRegistry): validate meta-info * feat(ExposedComponentsRegistry): validate meta-info * feat(usePluginComponent): add meta-info validation * feat(usePluginComponents): add meta-info validation * feat(usePluginLinks): add meta-info validation * fix: only validate meta-info in registries if dev mode is enabled * tests: add unit tests for the restrictions functionality * tests: fix Go tests * fix(tests): revert accidental changes * fix: run goimports * fix: api tests * add nested app so that meta data can bested e2e tested * refactor(types): extract the ExtensionInfo into a separate type * refactor(extensions/utils): use Array.prototype.some() instead of .find() * refactor(usePluginLinks): update warning message * feat(usePluginExtensions()): validate plugin meta-info * Wip * fix(e2e): E2E tests for extensions * fix(extensions): allow multiple "/" slashes in the extension point id * fix(extensions/validators): stop validating the plugin id pattern --------- Co-authored-by: Erik Sundell <erik.sundell87@gmail.com>
8 months ago
if (enableRestrictions && !isExtensionPointIdValid({ extensionPointId, pluginId })) {
pointLog.error(errors.INVALID_EXTENSION_POINT_ID);
Plugin Extensions: Require meta-data to be defined in `plugin.json` during development mode (#93429) * feat: add extensions to the backend plugin model * feat: update the frontend plugin types * feat(pluginContext): return a `null` if there is no context found This will be necessary to understand if a certain hook is running inside a plugin context or not. * feat: add utility functions for checking extension configs * tests: fix failing tests due to the type updates * feat(AddedComponentsRegistry): validate plugin meta-info * feat(AddedLinksRegistry): validate meta-info * feat(ExposedComponentsRegistry): validate meta-info * feat(usePluginComponent): add meta-info validation * feat(usePluginComponents): add meta-info validation * feat(usePluginLinks): add meta-info validation * fix: only validate meta-info in registries if dev mode is enabled * tests: add unit tests for the restrictions functionality * tests: fix Go tests * fix(tests): revert accidental changes * fix: run goimports * fix: api tests * add nested app so that meta data can bested e2e tested * refactor(types): extract the ExtensionInfo into a separate type * refactor(extensions/utils): use Array.prototype.some() instead of .find() * refactor(usePluginLinks): update warning message * feat(usePluginExtensions()): validate plugin meta-info * Wip * fix(e2e): E2E tests for extensions * fix(extensions): allow multiple "/" slashes in the extension point id * fix(extensions/validators): stop validating the plugin id pattern --------- Co-authored-by: Erik Sundell <erik.sundell87@gmail.com>
8 months ago
}
if (enableRestrictions && isExtensionPointMetaInfoMissing(extensionPointId, pluginContext)) {
pointLog.error(errors.EXTENSION_POINT_META_INFO_MISSING);
Plugin Extensions: Require meta-data to be defined in `plugin.json` during development mode (#93429) * feat: add extensions to the backend plugin model * feat: update the frontend plugin types * feat(pluginContext): return a `null` if there is no context found This will be necessary to understand if a certain hook is running inside a plugin context or not. * feat: add utility functions for checking extension configs * tests: fix failing tests due to the type updates * feat(AddedComponentsRegistry): validate plugin meta-info * feat(AddedLinksRegistry): validate meta-info * feat(ExposedComponentsRegistry): validate meta-info * feat(usePluginComponent): add meta-info validation * feat(usePluginComponents): add meta-info validation * feat(usePluginLinks): add meta-info validation * fix: only validate meta-info in registries if dev mode is enabled * tests: add unit tests for the restrictions functionality * tests: fix Go tests * fix(tests): revert accidental changes * fix: run goimports * fix: api tests * add nested app so that meta data can bested e2e tested * refactor(types): extract the ExtensionInfo into a separate type * refactor(extensions/utils): use Array.prototype.some() instead of .find() * refactor(usePluginLinks): update warning message * feat(usePluginExtensions()): validate plugin meta-info * Wip * fix(e2e): E2E tests for extensions * fix(extensions): allow multiple "/" slashes in the extension point id * fix(extensions/validators): stop validating the plugin id pattern --------- Co-authored-by: Erik Sundell <erik.sundell87@gmail.com>
8 months ago
return {
isLoading: false,
components: [],
};
}
if (isLoadingAppPlugins) {
return {
isLoading: true,
components: [],
};
}
for (const registryItem of registryState?.[extensionPointId] ?? []) {
const { pluginId } = registryItem;
// Only limit if the `limitPerPlugin` is set
if (limitPerPlugin && extensionsByPlugin[pluginId] >= limitPerPlugin) {
continue;
}
if (extensionsByPlugin[pluginId] === undefined) {
extensionsByPlugin[pluginId] = 0;
}
components.push(registryItem.component as React.ComponentType<Props>);
extensionsByPlugin[pluginId] += 1;
}
return {
isLoading: false,
components,
};
}, [extensionPointId, limitPerPlugin, pluginContext, registryState, isLoadingAppPlugins]);
}