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/api
Ryan McKinley 1824694c72
Provisioning: Show branch in save form (#103513)
1 month ago
..
clients Provisioning: Show branch in save form (#103513) 1 month ago
README.md Chore: Fix some links in our api generation docs (#102907) 2 months ago
createBaseQuery.ts API Client: Add client-level error handler (#102091) 2 months ago
utils.ts API client generation: create a central `getAPIBaseURL` function (#99961) 4 months ago

README.md

Generating RTK Query API Clients

To show the steps to follow, we are going to work on adding an API client to create a new dashboard. Just adapt the following guide to your use case.

1. Generate an OpenAPI snapshot

First, check if the group and the version are already present in openapi_test.go. If so, move on to the next step.
If you need to add a new block, you can check for the right group and version in the backend API call that you want to replicate in the frontend.

{
  Group:   "dashboard.grafana.app",
  Version: "v0alpha1",
}

Afterwards, you need to run the TestIntegrationOpenAPIs test. Note that it will fail the first time you run it. On the second run, it will generate the corresponding OpenAPI spec, which you can find in openapi_snapshots.

Note: You don’t need to follow these two steps if the group you’re working with is already in the openapi_test.go file.


2. Create the API definition

In the /public/app/api/clients folder, create a new folder and baseAPI.ts file for your group. This file should have the following content:

import { createApi } from '@reduxjs/toolkit/query/react';

import { createBaseQuery } from 'app/api/createBaseQuery';
import { getAPIBaseURL } from 'app/api/utils';

export const BASE_URL = getAPIBaseURL('dashboard.grafana.app', 'v0alpha1');

export const api = createApi({
  reducerPath: 'dashboardAPI',
  baseQuery: createBaseQuery({
    baseURL: BASE_URL,
  }),
  endpoints: () => ({}),
});

This is the API definition for the specific group you're working with, where getAPIBaseURL should have the proper group and version as parameters. The reducerPath needs to be unique. The convention is to use <group>API: dashboard will be dashboardAPI, iam will be iamAPI and so on.

3. Add your new client to the generation script

Open generate-rtk-apis.ts and add the following information:

Data Descritpion
outputFile name File that will be created after running the API Client Generation script. It is the key of the object.
apiFile File with the group's API definition.
schemaFile File with the schema that was automatically created in the second step. Although it is in openapi_snapshots, you should link the one saved in data/openapi.
filterEndpoints The operationId of the particular route you want to work with. You can check the available operationIds in the specific group's spec file. As seen in the migrate-to-cloud one, it is an array
 tag Must be set to true, to automatically attach tags to endpoints. This is needed for proper cache invalidation. See more info in the official documentation. 

More info in Redux Toolkit

In our example, the information added will be:

'../public/app/api/clients/dashboard/endpoints.gen.ts': {
    apiFile: '../public/app/api/clients/dashboard/baseAPI.ts',
    schemaFile: '../data/openapi/dashboard.grafana.app-v0alpha1.json',
    filterEndpoints: ['createDashboard', 'updateDashboard'],
    tag: true,
},

4. Run the API client generation script

Then, we are ready to run the script to create the API client:

yarn generate-apis

This will create an endpoints.gen.ts file in the path specified in the previous step.

5. Create the index file for your hooks

In the same api folder where the endpoints.gen.ts file has been saved, you have to create an index file from which you can import the types and hooks needed. By doing this, we selectively export hooks/types from endpoints.gen.ts.

In our case, the dashboard index will be like:

import { generatedAPI } from './endpoints.gen';

export const dashboardAPI = generatedAPI;
export const { useCreateDashboardMutation, useUpdateDashboardMutation} = dashboardAPI;
// eslint-disable-next-line no-barrel-files/no-barrel-files
export { type Dashboard } from './endpoints.gen';

There are some use cases where the hook will not work out of the box, and that is a clue to see if it needs to be modified. The hooks can be tweaked by using enhanceEndpoints.

export const dashboardsAPI = generatedApi.enhanceEndpoints({
  endpoints: {
    // Need to mutate the generated query to set the Content-Type header correctly
    updateDashboard: (endpointDefinition) => {
      const originalQuery = endpointDefinition.query;
      if (originalQuery) {
        endpointDefinition.query = (requestOptions) => ({
          ...originalQuery(requestOptions),
          headers: {
            'Content-Type': 'application/merge-patch+json',
          },
        });
      }
    },
  },
});

6. Add reducers and middleware to the Redux store

Last but not least, you need to add the middleware and reducers to the store.

In Grafana, the reducers are added to root.ts:

  import { dashboardAPI } from '<pathToYourAPI>';
  const rootReducers = {
    ...,
    [dashboardAPI.reducerPath]: dashboardAPI.reducer,
  };

And the middleware is added to configureStore.ts:

import { dashboardAPI } from '<pathToYourAPI>';
export function configureStore(initialState?: Partial<StoreState>) {
  const store = reduxConfigureStore({
    reducer: createRootReducer(),
    middleware: (getDefaultMiddleware) =>
      getDefaultMiddleware({ thunk: true, serializableCheck: false, immutableCheck: false }).concat(
        ...,
        dashboardAPI.middleware
      ),
    ...,
  });

You have available the official documentation in RTK Query

After this step is done, it is time to use your hooks across Grafana. Enjoy coding!