Trouble with migrating legacy plugin

We are really facing problems in implementing elasticsearch requests from Kibana Plugin using the core kibana API for elasticsearch? Also referred migration examples and the legacy to new platform migration document. Could you please provide sample search query implementation for http routes for third party kibana plugin?

Hey @kibanaPluginDev ,

It'd help if you could be more specific explaining what exactly you'd like to do and what version of Kibana you're using. Anyway here is the example of ES API call made from the route handler that may help.

Best,
Oleg

Hello @azasypkin ,
We are using Kiabana 7.11.0. I have a few logs in our elasticsearch so I was trying to implement a basic search query using Kibana Core API. I had generated a new plugin template using kibana plugin generator.
Our legacy plugin which we are trying to migrate is -

// server/plugin.ts
import {
  PluginInitializerContext,
  CoreSetup,
  CoreStart,
  Plugin,
  Logger,
} from '../../../src/core/server';

import { NewPluginPluginSetup, NewPluginPluginStart } from './types';
import { defineRoutes } from './routes';

export class NewPluginPlugin implements Plugin<NewPluginPluginSetup, NewPluginPluginStart> {
  private readonly logger: Logger;

  constructor(initializerContext: PluginInitializerContext) {
    this.logger = initializerContext.logger.get();
  }

  public setup(core: CoreSetup) {
    this.logger.debug('newPlugin: Setup');
    const router = core.http.createRouter();
    router.get(
      {
        path: '/api/new_plugin/example',
        validate: false,
      },
      async (context, request, response) => {
        const query = {
          query: {
            match_all: {},
          }}
        const results = await context.core.elasticsearch.client.asCurrentUser.search(query);
        return response.ok({
          body: { results },
        });
      }
    );

    return {};
  }

  public start(core: CoreStart) {
    this.logger.debug('newPlugin: Started');
    return {};
  }

  public stop() {}
}
// public/components/app.tsx
import React, { useState } from 'react';
import { i18n } from '@kbn/i18n';
import { FormattedMessage, I18nProvider } from '@kbn/i18n/react';
import { BrowserRouter as Router } from 'react-router-dom';

import {
  EuiButton,
  EuiHorizontalRule,
  EuiPage,
  EuiPageBody,
  EuiPageContent,
  EuiPageContentBody,
  EuiPageContentHeader,
  EuiPageHeader,
  EuiTitle,
  EuiText,
} from '@elastic/eui';

import { CoreStart } from '../../../../src/core/public';
import { NavigationPublicPluginStart } from '../../../../src/plugins/navigation/public';

import { PLUGIN_ID, PLUGIN_NAME } from '../../common';

interface NewPluginAppDeps {
  basename: string;
  notifications: CoreStart['notifications'];
  http: CoreStart['http'];
  navigation: NavigationPublicPluginStart;
}


export const NewPluginApp = ({ basename, notifications, http, navigation }: NewPluginAppDeps) => {
  // Use React hooks to manage state.
  const [timestamp, setTimestamp] = useState<string | undefined>();

  const onClickHandler = () => {
    // Use the core http service to make a response to the server API.
    http.get('/api/new_plugin/example').then((res) => {
      // eslint-disable-next-line no-console
      console.log(res.data);
    });
  };

  // Render the application DOM.
  // Note that `navigation.ui.TopNavMenu` is a stateful component exported on the `navigation` plugin's start contract.
  return (
    <Router basename={basename}>
      <I18nProvider>
        <>
          <navigation.ui.TopNavMenu
            appName={PLUGIN_ID}
            showSearchBar={true}
            useDefaultBehaviors={true}
          />
          <EuiPage restrictWidth="1000px">
            <EuiPageBody>
              <EuiPageHeader>
                <EuiTitle size="l">
                  <h1>
                    <FormattedMessage
                      id="newPlugin.helloWorldText"
                      defaultMessage="{name}"
                      values={{ name: PLUGIN_NAME }}
                    />
                  </h1>
                </EuiTitle>
              </EuiPageHeader>
              <EuiPageContent>
                <EuiPageContentHeader>
                  <EuiTitle>
                    <h2>
                      <FormattedMessage
                        id="newPlugin.congratulationsTitle"
                        defaultMessage="Sip Logs"
                      />
                    </h2>
                  </EuiTitle>
                  <EuiButton type="primary" size="s" onClick={onClickHandler}>
                      <FormattedMessage id="newPlugin.buttonText" defaultMessage="Get Logs" />
                    </EuiButton>
                </EuiPageContentHeader>
                <EuiPageContentBody>
                  <EuiText>
                    <EuiHorizontalRule />
                    <p>
                      <FormattedMessage
                        id="newPlugin.timestampText"
                        defaultMessage="Last timestamp: {time}"
                        values={{ time: timestamp ? timestamp : 'Unknown' }}
                      />
                    </p>
                  </EuiText>
                </EuiPageContentBody>
              </EuiPageContent>
            </EuiPageBody>
          </EuiPage>
        </>
      </I18nProvider>
    </Router>
  );
};

Hi there,

It would be helpful if you could describe exactly what you were having problems with in your implementation. Off hand, I noticed a few things:

I don't believe that your client-side code is accessing the right field of the response. I believe you should be accessing res.response (the same name of the field you return in res.ok({ response }) on the server:

    http.get('/api/new_plugin/example').then((res) => {
      console.log(res.response);
    });

On the server side, your routing and search code looks pretty good, though you're not currently specifying an index to search on in your search request. It's worth noting that the object on context.core.elasticsearch.client.asCurrentUser is an instance of the Client class from the @elastic/elasticsearch package. You can find API examples here: GitHub - elastic/elasticsearch-js: Official Elasticsearch client library for Node.js

I believe your query should look something closer to this:

const results = await context.core.elasticsearch.client.asCurrentUser.search({
  index: 'my-index',
  body: {
    query: {
      match_all: {}
    }
  }
});

If you have any more specific questions, let us know!

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.