Skip to content

Commit

Permalink
[Logs UI] HTTP endpoint for Log Summary (#51903)
Browse files Browse the repository at this point in the history
* Scaffold `/logs/summary` endpoint

* Use HTTP API for the log summary

* Handle queries in log summary

* Simplify `useLogSummary` implementation

* Scaffold `/logs/summary/highlights` API

* Use HTTP endpoint for log summary highlights

* Tweak `highlightTerms`

* Deduplicate ES queries for summary endpoints

* Clean GraphQL implementation

* Make tests pass

* Handle server errors

* Pass source to the API

* Cleanup tests

* Future-proof response types

Wrap the existing response into a `{ data: ... }` object to allow adding
metadata in the future.

* Refactor tests with `@testing-library/react-hooks`

* Adapt endpoint to NP

* Tweak types in the test

* Split API methods into separate files

* Flatten highlights API

* Restructure `common/http_api/logs` folder

We will group relevant codecs and types into `log_entries`, splitting
summary and summary_highlights as two individual concepts.

* Reorganize route files

* Resurrect changes in `server/lib/{adapter,domain}`

Replace some of the exported types from GraphQL with io-ts codecs

* Wire the route with the domain library

* Remove dead types

* Clean up test file

* Fix merge mishap


Co-authored-by: Elastic Machine <[email protected]>
  • Loading branch information
Alejandro Fernández and elasticmachine authored Dec 18, 2019
1 parent 254b18c commit 0a1ffd9
Show file tree
Hide file tree
Showing 24 changed files with 517 additions and 1,493 deletions.
163 changes: 0 additions & 163 deletions x-pack/legacy/plugins/infra/common/graphql/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,6 @@ export interface InfraSource {
logEntriesBetween: InfraLogEntryInterval;
/** Sequences of log entries matching sets of highlighting queries within an interval */
logEntryHighlights: InfraLogEntryInterval[];
/** A consecutive span of summary buckets within an interval */
logSummaryBetween: InfraLogSummaryInterval;
/** Spans of summary highlight buckets within an interval */
logSummaryHighlightsBetween: InfraLogSummaryHighlightInterval[];

logItem: InfraLogItem;
/** A snapshot of nodes */
Expand Down Expand Up @@ -208,50 +204,6 @@ export interface InfraLogEntryFieldColumn {
/** A list of highlighted substrings of the value */
highlights: string[];
}
/** A consecutive sequence of log summary buckets */
export interface InfraLogSummaryInterval {
/** The millisecond timestamp corresponding to the start of the interval covered by the summary */
start?: number | null;
/** The millisecond timestamp corresponding to the end of the interval covered by the summary */
end?: number | null;
/** The query the log entries were filtered by */
filterQuery?: string | null;
/** A list of the log entries */
buckets: InfraLogSummaryBucket[];
}
/** A log summary bucket */
export interface InfraLogSummaryBucket {
/** The start timestamp of the bucket */
start: number;
/** The end timestamp of the bucket */
end: number;
/** The number of entries inside the bucket */
entriesCount: number;
}
/** A consecutive sequence of log summary highlight buckets */
export interface InfraLogSummaryHighlightInterval {
/** The millisecond timestamp corresponding to the start of the interval covered by the summary */
start?: number | null;
/** The millisecond timestamp corresponding to the end of the interval covered by the summary */
end?: number | null;
/** The query the log entries were filtered by */
filterQuery?: string | null;
/** The query the log entries were highlighted with */
highlightQuery?: string | null;
/** A list of the log entries */
buckets: InfraLogSummaryHighlightBucket[];
}
/** A log summary highlight bucket */
export interface InfraLogSummaryHighlightBucket {
/** The start timestamp of the bucket */
start: number;
/** The end timestamp of the bucket */
end: number;
/** The number of highlighted entries inside the bucket */
entriesCount: number;
/** The time key of a representative of the highlighted log entries in this bucket */
representativeKey: InfraTimeKey;
}

export interface InfraLogItem {
/** The ID of the document */
Expand Down Expand Up @@ -472,28 +424,6 @@ export interface LogEntryHighlightsInfraSourceArgs {
/** The highlighting to apply to the log entries */
highlights: InfraLogEntryHighlightInput[];
}
export interface LogSummaryBetweenInfraSourceArgs {
/** The millisecond timestamp that corresponds to the start of the interval */
start: number;
/** The millisecond timestamp that corresponds to the end of the interval */
end: number;
/** The size of each bucket in milliseconds */
bucketSize: number;
/** The query to filter the log entries by */
filterQuery?: string | null;
}
export interface LogSummaryHighlightsBetweenInfraSourceArgs {
/** The millisecond timestamp that corresponds to the start of the interval */
start: number;
/** The millisecond timestamp that corresponds to the end of the interval */
end: number;
/** The size of each bucket in milliseconds */
bucketSize: number;
/** The query to filter the log entries by */
filterQuery?: string | null;
/** The highlighting to apply to the log entries */
highlightQueries: string[];
}
export interface LogItemInfraSourceArgs {
id: string;
}
Expand Down Expand Up @@ -753,99 +683,6 @@ export namespace LogEntryHighlightsQuery {
export type Entries = InfraLogEntryHighlightFields.Fragment;
}

export namespace LogSummaryHighlightsQuery {
export type Variables = {
sourceId?: string | null;
start: number;
end: number;
bucketSize: number;
highlightQueries: string[];
filterQuery?: string | null;
};

export type Query = {
__typename?: 'Query';

source: Source;
};

export type Source = {
__typename?: 'InfraSource';

id: string;

logSummaryHighlightsBetween: LogSummaryHighlightsBetween[];
};

export type LogSummaryHighlightsBetween = {
__typename?: 'InfraLogSummaryHighlightInterval';

start?: number | null;

end?: number | null;

buckets: Buckets[];
};

export type Buckets = {
__typename?: 'InfraLogSummaryHighlightBucket';

start: number;

end: number;

entriesCount: number;

representativeKey: RepresentativeKey;
};

export type RepresentativeKey = InfraTimeKeyFields.Fragment;
}

export namespace LogSummary {
export type Variables = {
sourceId?: string | null;
start: number;
end: number;
bucketSize: number;
filterQuery?: string | null;
};

export type Query = {
__typename?: 'Query';

source: Source;
};

export type Source = {
__typename?: 'InfraSource';

id: string;

logSummaryBetween: LogSummaryBetween;
};

export type LogSummaryBetween = {
__typename?: 'InfraLogSummaryInterval';

start?: number | null;

end?: number | null;

buckets: Buckets[];
};

export type Buckets = {
__typename?: 'InfraLogSummaryBucket';

start: number;

end: number;

entriesCount: number;
};
}

export namespace MetricsQuery {
export type Variables = {
sourceId: string;
Expand Down
1 change: 1 addition & 0 deletions x-pack/legacy/plugins/infra/common/http_api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@

export * from './log_analysis';
export * from './metadata_api';
export * from './log_entries';
export * from './metrics_explorer';
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
* you may not use this file except in compliance with the Elastic License.
*/

export * from './log_summary';
export * from './summary';
export * from './summary_highlights';
37 changes: 37 additions & 0 deletions x-pack/legacy/plugins/infra/common/http_api/log_entries/summary.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import * as rt from 'io-ts';

export const LOG_ENTRIES_SUMMARY_PATH = '/api/log_entries/summary';

export const logEntriesSummaryRequestRT = rt.type({
sourceId: rt.string,
startDate: rt.number,
endDate: rt.number,
bucketSize: rt.number,
query: rt.union([rt.string, rt.undefined, rt.null]),
});

export type LogEntriesSummaryRequest = rt.TypeOf<typeof logEntriesSummaryRequestRT>;

export const logEntriesSummaryBucketRT = rt.type({
start: rt.number,
end: rt.number,
entriesCount: rt.number,
});

export type LogEntriesSummaryBucket = rt.TypeOf<typeof logEntriesSummaryBucketRT>;

export const logEntriesSummaryResponseRT = rt.type({
data: rt.type({
start: rt.number,
end: rt.number,
buckets: rt.array(logEntriesSummaryBucketRT),
}),
});

export type LogEntriesSummaryResponse = rt.TypeOf<typeof logEntriesSummaryResponseRT>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import * as rt from 'io-ts';
import { logEntriesSummaryRequestRT, logEntriesSummaryBucketRT } from './summary';

export const LOG_ENTRIES_SUMMARY_HIGHLIGHTS_PATH = '/api/log_entries/summary_highlights';

export const logEntriesSummaryHighlightsRequestRT = rt.intersection([
logEntriesSummaryRequestRT,
rt.type({
highlightTerms: rt.array(rt.string),
}),
]);

export type LogEntriesSummaryHighlightsRequest = rt.TypeOf<
typeof logEntriesSummaryHighlightsRequestRT
>;

export const logEntriesSummaryHighlightsBucketRT = rt.intersection([
logEntriesSummaryBucketRT,
rt.type({
representativeKey: rt.type({
time: rt.number,
tiebreaker: rt.number,
}),
}),
]);

export type LogEntriesSummaryHighlightsBucket = rt.TypeOf<
typeof logEntriesSummaryHighlightsBucketRT
>;

export const logEntriesSummaryHighlightsResponseRT = rt.type({
data: rt.array(
rt.type({
start: rt.number,
end: rt.number,
buckets: rt.array(logEntriesSummaryHighlightsBucketRT),
})
),
});
export type LogEntriesSummaryHighlightsResponse = rt.TypeOf<
typeof logEntriesSummaryHighlightsResponseRT
>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { fold } from 'fp-ts/lib/Either';
import { pipe } from 'fp-ts/lib/pipeable';
import { identity } from 'fp-ts/lib/function';
import { kfetch } from 'ui/kfetch';

import { throwErrors, createPlainError } from '../../../../../common/runtime_types';

import {
LOG_ENTRIES_SUMMARY_HIGHLIGHTS_PATH,
LogEntriesSummaryHighlightsRequest,
logEntriesSummaryHighlightsRequestRT,
logEntriesSummaryHighlightsResponseRT,
} from '../../../../../common/http_api';

export const fetchLogSummaryHighlights = async (
requestArgs: LogEntriesSummaryHighlightsRequest
) => {
const response = await kfetch({
method: 'POST',
pathname: LOG_ENTRIES_SUMMARY_HIGHLIGHTS_PATH,
body: JSON.stringify(logEntriesSummaryHighlightsRequestRT.encode(requestArgs)),
});

return pipe(
logEntriesSummaryHighlightsResponseRT.decode(response),
fold(throwErrors(createPlainError), identity)
);
};

This file was deleted.

Loading

0 comments on commit 0a1ffd9

Please sign in to comment.