Skip to content

tech-insights: Unable to create custom fact retriever #5798

@jmpinto-critical

Description

@jmpinto-critical

Workspace

tech-insights

📜 Description

I followed the documentation present here and here and am having some issues creating a custom fact retriever.

👍 Expected behavior

It should show the custom fact I introduced in the Tech Insights view:

Image

👎 Actual Behavior with Screenshots

I get the following error in the backstage logs:

Image

With the corresponding behavior in the Backstage UI:

Image

👟 Reproduction steps

  1. Add the backend plugins:
    "@backstage-community/plugin-tech-insights-backend": "^2.4.1",
    "@backstage-community/plugin-tech-insights-backend-module-jsonfc": "^0.6.1",
    "@backstage-community/plugin-tech-insights-node": "^2.5.1",
  1. Add the code for the custom fact retriever as stated in the documentation links mentioned previously:
// packages/backend/src/index.ts

import { FactRetriever, techInsightsFactRetrieversExtensionPoint } from '@backstage-community/plugin-tech-insights-node';
import { CatalogClient } from '@backstage/catalog-client';

export const myFactRetriever: FactRetriever = {
  id: 'documentation-number-factretriever', // unique identifier of the fact retriever
  version: '1.0.0', // SemVer version number of this fact retriever schema. This should be incremented if the implementation changes
  entityFilter: [{ kind: 'service' }], // EntityFilter to be used in the future (creating checks, graphs etc.) to figure out which entities this fact retrieves data for.
  schema: {
    // Name/identifier of an individual fact that this retriever returns
    examplenumberfact: {
      type: 'integer', // Type of the fact
      description: 'A fact of a number', // Description of the fact
    },
  },
  handler: async (ctx:any) => {
    // Handler function that retrieves the fact
    const { discovery, config, logger, auth } = ctx;

    const { token } = await auth.getPluginRequestToken({
      onBehalfOf: await auth.getOwnServiceCredentials(),
      targetPluginId: 'catalog',
    });

    const catalogClient = new CatalogClient({
      discoveryApi: discovery,
    });
    const entities = await catalogClient.getEntities(
      {
        filter: [{ kind: 'component' }],
      },
      { token },
    );
    /**
     * snip: Do complex logic to retrieve facts from external system or calculate fact values
     */

    // Respond with an array of entity/fact values
    return entities.items.map((it:any) => {
      return {
        // Entity information that this fact relates to
        entity: {
          namespace: it.metadata.namespace,
          kind: it.kind,
          name: it.metadata.name,
        },

        // All facts that this retriever returns
        facts: {
          examplenumberfact: 2,
        },
        // (optional) timestamp to use as a Luxon DateTime object
      };
    });
  },
};

export const techInsightsModuleMyFactRetriever = createBackendModule({
  pluginId: 'tech-insights',
  moduleId: 'my-fact-retriever',
  register(reg:any) {
    reg.registerInit({
      deps: {
        providers: techInsightsFactRetrieversExtensionPoint,
      },
      async init({ providers }:any) {
        providers.addFactRetrievers({
          myFactRetriever,
        });
      },
    });
  },
});

backend.add(import('@backstage-community/plugin-tech-insights-backend'));
backend.add(import('@backstage-community/plugin-tech-insights-backend-module-jsonfc'));
backend.add(techInsightsModuleMyFactRetriever);

Add the necessary configuration to app-config.yaml as stated in the documentation mentioned previously:

techInsights:
  factRetrievers:
    entityMetadataFactRetriever:
      cadence: '*/15 * * * *'  # Every 15 minutes
      lifecycle: 
        timeToLive: { weeks: 2 }
    entityOwnershipFactRetriever:
      cadence: '0 2 * * *'     # Daily at 2 AM
      lifecycle: 
        maxItems: 10
    techdocsFactRetriever:
      cadence: '0 */6 * * *'   # Every 6 hours
      lifecycle:
        timeToLive: { days: 30 }
    documentation-number-factretriever:
      cadence: '*/15 * * * *'   # Every 15 minutes
      lifecycle:
        timeToLive: { days: 2 }
  factChecker:
    checks:
      groupOwnerCheck:
        type: json-rules-engine
        name: 'Group Owner Check'
        description: 'Verifies that a component has a group owner'
        factIds:
          - entityOwnershipFactRetriever
        rule:
          conditions:
            all:
              - fact: hasGroupOwner
                operator: equal
                value: true
      titleCheck:
        type: json-rules-engine
        name: 'Entity Title Check'
        description: 'Verifies that entities have descriptive titles'
        factIds:
          - entityMetadataFactRetriever
        rule:
          conditions:
            all:
              - fact: hasTitle
                operator: equal
                value: true
              - fact: hasDescription
                operator: equal
                value: true
      myCustomCheck:
        type: json-rules-engine
        name: 'Repository Quality Standards'
        description: 'Ensures repositories meet basic quality standards'
        factIds:
          - documentation-number-factretriever
        rule:
          conditions:
            all:
              - fact: examplenumberfact
                operator: equal
                value: 0

📃 Provide the context for the Bug.

I'm trying to implement a custom fact retriever so that I can define custom scores on my backstage entities.

👀 Have you spent some time to check if this bug has been raised before?

  • I checked and didn't find similar issue

🏢 Have you read the Code of Conduct?

Are you willing to submit PR?

None

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingworkspace/tech-insightsUsed to tag tech-insights workspace issues and pull requests

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions