diff --git a/docs/compatibility/new-frontend-system.md b/docs/compatibility/new-frontend-system.md index 02fc7337ef5..79b87b4abb1 100644 --- a/docs/compatibility/new-frontend-system.md +++ b/docs/compatibility/new-frontend-system.md @@ -74,7 +74,7 @@ This page provides a table listing all the frontend plugins in the Community Plu | @backstage-community/plugin-growthbook | frontend-plugin | true | 1.48.0 | true | [README](https://github.com/backstage/community-plugins/blob/master/workspaces/growthbook-flags/plugins/growthbook/README.md) | | @backstage-community/plugin-healert | frontend-plugin | true | 1.51.0 | | [README](https://github.com/backstage/community-plugins/blob/master/workspaces/healert/plugins/healert/README.md) | | @backstage-community/plugin-ilert | frontend-plugin | | 1.53.0 | | [README](https://github.com/backstage/community-plugins/blob/master/workspaces/ilert/plugins/ilert/README.md) | -| @backstage-community/plugin-jaeger | frontend-plugin | | 1.53.0 | | [README](https://github.com/backstage/community-plugins/blob/master/workspaces/jaeger/plugins/jaeger/README.md) | +| @backstage-community/plugin-jaeger | frontend-plugin | true | 1.53.0 | true | [README](https://github.com/backstage/community-plugins/blob/master/workspaces/jaeger/plugins/jaeger/README.md) | | @backstage-community/plugin-jenkins | frontend-plugin | true | 1.53.0 | true | [README](https://github.com/backstage/community-plugins/blob/master/workspaces/jenkins/plugins/jenkins/README.md) | | @backstage-community/plugin-jfrog-artifactory | frontend-plugin | | 1.52.0 | | [README](https://github.com/backstage/community-plugins/blob/master/workspaces/jfrog-artifactory/plugins/jfrog-artifactory/README.md) | | @backstage-community/plugin-kafka | frontend-plugin | true | 1.49.2 | true | [README](https://github.com/backstage/community-plugins/blob/master/workspaces/kafka/plugins/kafka/README.md) | diff --git a/workspaces/jaeger/.changeset/smooth-donkeys-share.md b/workspaces/jaeger/.changeset/smooth-donkeys-share.md new file mode 100644 index 00000000000..265a386ccc9 --- /dev/null +++ b/workspaces/jaeger/.changeset/smooth-donkeys-share.md @@ -0,0 +1,5 @@ +--- +'@backstage-community/plugin-jaeger': patch +--- + +Added New Frontend System support. The plugin can now be used with the new frontend system using package discovery or by importing from the `/alpha` entrypoint. diff --git a/workspaces/jaeger/plugins/jaeger/README.md b/workspaces/jaeger/plugins/jaeger/README.md index c9736dca124..0de1656aa8d 100644 --- a/workspaces/jaeger/plugins/jaeger/README.md +++ b/workspaces/jaeger/plugins/jaeger/README.md @@ -94,3 +94,44 @@ spec: providesApis: - petstore ``` + +## New Frontend System (Alpha) + +The Jaeger plugin supports the New Frontend System via an `/alpha` export, here's how to use it: + +1. Add the plugin to your app, using either auto discovery or the manual option: + + For auto discovery, add the following to your `app-config.yaml` file: + + ```yaml + app: + packages: all + ``` + + Alternatively, add the plugin manually in your `packages/app(-next)/src/App.tsx`, after all other imports: + + ```tsx + import jaegerPlugin from '@backstage-community/plugin-jaeger/alpha'; + ``` + + ```tsx + export const app = createApp({ + features: [ + catalogPlugin, + catalogImportPlugin, + userSettingsPlugin, + jaegerPlugin, + // ... + ], + }); + ``` + +2. Next, enable the entity content extension in your `app-config.yaml`: + + ```yaml + app: + extensions: + - entity-content:jaeger/entity + ``` + + The `Traces` tab is shown on components annotated with `jaegertracing.io/service`, as described above. diff --git a/workspaces/jaeger/plugins/jaeger/package.json b/workspaces/jaeger/plugins/jaeger/package.json index f6ea26d45eb..d94dfba1dda 100644 --- a/workspaces/jaeger/plugins/jaeger/package.json +++ b/workspaces/jaeger/plugins/jaeger/package.json @@ -5,9 +5,22 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "main": "dist/index.esm.js", - "types": "dist/index.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" + }, + "typesVersions": { + "*": { + "alpha": [ + "src/alpha.ts" + ], + "package.json": [ + "package.json" + ] + } }, "repository": { "type": "git", @@ -35,9 +48,11 @@ "dependencies": { "@backstage-community/plugin-jaeger-common": "workspace:^", "@backstage/catalog-model": "backstage:^", + "@backstage/core-compat-api": "backstage:^", "@backstage/core-components": "backstage:^", "@backstage/core-plugin-api": "backstage:^", "@backstage/errors": "backstage:^", + "@backstage/frontend-plugin-api": "backstage:^", "@backstage/plugin-catalog-react": "backstage:^", "@backstage/theme": "backstage:^", "@material-ui/core": "^4.12.2", diff --git a/workspaces/jaeger/plugins/jaeger/report-alpha.api.md b/workspaces/jaeger/plugins/jaeger/report-alpha.api.md new file mode 100644 index 00000000000..acca6841c6c --- /dev/null +++ b/workspaces/jaeger/plugins/jaeger/report-alpha.api.md @@ -0,0 +1,126 @@ +## API Report File for "@backstage-community/plugin-jaeger" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { AnyApiFactory } from '@backstage/frontend-plugin-api'; +import { AnyRouteRefParams } from '@backstage/frontend-plugin-api'; +import { ApiFactory } from '@backstage/frontend-plugin-api'; +import { Entity } from '@backstage/catalog-model'; +import { ExtensionBlueprintParams } from '@backstage/frontend-plugin-api'; +import { ExtensionDataRef } from '@backstage/frontend-plugin-api'; +import { FilterPredicate } from '@backstage/filter-predicates'; +import { JSX as JSX_2 } from 'react'; +import { JSXElementConstructor } from 'react'; +import { OverridableExtensionDefinition } from '@backstage/frontend-plugin-api'; +import { OverridableFrontendPlugin } from '@backstage/frontend-plugin-api'; +import { ReactElement } from 'react'; +import { RouteRef } from '@backstage/frontend-plugin-api'; + +// @alpha (undocumented) +const _default: OverridableFrontendPlugin< + { + entityContent: RouteRef; + }, + {}, + { + 'api:jaeger': OverridableExtensionDefinition<{ + kind: 'api'; + name: undefined; + config: {}; + configInput: {}; + output: ExtensionDataRef; + inputs: {}; + params: < + TApi, + TImpl extends TApi, + TDeps extends { [name in string]: unknown }, + >( + params: ApiFactory, + ) => ExtensionBlueprintParams; + }>; + 'entity-content:jaeger/entity': OverridableExtensionDefinition<{ + kind: 'entity-content'; + name: 'entity'; + config: { + path: string | undefined; + title: string | undefined; + filter: FilterPredicate | undefined; + group: string | false | undefined; + icon: string | undefined; + }; + configInput: { + path?: string | undefined; + title?: string | undefined; + filter?: FilterPredicate | undefined; + group?: string | false | undefined; + icon?: string | undefined; + }; + output: + | ExtensionDataRef + | ExtensionDataRef + | ExtensionDataRef< + RouteRef, + 'core.routing.ref', + { + optional: true; + } + > + | ExtensionDataRef< + (entity: Entity) => boolean, + 'catalog.entity-filter-function', + { + optional: true; + } + > + | ExtensionDataRef< + string, + 'catalog.entity-filter-expression', + { + optional: true; + } + > + | ExtensionDataRef + | ExtensionDataRef< + string, + 'catalog.entity-content-group', + { + optional: true; + } + > + | ExtensionDataRef< + string | ReactElement>, + 'catalog.entity-content-icon', + { + optional: true; + } + >; + inputs: {}; + params: { + defaultPath?: [Error: `Use the 'path' param instead`]; + path: string; + defaultTitle?: [Error: `Use the 'title' param instead`]; + title: string; + defaultGroup?: [Error: `Use the 'group' param instead`]; + group?: + | ( + | 'development' + | 'deployment' + | 'overview' + | 'documentation' + | 'operation' + | 'observability' + ) + | (string & {}); + icon?: string | ReactElement; + loader: () => Promise; + routeRef?: RouteRef; + filter?: string | FilterPredicate | ((entity: Entity) => boolean); + }; + }>; + } +>; +export default _default; + +// (No @packageDocumentation comment for this package) +``` diff --git a/workspaces/jaeger/plugins/jaeger/src/alpha.test.ts b/workspaces/jaeger/plugins/jaeger/src/alpha.test.ts new file mode 100644 index 00000000000..03d1ad228a7 --- /dev/null +++ b/workspaces/jaeger/plugins/jaeger/src/alpha.test.ts @@ -0,0 +1,26 @@ +/* + * Copyright 2026 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import jaegerPlugin from './alpha'; + +describe('jaeger alpha plugin', () => { + it('should register the API and entity content extensions', () => { + expect(jaegerPlugin.pluginId).toBe('jaeger'); + expect(jaegerPlugin.getExtension('api:jaeger')).toBeDefined(); + expect( + jaegerPlugin.getExtension('entity-content:jaeger/entity'), + ).toBeDefined(); + }); +}); diff --git a/workspaces/jaeger/plugins/jaeger/src/alpha.ts b/workspaces/jaeger/plugins/jaeger/src/alpha.ts new file mode 100644 index 00000000000..85e0abebe04 --- /dev/null +++ b/workspaces/jaeger/plugins/jaeger/src/alpha.ts @@ -0,0 +1,30 @@ +/* + * Copyright 2026 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { convertLegacyRouteRefs } from '@backstage/core-compat-api'; +import { createFrontendPlugin } from '@backstage/frontend-plugin-api'; +import { jaegerApiExtension, entityJaegerContent } from './alpha/index'; +import { rootRouteRef } from './routes'; + +/** + * @alpha + */ +export default createFrontendPlugin({ + pluginId: 'jaeger', + routes: convertLegacyRouteRefs({ + entityContent: rootRouteRef, + }), + extensions: [jaegerApiExtension, entityJaegerContent], +}); diff --git a/workspaces/jaeger/plugins/jaeger/src/alpha/apis.ts b/workspaces/jaeger/plugins/jaeger/src/alpha/apis.ts new file mode 100644 index 00000000000..74efe2ad1dc --- /dev/null +++ b/workspaces/jaeger/plugins/jaeger/src/alpha/apis.ts @@ -0,0 +1,37 @@ +/* + * Copyright 2026 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { ApiBlueprint } from '@backstage/frontend-plugin-api'; +import { jaegerApiRef, JaegerClient } from '../api'; +import { discoveryApiRef, fetchApiRef } from '@backstage/core-plugin-api'; + +/** + * @alpha + */ +export const jaegerApiExtension = ApiBlueprint.make({ + params: defineParams => + defineParams({ + api: jaegerApiRef, + deps: { + discoveryApi: discoveryApiRef, + fetchApi: fetchApiRef, + }, + factory: ({ discoveryApi, fetchApi }) => + new JaegerClient({ + discoveryApi, + fetchApi, + }), + }), +}); diff --git a/workspaces/jaeger/plugins/jaeger/src/alpha/entityContent.tsx b/workspaces/jaeger/plugins/jaeger/src/alpha/entityContent.tsx new file mode 100644 index 00000000000..8a2b6eee60a --- /dev/null +++ b/workspaces/jaeger/plugins/jaeger/src/alpha/entityContent.tsx @@ -0,0 +1,39 @@ +/* + * Copyright 2026 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { + compatWrapper, + convertLegacyRouteRef, +} from '@backstage/core-compat-api'; +import { EntityContentBlueprint } from '@backstage/plugin-catalog-react/alpha'; +import { rootRouteRef } from '../routes'; +import { isJaegerAvailable } from '../utils'; + +/** + * @alpha + */ +export const entityJaegerContent = EntityContentBlueprint.make({ + name: 'entity', + params: { + path: '/jaeger', + title: 'Traces', + filter: isJaegerAvailable, + routeRef: convertLegacyRouteRef(rootRouteRef), + loader: () => + import('../components/JaegerComponent').then(m => + compatWrapper(), + ), + }, +}); diff --git a/workspaces/jaeger/plugins/jaeger/src/alpha/index.ts b/workspaces/jaeger/plugins/jaeger/src/alpha/index.ts new file mode 100644 index 00000000000..b471bda47ab --- /dev/null +++ b/workspaces/jaeger/plugins/jaeger/src/alpha/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2026 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export { jaegerApiExtension } from './apis'; +export { entityJaegerContent } from './entityContent'; diff --git a/workspaces/jaeger/yarn.lock b/workspaces/jaeger/yarn.lock index e31822af40e..904a91d9a1f 100644 --- a/workspaces/jaeger/yarn.lock +++ b/workspaces/jaeger/yarn.lock @@ -1808,10 +1808,12 @@ __metadata: "@backstage/catalog-model": "backstage:^" "@backstage/cli": "backstage:^" "@backstage/core-app-api": "backstage:^" + "@backstage/core-compat-api": "backstage:^" "@backstage/core-components": "backstage:^" "@backstage/core-plugin-api": "backstage:^" "@backstage/dev-utils": "backstage:^" "@backstage/errors": "backstage:^" + "@backstage/frontend-plugin-api": "backstage:^" "@backstage/plugin-catalog-react": "backstage:^" "@backstage/test-utils": "backstage:^" "@backstage/theme": "backstage:^" @@ -2530,7 +2532,7 @@ __metadata: languageName: node linkType: hard -"@backstage/core-compat-api@npm:^0.5.13": +"@backstage/core-compat-api@backstage:^::backstage=1.53.0&npm=0.5.13, @backstage/core-compat-api@npm:^0.5.13": version: 0.5.13 resolution: "@backstage/core-compat-api@npm:0.5.13" dependencies: @@ -2713,7 +2715,7 @@ __metadata: languageName: node linkType: hard -"@backstage/frontend-plugin-api@npm:^0.17.3": +"@backstage/frontend-plugin-api@backstage:^::backstage=1.53.0&npm=0.17.3, @backstage/frontend-plugin-api@npm:^0.17.3": version: 0.17.3 resolution: "@backstage/frontend-plugin-api@npm:0.17.3" dependencies: