kibana/x-pack/plugins/event_log
Tomas Della Vedova 238791b942
ES client : use the new type definitions (#83808)
* Use client from branch

* Get type checking working in core

* Fix types in other plugins

* Update client types + remove type errors from core

* migrate Task Manager Elasticsearch typing from legacy library to client library

* use SortOrder instead o string in alerts

* Update client types + fix core type issues

* fix maps ts errors

* Update Lens types

* Convert Search Profiler body from a string to an object to conform to SearchRequest type.

* Fix SOT types

* Fix/mute Security/Spaces plugins type errors.

* Fix bootstrap types

* Fix painless_lab

* corrected es typing in Event Log

* Use new types from client for inferred search responses

* Latest type defs

* Integrate latest type defs for APM/UX

* fix core errors

* fix telemetry errors

* fix canvas errors

* fix data_enhanced errors

* fix event_log errors

* mute lens errors

* fix or mute maps errors

* fix reporting errors

* fix security errors

* mute errors in task_manager

* fix errors in telemetry_collection_xpack

* fix errors in data plugins

* fix errors in alerts

* mute errors in index_management

* fix task_manager errors

* mute or fix lens errors

* fix upgrade_assistant errors

* fix or mute errors in index_lifecycle_management

* fix discover errors

* fix core tests

* ML changes

* fix core type errors

* mute error in kbn-es-archiver

* fix error in data plugin

* fix error in telemetry plugin

* fix error in discover

* fix discover errors

* fix errors in task_manager

* fix security errors

* fix wrong conflict resolution

* address errors with upstream code

* update deps to the last commit

* remove outdated comments

* fix core errors

* fix errors after update

* adding more expect errors to ML

* pull the lastest changes

* fix core errors

* fix errors in infra plugin

* fix errors in uptime plugin

* fix errors in ml

* fix errors in xpack telemetry

* fix or mute errors in transform

* fix errors in upgrade assistant

* fix or mute fleet errors

* start fixing apm errors

* fix errors in osquery

* fix telemetry tests

* core cleanup

* fix asMutableArray imports

* cleanup

* data_enhanced cleanup

* cleanup events_log

* cleaup

* fix error in kbn-es-archiver

* fix errors in kbn-es-archiver

* fix errors in kbn-es-archiver

* fix ES typings for Hit

* fix SO

* fix actions plugin

* fix fleet

* fix maps

* fix stack_alerts

* fix eslint problems

* fix event_log unit tests

* fix failures in data_enhanced tests

* fix test failure in kbn-es-archiver

* fix test failures in index_pattern_management

* fixing ML test

* remove outdated comment in kbn-es-archiver

* fix error type in ml

* fix eslint errors in osquery plugin

* fix runtime error in infra plugin

* revert changes to event_log cluser exist check

* fix eslint error in osquery

* fixing ML endpoint argument types

* fx types

* Update api-extractor docs

* attempt fix for ese test

* Fix lint error

* Fix types for ts refs

* Fix data_enhanced unit test

* fix lens types

* generate docs

* Fix a number of type issues in monitoring and ml

* fix triggers_actions_ui

* Fix ILM functional test

* Put search.d.ts typings back

* fix data plugin

* Update typings in typings/elasticsearch

* Update snapshots

* mute errors in task_manager

* mute fleet errors

* lens. remove unnecessary ts-expect-errors

* fix errors in stack_alerts

* mute errors in osquery

* fix errors in security_solution

* fix errors in lists

* fix errors in cases

* mute errors in search_examples

* use KibanaClient to enforce promise-based API

* fix errors in test/ folder

* update comment

* fix errors in x-pack/test folder

* fix errors in ml plugin

* fix optional fields in ml api_integartoon tests

* fix another casting problem in ml tests

* fix another ml test failure

* fix fleet problem after conflict resolution

* rollback changes in security_solution. trying to fix test

* Update type for discover rows

* uncomment runtime_mappings as its outdated

* address comments from Wylie

* remove eslint error due to any

* mute error due to incompatibility

* Apply suggestions from code review

Co-authored-by: John Schulz <github.com@jfsiii.org>

* fix type error in lens tests

* Update x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.ts

Co-authored-by: Alison Goryachev <alisonmllr20@gmail.com>

* Update x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts

Co-authored-by: Alison Goryachev <alisonmllr20@gmail.com>

* update deps

* fix errors in core types

* fix errors for the new elastic/elasticsearch version

* remove unused type

* remove unnecessary manual type cast and put optional chaining back

* ML: mute Datafeed is missing indices_options

* Apply suggestions from code review

Co-authored-by: Josh Dover <1813008+joshdover@users.noreply.github.com>

* use canary pacakge instead of git commit

Co-authored-by: Josh Dover <me@joshdover.com>
Co-authored-by: Josh Dover <1813008+joshdover@users.noreply.github.com>
Co-authored-by: Gidi Meir Morris <github@gidi.io>
Co-authored-by: Nathan Reese <reese.nathan@gmail.com>
Co-authored-by: Wylie Conlon <wylieconlon@gmail.com>
Co-authored-by: CJ Cenizal <cj@cenizal.com>
Co-authored-by: Aleh Zasypkin <aleh.zasypkin@gmail.com>
Co-authored-by: Dario Gieselaar <dario.gieselaar@elastic.co>
Co-authored-by: restrry <restrry@gmail.com>
Co-authored-by: James Gowdy <jgowdy@elastic.co>
Co-authored-by: John Schulz <github.com@jfsiii.org>
Co-authored-by: Alison Goryachev <alisonmllr20@gmail.com>
2021-03-25 04:47:16 -04:00
..
common Elastic License 2.0 (#90099) 2021-02-03 18:12:39 -08:00
generated Elastic License 2.0 (#90099) 2021-02-03 18:12:39 -08:00
scripts Elastic License 2.0 (#90099) 2021-02-03 18:12:39 -08:00
server ES client : use the new type definitions (#83808) 2021-03-25 04:47:16 -04:00
jest.config.js Elastic License 2.0 (#90099) 2021-02-03 18:12:39 -08:00
kibana.json [eventLog] search for actions/alerts as hidden saved objects (#70395) 2020-07-16 09:10:51 -04:00
README.md [eventLog][docs] updates README.md (#92563) 2021-03-04 19:23:55 -05:00
tsconfig.json [Alerting] Migrate Event Log plugin to TS project references (#81557) 2021-01-15 19:07:45 -08:00

Event Log

The event log plugin provides a persistent history of alerting and action actitivies.

Overview

This plugin provides a persistent log of "events" that can be used by other plugins to record their processing, for later acccess. Currently it's only used by the alerts and actions plugins.

The "events" are ECS documents, with some custom properties for Kibana, and alerting-specific properties within those Kibana properties. The number of ECS fields is limited today, but can be extended fairly easily. We are being conservative in adding new fields though, to help prevent indexing explosions.

A client API is available for other plugins to:

  • register the events they want to write
  • write the events, with helpers for duration calculation, etc
  • query the events

HTTP APIs are also available to query the events.

Currently, events are written with references to Saved Objects, and queries against the event log must include the Saved Object references that the query should return events for. This is the basic security mechanism to prevent users from accessing events for Saved Objects that they do not have access to. The queries ensure that the user can read the referenced Saved Objects before returning the events relating to them.

The default index name is .kibana-event-log-${kibanaVersion}-${ILM-sequence}.

The index written to is controlled by ILM. The ILM policy is initially created by the plugin, but is otherwise never updated by the plugin. This allows customers to customize it to their environment, without having to worry about their updates getting overwritten by newer versions of Kibana. The policy provides some default phases to roll over and delete older indices. The name of the policy is kibana-event-log-policy.

Event Documents

The structure of the event documents can be seen in the mappings and config-schema definitions. Note these files are generated via a script when the structure changes. See the README.md for how to change the document structure.

Below is an document in the expected structure, with descriptions of the fields:

{
  "@timestamp": "ISO date",
  tags: ["tags", "here"],
  message: "message for humans here",
  ecs: {
    version: "version of ECS used by the event log",
  },
  event: {
    provider: "see below",
    action: "see below",
    start: "ISO date of start time for events that capture a duration",
    duration: "duration in nanoseconds for events that capture a duration",
    end: "ISO date of end time for events that capture a duration",
    outcome: "success | failure, for events that indicate an outcome",
    reason: "additional detail on failure outcome",
  },
  error: {
    message: "an error message, usually associated with outcome: failure",
  },
  user: {
    name: "name of Kibana user",
  }, 
  kibana: { // custom ECS field
    server_uuid: "UUID of kibana server, for diagnosing multi-Kibana scenarios",
    alerting: {
      instance_id: "alert instance id, for relevant documents",
      action_group_id: "alert action group, for relevant documents",
      action_subgroup_id: "alert action subgroup, for relevant documents",
      status: "overall alert status, after alert execution",
    },
    saved_objects: [
      {
        rel: "'primary' | undefined; see below",
        namespace: "${spaceId} | undefined",
        id: "saved object id",
        type: " saved object type",
      },
    ],
  },
}

The event.provider and event.action fields provide a scoped mechanism for describing who is generating the event, and what kind of event it is. Plugins that write events need to register the provider and action values they will be using. Generally, each plugin should provide it's own provider, but a plugin could provide multiple providers, or a single provider might be used by multiple plugins.

The following provider / action pairs are used by the alerting and actions plugins:

  • provider: actions

    • action: execute - generated when an action is executed by the actions client
    • action: execute-via-http - generated when an action is executed via HTTP request
  • provider: alerting

    • action: execute - generated when an alert executor runs
    • action: execute-action - generated when an alert schedules an action to run
    • action: new-instance - generated when an alert has a new instance id that is active
    • action: recovered-instance - generated when an alert has a previously active instance id that is no longer active
    • action: active-instance - generated when an alert determines an instance id is active

For the saved_objects array elements, these are references to saved objects associated with the event. For the alerting provider, those are alert saved ojects and for the actions provider those are action saved objects. The alerts:execute-action event includes both the alert and action saved object references. For that event, only the alert reference has the optional rel property with a primary value. This property is used when searching the event log to indicate which saved objects should be directly searchable via saved object references. For the alerts:execute-action event, searching only via the alert saved object reference will return the event.

Event Log index - associated resources

The index template and ILM policy are defined in the file x-pack/plugins/event_log/server/es/documents.ts.

See ILM rollover action docs for more information on the is_write_index and index.lifecycle.* properties.

Using the Event Log for diagnosing alerting and actions issues

For ad-hoc diagnostic purposes, your go to tools are Discover and Lens. Your user will need to have access to the index, which is considered a Kibana system index due to it's prefix.

Add the event log index as an index pattern. The only customization needed is to set the event.duration field to a duration in nanoseconds. You'll probably want it displayed as milliseconds.

Experimental RESTful API for querying

As this plugin is space-aware, prefix any URL below with the usual /s/{space} to target a space other than the default space.

Usage of the event log allows you to retrieve the events for a given saved object type by the specified set of IDs. The following API is experimental and can change or be removed in a future release.

GET /api/event_log/{type}/{id}/_find: Get events for a given saved object type by the ID

Collects event information from the event log for the selected saved object by type and ID.

Params:

Property Description Type
type The type of the saved object whose events you're trying to get. string
id The id of the saved object. string

Query:

Property Description Type
page The page number. number
per_page The number of events to return per page. number
sort_field Sorts the response. Could be an event fields returned in the response. string
sort_order Sort direction, either asc or desc. string
filter A KQL string that you filter with an attribute from the event. It should look like event.action:(execute). string
start The date to start looking for saved object events in the event log. Either an ISO date string, or a duration string that indicates the time since now. string
end The date to stop looking for saved object events in the event log. Either an ISO date string, or a duration string that indicates the time since now. string

Response body:

See QueryEventsBySavedObjectResult in the Plugin Client APIs below.

POST /api/event_log/{type}/_find: Retrive events for a given saved object type by the IDs

Collects event information from the event log for the selected saved object by type and by IDs.

Params:

Property Description Type
type The type of the saved object whose events you're trying to get. string

Query:

Property Description Type
page The page number. number
per_page The number of events to return per page. number
sort_field Sorts the response. Could be an event field returned in the response. string
sort_order Sort direction, either asc or desc. string
filter A KQL string that you filter with an attribute from the event. It should look like event.action:(execute). string
start The date to start looking for saved object events in the event log. Either an ISO date string, or a duration string that indicates the time since now. string
end The date to stop looking for saved object events in the event log. Either an ISO date string, or a duration string that indicates the time since now. string

Request Body:

Property Description Type
ids The array ids of the saved object. string array

Response body:

See QueryEventsBySavedObjectResult in the Plugin Client APIs below.

Plugin Client APIs for querying

interface EventLogClient {
  findEventsBySavedObjectIds(
    type: string,
    ids: string[],
    options?: Partial<FindOptionsType>
  ): Promise<QueryEventsBySavedObjectResult>;
}

interface FindOptionsType { /* typed version of HTTP query parameters ^^^ */ }

interface QueryEventsBySavedObjectResult {
  page: number;
  per_page: number;
  total: number;
  data: Event[];
}

Generating Events

Follow these steps to use eventLog in your plugin:

  1. Declare eventLog as a dependency in kibana.json:
{
  ...
  "requiredPlugins": ["eventLog"],
  ...
}
  1. Register provider / actions, and create your plugin's logger, using the service API provided in the setup stage:
...
import { IEventLogger, IEventLogService } from '../../event_log/server';
interface PluginSetupDependencies {
  eventLog: IEventLogService;
}
...
public setup(core: CoreSetup, { eventLog }: PluginSetupDependencies) {
  ...
  eventLog.registerProviderActions('my-plugin', ['action-1, action-2']);
  const eventLogger: IEventLogger = eventLog.getLogger({ event: { provider: 'my-plugin' } });
  ...
}
...
  1. To log an event, call logEvent() on the eventLogger object you created:
...
  eventLogger.logEvent({ event: { action: 'action-1' }, tags: ['fe', 'fi', 'fo'] });
...

The plugin exposes an IEventLogService object to plugins that pre-req it. Those plugins need to call registerProviderActions() to indicate the values of the event.provider and event.action values they will be using when logging events.

The pre-registration helps in two ways:

  • dealing with misspelled values
  • preventing index explosion on those fields

Once the values are registered, the plugin will get an IEventLogger instance by passing in a set of default properties to be used for all it's logging, to the getLogger() method. For instance, the actions plugin creates a logger with event.provider set to actions, and provides event.action values when writing actual entries.

The IEventLogger object can be cached at the plugin level and accessed by any code in the plugin. It has a single method to write an event log entry, logEvent(), which is passed specific properties for the event.

The final data written is a combination of the data passed to getLogger() when creating the logger, and the data passed on the logEvent() call, and then that result is validated to ensure it's complete and valid. Errors will be logged to the server log.

The logEvent() method returns no values, and is itself not asynchronous. The messages are queued written asynchonously in bulk. It's designed this way because it's not clear what a client would do with a result from this method, nor what it would do if the method threw an error. All the error processing involved with getting the data into the index is handled internally, and logged to the server log as appropriate.

There are additional utility methods startTiming() and stopTiming() which can be used to set the timing properties start, end, and duration in the event. For example:

    const loggedEvent: IEvent = { event: { action: 'foo' } };

    // sets event.start
    eventLogger.startTiming(loggedEvent);

    longRunningFunction();
    
    // sets event.end and event.duration
    eventLogger.stopTiming(loggedEvent);

    eventLogger.logEvent(loggedEvent);

It's anticipated that more "helper" methods like this will be provided in the future.

Start


export interface IEventLogClientService {
  getClient(request: KibanaRequest): IEventLogClient;
}

export interface IEventLogClient {
  findEventsBySavedObjectIds(
    type: string,
    ids: string[],
    options?: Partial<FindOptionsType>
  ): Promise<QueryEventsBySavedObjectResult>;
}

The plugin exposes an IEventLogClientService object to plugins that request it. These plugins must call getClient(request) to get the event log client.

Testing

Unit tests

Documentation: https://www.elastic.co/guide/en/kibana/current/development-tests.html#_unit_testing

yarn test:jest x-pack/plugins/event_log --watch

API Integration tests

See: x-pack/test/plugin_api_integration/test_suites/event_log.