[ML] AIOps Log Rate Analysis: Rename SignificantTerm to SignificantItem. (#169756)

Log rate analysis now supports both keywords and log patterns derived
from text fields. The type `SignificantTerm` originally was used for the
results of the `significant_terms` agg to get the p-values for keyword
fields. Since it's now used for both cases (keyword fields and log
patterns) this PR renames the type and related variables etc. to
`SignificantItem` (we used the wording `item` already in some cases in
the context of groups).
This commit is contained in:
Walter Rafelsberger 2023-11-10 18:57:04 +01:00 committed by GitHub
parent 33757f64ca
commit 9b29b1898e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
66 changed files with 512 additions and 506 deletions

View file

@ -18,17 +18,17 @@ export type {
NumericHistogramField,
} from './src/fetch_histograms_for_fields';
export { isMultiBucketAggregate } from './src/is_multi_bucket_aggregate';
export { isSignificantTerm } from './src/type_guards';
export { SIGNIFICANT_TERM_TYPE } from './src/types';
export { isSignificantItem } from './src/type_guards';
export { SIGNIFICANT_ITEM_TYPE } from './src/types';
export type {
AggCardinality,
SignificantTerm,
SignificantTermGroup,
SignificantTermGroupItem,
SignificantTermGroupHistogram,
SignificantTermHistogram,
SignificantTermHistogramItem,
SignificantTermType,
SignificantItem,
SignificantItemGroup,
SignificantItemGroupItem,
SignificantItemGroupHistogram,
SignificantItemHistogram,
SignificantItemHistogramItem,
SignificantItemType,
HistogramField,
NumericColumnStats,
NumericColumnStatsMap,

View file

@ -5,15 +5,15 @@
* 2.0.
*/
import { isSignificantTerm } from './type_guards';
import { isSignificantItem } from './type_guards';
describe('isSignificantTerm', () => {
it('identifies significant terms', () => {
expect(isSignificantTerm({})).toBeFalsy();
expect(isSignificantTerm({ fieldName: 'response_code' })).toBeFalsy();
expect(isSignificantTerm({ fieldValue: '500' })).toBeFalsy();
describe('isSignificantItem', () => {
it('identifies significant items', () => {
expect(isSignificantItem({})).toBeFalsy();
expect(isSignificantItem({ fieldName: 'response_code' })).toBeFalsy();
expect(isSignificantItem({ fieldValue: '500' })).toBeFalsy();
expect(
isSignificantTerm({
isSignificantItem({
key: 'response_code:500',
type: 'keyword',
fieldName: 'response_code',

View file

@ -7,17 +7,17 @@
import { isPopulatedObject } from '@kbn/ml-is-populated-object';
import type { SignificantTerm } from './types';
import type { SignificantItem } from './types';
/**
* Type guard for a significant term.
* Type guard for a significant item.
* Note this is used as a custom type within Log Rate Analysis
* for a p-value based variant, not a generic significant terms
* aggregation type.
* @param arg The unknown type to be evaluated
* @returns whether arg is of type SignificantTerm
* @returns whether arg is of type SignificantItem
*/
export function isSignificantTerm(arg: unknown): arg is SignificantTerm {
export function isSignificantItem(arg: unknown): arg is SignificantItem {
return isPopulatedObject(arg, [
'key',
'type',

View file

@ -88,25 +88,25 @@ export interface HistogramField {
}
/**
* Enumeration of significant term types.
* Enumeration of significant item types.
*/
export const SIGNIFICANT_TERM_TYPE = {
export const SIGNIFICANT_ITEM_TYPE = {
KEYWORD: 'keyword',
LOG_PATTERN: 'log_pattern',
} as const;
/**
* Type for significant term type keys.
* Type for significant item type keys.
*/
type SignificantTermTypeKeys = keyof typeof SIGNIFICANT_TERM_TYPE;
type SignificantItemTypeKeys = keyof typeof SIGNIFICANT_ITEM_TYPE;
/**
* Represents the type of significant term as determined by the SIGNIFICANT_TERM_TYPE enumeration.
* Represents the type of significant item as determined by the SIGNIFICANT_ITEM_TYPE enumeration.
*/
export type SignificantTermType = typeof SIGNIFICANT_TERM_TYPE[SignificantTermTypeKeys];
export type SignificantItemType = typeof SIGNIFICANT_ITEM_TYPE[SignificantItemTypeKeys];
/**
* Represents significant term metadata for a field/value pair.
* Represents significant item metadata for a field/value pair.
* This interface is used as a custom type within Log Rate Analysis
* for a p-value based variant, not related to the generic
* significant terms aggregation type.
@ -114,42 +114,42 @@ export type SignificantTermType = typeof SIGNIFICANT_TERM_TYPE[SignificantTermTy
* @interface
* @extends FieldValuePair
*/
export interface SignificantTerm extends FieldValuePair {
/** The key associated with the significant term. */
export interface SignificantItem extends FieldValuePair {
/** The key associated with the significant item. */
key: string;
/** The type of the significant term. */
type: SignificantTermType;
/** The type of the significant item. */
type: SignificantItemType;
/** The document count for the significant term. */
/** The document count for the significant item. */
doc_count: number;
/** The background count for the significant term. */
/** The background count for the significant item. */
bg_count: number;
/** The total document count for all terms. */
/** The total document count for all items. */
total_doc_count: number;
/** The total background count for all terms. */
/** The total background count for all items. */
total_bg_count: number;
/** The score associated with the significant term. */
/** The score associated with the significant item. */
score: number;
/** The p-value for the significant term, or null if not available. */
/** The p-value for the significant item, or null if not available. */
pValue: number | null;
/** The normalized score for the significant term. */
/** The normalized score for the significant item. */
normalizedScore: number;
/** An optional histogram of significant term items. */
histogram?: SignificantTermHistogramItem[];
/** An optional histogram for the significant item. */
histogram?: SignificantItemHistogramItem[];
/** Indicates if the significant term is unique within a group. */
/** Indicates if the significant item is unique within a group. */
unique?: boolean;
}
interface SignificantTermHistogramItemBase {
interface SignificantItemHistogramItemBase {
/** The document count for this item in the overall context. */
doc_count_overall: number;
@ -163,12 +163,12 @@ interface SignificantTermHistogramItemBase {
/**
* @deprecated since version 2 of internal log rate analysis REST API endpoint
*/
interface SignificantTermHistogramItemV1 extends SignificantTermHistogramItemBase {
interface SignificantItemHistogramItemV1 extends SignificantItemHistogramItemBase {
/** The document count for this item in the significant term context. */
doc_count_significant_term: number;
}
interface SignificantTermHistogramItemV2 extends SignificantTermHistogramItemBase {
interface SignificantItemHistogramItemV2 extends SignificantItemHistogramItemBase {
/** The document count for this histogram item in the significant item context. */
doc_count_significant_item: number;
}
@ -176,41 +176,41 @@ interface SignificantTermHistogramItemV2 extends SignificantTermHistogramItemBas
/**
* Represents a data item in a significant term histogram.
*/
export type SignificantTermHistogramItem =
| SignificantTermHistogramItemV1
| SignificantTermHistogramItemV2;
export type SignificantItemHistogramItem =
| SignificantItemHistogramItemV1
| SignificantItemHistogramItemV2;
/**
* Represents histogram data for a field/value pair.
* @interface
*/
export interface SignificantTermHistogram extends FieldValuePair {
/** An array of significant term histogram items. */
histogram: SignificantTermHistogramItem[];
export interface SignificantItemHistogram extends FieldValuePair {
/** An array of significant item histogram items. */
histogram: SignificantItemHistogramItem[];
}
/**
* Represents histogram data for a group of field/value pairs.
* @interface
*/
export interface SignificantTermGroupHistogram {
export interface SignificantItemGroupHistogram {
/** The identifier for the group. */
id: string;
/** An array of significant term histogram items. */
histogram: SignificantTermHistogramItem[];
/** An array of significant item histogram items. */
histogram: SignificantItemHistogramItem[];
}
/**
* Represents an item in a significant term group.
* Represents an item in a significant item group.
* @interface
*/
export interface SignificantTermGroupItem extends FieldValuePair {
/** The key associated with the significant term. */
export interface SignificantItemGroupItem extends FieldValuePair {
/** The key associated with the significant item. */
key: string;
/** The type of the significant term. */
type: SignificantTermType;
/** The type of the significant item. */
type: SignificantItemType;
/** The document count associated with this item. */
docCount: number;
@ -223,15 +223,15 @@ export interface SignificantTermGroupItem extends FieldValuePair {
}
/**
* Represents a significant term group.
* Represents a significant item group.
* @interface
*/
export interface SignificantTermGroup {
export interface SignificantItemGroup {
/** The identifier for the item. */
id: string;
/** An array of significant term group items. */
group: SignificantTermGroupItem[];
/** An array of significant item group items. */
group: SignificantItemGroupItem[];
/** The document count associated with this item. */
docCount: number;
@ -239,6 +239,6 @@ export interface SignificantTermGroup {
/** The p-value for this item, or null if not available. */
pValue: number | null;
/** An optional array of significant term histogram items. */
histogram?: SignificantTermHistogramItem[];
/** An optional array of significant item histogram items. */
histogram?: SignificantItemHistogramItem[];
}

View file

@ -5,9 +5,9 @@
* 2.0.
*/
import type { SignificantTermGroup } from '@kbn/ml-agg-utils';
import type { SignificantItemGroup } from '@kbn/ml-agg-utils';
export const finalSignificantTermGroups: SignificantTermGroup[] = [
export const finalSignificantItemGroups: SignificantItemGroup[] = [
{
docCount: 632,
group: [

View file

@ -5,9 +5,9 @@
* 2.0.
*/
import type { SignificantTermGroup } from '@kbn/ml-agg-utils';
import type { SignificantItemGroup } from '@kbn/ml-agg-utils';
export const finalSignificantTermGroupsTextfield: SignificantTermGroup[] = [
export const finalSignificantItemGroupsTextfield: SignificantItemGroup[] = [
{
docCount: 636,
group: [

View file

@ -5,9 +5,9 @@
* 2.0.
*/
import type { SignificantTermGroup } from '@kbn/ml-agg-utils';
import type { SignificantItemGroup } from '@kbn/ml-agg-utils';
export const significantTermGroups: SignificantTermGroup[] = [
export const significantItemGroups: SignificantItemGroup[] = [
{
id: '2038579476',
group: [

View file

@ -5,9 +5,10 @@
* 2.0.
*/
import type { SignificantTerm } from '@kbn/ml-agg-utils';
import type { SignificantItem } from '@kbn/ml-agg-utils';
export const significantLogPatterns: SignificantTerm[] = [
// Named significantLogPatterns since all these items are of type `log_pattern`.
export const significantLogPatterns: SignificantItem[] = [
{
bg_count: 0,
doc_count: 1266,

View file

@ -5,9 +5,10 @@
* 2.0.
*/
import type { SignificantTerm } from '@kbn/ml-agg-utils';
import type { SignificantItem } from '@kbn/ml-agg-utils';
export const significantTerms: SignificantTerm[] = [
// Named significantTerms since all these items are of type `keyword`.
export const significantTerms: SignificantItem[] = [
{
key: 'user:Peter',
type: 'keyword',

View file

@ -5,9 +5,9 @@
* 2.0.
*/
import type { SignificantTermGroup } from '@kbn/ml-agg-utils';
import type { SignificantItemGroup } from '@kbn/ml-agg-utils';
export const significantTermGroups: SignificantTermGroup[] = [
export const significantItemGroups: SignificantItemGroup[] = [
{
id: 'group-1',
group: [

View file

@ -6,10 +6,10 @@
*/
import type {
SignificantTerm,
SignificantTermHistogram,
SignificantTermGroup,
SignificantTermGroupHistogram,
SignificantItem,
SignificantItemHistogram,
SignificantItemGroup,
SignificantItemGroupHistogram,
} from '@kbn/ml-agg-utils';
import type { AiopsLogRateAnalysisApiVersion as ApiVersion } from './schema';
@ -40,108 +40,108 @@ export const API_ACTION_NAME = {
} as const;
export type ApiActionName = typeof API_ACTION_NAME[keyof typeof API_ACTION_NAME];
interface ApiActionAddSignificantTerms<T extends ApiVersion> {
interface ApiActionAddSignificantItems<T extends ApiVersion> {
type: T extends '1'
? typeof API_ACTION_NAME.ADD_SIGNIFICANT_TERMS
: T extends '2'
? typeof API_ACTION_NAME.ADD_SIGNIFICANT_ITEMS
: never;
payload: SignificantTerm[];
payload: SignificantItem[];
}
export function addSignificantTermsAction<T extends ApiVersion>(
payload: ApiActionAddSignificantTerms<T>['payload'],
export function addSignificantItemsAction<T extends ApiVersion>(
payload: ApiActionAddSignificantItems<T>['payload'],
version: T
): ApiActionAddSignificantTerms<T> {
): ApiActionAddSignificantItems<T> {
if (version === '1') {
return {
type: API_ACTION_NAME.ADD_SIGNIFICANT_TERMS,
payload,
} as ApiActionAddSignificantTerms<T>;
} as ApiActionAddSignificantItems<T>;
}
return {
type: API_ACTION_NAME.ADD_SIGNIFICANT_ITEMS,
payload,
} as ApiActionAddSignificantTerms<T>;
} as ApiActionAddSignificantItems<T>;
}
interface ApiActionAddSignificantTermsHistogram<T extends ApiVersion> {
interface ApiActionAddSignificantItemsHistogram<T extends ApiVersion> {
type: T extends '1'
? typeof API_ACTION_NAME.ADD_SIGNIFICANT_TERMS_HISTOGRAM
: T extends '2'
? typeof API_ACTION_NAME.ADD_SIGNIFICANT_ITEMS_HISTOGRAM
: never;
payload: SignificantTermHistogram[];
payload: SignificantItemHistogram[];
}
export function addSignificantTermsHistogramAction<T extends ApiVersion>(
payload: ApiActionAddSignificantTermsHistogram<T>['payload'],
export function addSignificantItemsHistogramAction<T extends ApiVersion>(
payload: ApiActionAddSignificantItemsHistogram<T>['payload'],
version: T
): ApiActionAddSignificantTermsHistogram<T> {
): ApiActionAddSignificantItemsHistogram<T> {
if (version === '1') {
return {
type: API_ACTION_NAME.ADD_SIGNIFICANT_TERMS_HISTOGRAM,
payload,
} as ApiActionAddSignificantTermsHistogram<T>;
} as ApiActionAddSignificantItemsHistogram<T>;
}
return {
type: API_ACTION_NAME.ADD_SIGNIFICANT_ITEMS_HISTOGRAM,
payload,
} as ApiActionAddSignificantTermsHistogram<T>;
} as ApiActionAddSignificantItemsHistogram<T>;
}
interface ApiActionAddSignificantTermsGroup<T extends ApiVersion> {
interface ApiActionAddSignificantItemsGroup<T extends ApiVersion> {
type: T extends '1'
? typeof API_ACTION_NAME.ADD_SIGNIFICANT_TERMS_GROUP
: T extends '2'
? typeof API_ACTION_NAME.ADD_SIGNIFICANT_ITEMS_GROUP
: never;
payload: SignificantTermGroup[];
payload: SignificantItemGroup[];
}
export function addSignificantTermsGroupAction<T extends ApiVersion>(
payload: ApiActionAddSignificantTermsGroup<T>['payload'],
export function addSignificantItemsGroupAction<T extends ApiVersion>(
payload: ApiActionAddSignificantItemsGroup<T>['payload'],
version: T
): ApiActionAddSignificantTermsGroup<T> {
): ApiActionAddSignificantItemsGroup<T> {
if (version === '1') {
return {
type: API_ACTION_NAME.ADD_SIGNIFICANT_TERMS_GROUP,
payload,
} as ApiActionAddSignificantTermsGroup<T>;
} as ApiActionAddSignificantItemsGroup<T>;
}
return {
type: API_ACTION_NAME.ADD_SIGNIFICANT_ITEMS_GROUP,
payload,
} as ApiActionAddSignificantTermsGroup<T>;
} as ApiActionAddSignificantItemsGroup<T>;
}
interface ApiActionAddSignificantTermsGroupHistogram<T extends ApiVersion> {
interface ApiActionAddSignificantItemsGroupHistogram<T extends ApiVersion> {
type: T extends '1'
? typeof API_ACTION_NAME.ADD_SIGNIFICANT_TERMS_GROUP_HISTOGRAM
: T extends '2'
? typeof API_ACTION_NAME.ADD_SIGNIFICANT_ITEMS_GROUP_HISTOGRAM
: never;
payload: SignificantTermGroupHistogram[];
payload: SignificantItemGroupHistogram[];
}
export function addSignificantTermsGroupHistogramAction<T extends ApiVersion>(
payload: ApiActionAddSignificantTermsGroupHistogram<T>['payload'],
export function addSignificantItemsGroupHistogramAction<T extends ApiVersion>(
payload: ApiActionAddSignificantItemsGroupHistogram<T>['payload'],
version: T
): ApiActionAddSignificantTermsGroupHistogram<T> {
): ApiActionAddSignificantItemsGroupHistogram<T> {
if (version === '1') {
return {
type: API_ACTION_NAME.ADD_SIGNIFICANT_TERMS_GROUP_HISTOGRAM,
payload,
} as ApiActionAddSignificantTermsGroupHistogram<T>;
} as ApiActionAddSignificantItemsGroupHistogram<T>;
}
return {
type: API_ACTION_NAME.ADD_SIGNIFICANT_ITEMS_GROUP_HISTOGRAM,
payload,
} as ApiActionAddSignificantTermsGroupHistogram<T>;
} as ApiActionAddSignificantItemsGroupHistogram<T>;
}
interface ApiActionAddError {
@ -211,10 +211,10 @@ export function updateLoadingStateAction(
}
export type AiopsLogRateAnalysisApiAction<T extends ApiVersion> =
| ApiActionAddSignificantTerms<T>
| ApiActionAddSignificantTermsGroup<T>
| ApiActionAddSignificantTermsHistogram<T>
| ApiActionAddSignificantTermsGroupHistogram<T>
| ApiActionAddSignificantItems<T>
| ApiActionAddSignificantItemsGroup<T>
| ApiActionAddSignificantItemsHistogram<T>
| ApiActionAddSignificantItemsGroupHistogram<T>
| ApiActionAddError
| ApiActionPing
| ApiActionResetAll

View file

@ -6,11 +6,11 @@
*/
import { significantTerms } from '../__mocks__/artificial_logs/significant_terms';
import { finalSignificantTermGroups } from '../__mocks__/artificial_logs/final_significant_term_groups';
import { finalSignificantItemGroups } from '../__mocks__/artificial_logs/final_significant_item_groups';
import {
addSignificantTermsAction,
addSignificantTermsGroupAction,
addSignificantItemsAction,
addSignificantItemsGroupAction,
resetAllAction,
resetGroupsAction,
updateLoadingStateAction,
@ -37,7 +37,7 @@ describe('streamReducer', () => {
it('adds significant item, then resets all state again', () => {
const state1 = streamReducer(
initialState,
addSignificantTermsAction(
addSignificantItemsAction(
[
{
key: 'the-field-name:the-field-value',
@ -65,14 +65,14 @@ describe('streamReducer', () => {
});
it('adds significant items and groups, then resets groups only', () => {
const state1 = streamReducer(initialState, addSignificantTermsAction(significantTerms, '2'));
const state1 = streamReducer(initialState, addSignificantItemsAction(significantTerms, '2'));
expect(state1.significantItems).toHaveLength(4);
expect(state1.significantItemsGroups).toHaveLength(0);
const state2 = streamReducer(
state1,
addSignificantTermsGroupAction(finalSignificantTermGroups, '2')
addSignificantItemsGroupAction(finalSignificantItemGroups, '2')
);
expect(state2.significantItems).toHaveLength(4);

View file

@ -5,14 +5,14 @@
* 2.0.
*/
import type { SignificantTerm, SignificantTermGroup } from '@kbn/ml-agg-utils';
import type { SignificantItem, SignificantItemGroup } from '@kbn/ml-agg-utils';
import { API_ACTION_NAME, AiopsLogRateAnalysisApiAction } from './log_rate_analysis/actions';
interface StreamState {
ccsWarning: boolean;
significantItems: SignificantTerm[];
significantItemsGroups: SignificantTermGroup[];
significantItems: SignificantItem[];
significantItemsGroups: SignificantItemGroup[];
errors: string[];
loaded: number;
loadingState: string;

View file

@ -5,11 +5,11 @@
* 2.0.
*/
import type { SignificantTerm, SignificantTermType, FieldValuePair } from '@kbn/ml-agg-utils';
import type { SignificantItem, SignificantItemType, FieldValuePair } from '@kbn/ml-agg-utils';
export interface SignificantTermDuplicateGroup {
keys: Pick<SignificantTerm, keyof SignificantTerm>;
group: SignificantTerm[];
export interface SignificantItemDuplicateGroup {
keys: Pick<SignificantItem, keyof SignificantItem>;
group: SignificantItem[];
}
export type FieldValuePairCounts = Record<string, Record<string, number>>;
@ -31,7 +31,7 @@ export interface FetchFrequentItemSetsResponse {
interface SimpleHierarchicalTreeNodeSet extends FieldValuePair {
key: string;
type: SignificantTermType;
type: SignificantItemType;
docCount: number;
pValue: number | null;
}

View file

@ -5,13 +5,13 @@
* 2.0.
*/
import type { SignificantTerm } from '@kbn/ml-agg-utils';
import type { SignificantItem } from '@kbn/ml-agg-utils';
import type { GroupTableItem } from '../../components/log_rate_analysis_results_table/types';
import { buildExtendedBaseFilterCriteria } from './build_extended_base_filter_criteria';
const selectedSignificantTermMock: SignificantTerm = {
const selectedSignificantItemMock: SignificantItem = {
key: 'meta.cloud.instance_id.keyword:1234',
type: 'keyword',
doc_count: 53408,
@ -123,13 +123,13 @@ describe('query_utils', () => {
]);
});
it('includes a term filter when including a selectedSignificantTerm', () => {
it('includes a term filter when including a selectedSignificantItem', () => {
const baseFilterCriteria = buildExtendedBaseFilterCriteria(
'@timestamp',
1640082000012,
1640103600906,
{ match_all: {} },
selectedSignificantTermMock
selectedSignificantItemMock
);
expect(baseFilterCriteria).toEqual([
@ -147,13 +147,13 @@ describe('query_utils', () => {
]);
});
it('includes a term filter with must_not when excluding a selectedSignificantTerm', () => {
it('includes a term filter with must_not when excluding a selectedSignificantItem', () => {
const baseFilterCriteria = buildExtendedBaseFilterCriteria(
'@timestamp',
1640082000012,
1640103600906,
{ match_all: {} },
selectedSignificantTermMock,
selectedSignificantItemMock,
false
);

View file

@ -11,7 +11,7 @@
import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import type { Query } from '@kbn/es-query';
import { type SignificantTerm, SIGNIFICANT_TERM_TYPE } from '@kbn/ml-agg-utils';
import { type SignificantItem, SIGNIFICANT_ITEM_TYPE } from '@kbn/ml-agg-utils';
import { buildBaseFilterCriteria } from '@kbn/ml-query-utils';
@ -30,8 +30,8 @@ export function buildExtendedBaseFilterCriteria(
earliestMs?: number,
latestMs?: number,
query?: Query['query'],
selectedSignificantTerm?: SignificantTerm,
includeSelectedSignificantTerm = true,
selectedSignificantItem?: SignificantItem,
includeSelectedSignificantItem = true,
selectedGroup?: GroupTableItem | null
): estypes.QueryDslQueryContainer[] {
const filterCriteria = buildBaseFilterCriteria(timeFieldName, earliestMs, latestMs, query);
@ -41,7 +41,7 @@ export function buildExtendedBaseFilterCriteria(
const allItems = selectedGroup.groupItemsSortedByUniqueness;
for (const item of allItems) {
const { fieldName, fieldValue, key, type, docCount } = item;
if (type === SIGNIFICANT_TERM_TYPE.KEYWORD) {
if (type === SIGNIFICANT_ITEM_TYPE.KEYWORD) {
groupFilter.push({ term: { [fieldName]: fieldValue } });
} else {
groupFilter.push(
@ -57,18 +57,18 @@ export function buildExtendedBaseFilterCriteria(
}
}
if (includeSelectedSignificantTerm) {
if (selectedSignificantTerm) {
if (selectedSignificantTerm.type === 'keyword') {
if (includeSelectedSignificantItem) {
if (selectedSignificantItem) {
if (selectedSignificantItem.type === 'keyword') {
filterCriteria.push({
term: { [selectedSignificantTerm.fieldName]: selectedSignificantTerm.fieldValue },
term: { [selectedSignificantItem.fieldName]: selectedSignificantItem.fieldValue },
});
} else {
filterCriteria.push(
getCategoryQuery(selectedSignificantTerm.fieldName, [
getCategoryQuery(selectedSignificantItem.fieldName, [
{
key: `${selectedSignificantTerm.key}`,
count: selectedSignificantTerm.doc_count,
key: `${selectedSignificantItem.key}`,
count: selectedSignificantItem.doc_count,
examples: [],
},
])
@ -77,13 +77,13 @@ export function buildExtendedBaseFilterCriteria(
} else if (selectedGroup) {
filterCriteria.push(...groupFilter);
}
} else if (selectedSignificantTerm && !includeSelectedSignificantTerm) {
if (selectedSignificantTerm.type === 'keyword') {
} else if (selectedSignificantItem && !includeSelectedSignificantItem) {
if (selectedSignificantItem.type === 'keyword') {
filterCriteria.push({
bool: {
must_not: [
{
term: { [selectedSignificantTerm.fieldName]: selectedSignificantTerm.fieldValue },
term: { [selectedSignificantItem.fieldName]: selectedSignificantItem.fieldValue },
},
],
},
@ -92,10 +92,10 @@ export function buildExtendedBaseFilterCriteria(
filterCriteria.push({
bool: {
must_not: [
getCategoryQuery(selectedSignificantTerm.fieldName, [
getCategoryQuery(selectedSignificantItem.fieldName, [
{
key: `${selectedSignificantTerm.key}`,
count: selectedSignificantTerm.doc_count,
key: `${selectedSignificantItem.key}`,
count: selectedSignificantItem.doc_count,
examples: [],
},
]),
@ -103,7 +103,7 @@ export function buildExtendedBaseFilterCriteria(
},
});
}
} else if (selectedGroup && !includeSelectedSignificantTerm) {
} else if (selectedGroup && !includeSelectedSignificantItem) {
filterCriteria.push({
bool: {
must_not: [

View file

@ -20,7 +20,7 @@ import {
type LogRateAnalysisType,
type WindowParameters,
} from '@kbn/aiops-utils';
import type { SignificantTerm } from '@kbn/ml-agg-utils';
import type { SignificantItem } from '@kbn/ml-agg-utils';
import { useData } from '../../../hooks/use_data';
@ -35,11 +35,11 @@ import { useLogRateAnalysisResultsTableRowContext } from '../../log_rate_analysi
const DEFAULT_SEARCH_QUERY = { match_all: {} };
export function getDocumentCountStatsSplitLabel(
significantTerm?: SignificantTerm,
significantItem?: SignificantItem,
group?: GroupTableItem
) {
if (significantTerm) {
return `${significantTerm?.fieldName}:${significantTerm?.fieldValue}`;
if (significantItem) {
return `${significantItem?.fieldName}:${significantItem?.fieldValue}`;
} else if (group) {
return i18n.translate('xpack.aiops.logRateAnalysis.page.documentCountStatsSplitGroupLabel', {
defaultMessage: 'Selected group',
@ -94,11 +94,11 @@ export const LogRateAnalysisContent: FC<LogRateAnalysisContentProps> = ({
}, [windowParameters]);
const {
currentSelectedSignificantTerm,
currentSelectedSignificantItem,
currentSelectedGroup,
setPinnedSignificantTerm,
setPinnedSignificantItem,
setPinnedGroup,
setSelectedSignificantTerm,
setSelectedSignificantItem,
setSelectedGroup,
} = useLogRateAnalysisResultsTableRowContext();
@ -107,7 +107,7 @@ export const LogRateAnalysisContent: FC<LogRateAnalysisContentProps> = ({
'log_rate_analysis',
esSearchQuery,
setGlobalState,
currentSelectedSignificantTerm,
currentSelectedSignificantItem,
currentSelectedGroup,
undefined,
timeRange
@ -132,9 +132,9 @@ export const LogRateAnalysisContent: FC<LogRateAnalysisContentProps> = ({
function clearSelection() {
setWindowParameters(undefined);
setPinnedSignificantTerm(null);
setPinnedSignificantItem(null);
setPinnedGroup(null);
setSelectedSignificantTerm(null);
setSelectedSignificantItem(null);
setSelectedGroup(null);
setIsBrushCleared(true);
setInitialAnalysisStart(undefined);
@ -148,7 +148,7 @@ export const LogRateAnalysisContent: FC<LogRateAnalysisContentProps> = ({
documentCountStats={documentCountStats}
documentCountStatsSplit={documentCountStatsCompare}
documentCountStatsSplitLabel={getDocumentCountStatsSplitLabel(
currentSelectedSignificantTerm,
currentSelectedSignificantItem,
currentSelectedGroup
)}
isBrushCleared={isBrushCleared}

View file

@ -37,7 +37,7 @@ export const LogRateAnalysisPage: FC<Props> = ({ stickyHistogram }) => {
const { data: dataService } = useAiopsAppContext();
const { dataView, savedSearch } = useDataSource();
const { currentSelectedSignificantTerm, currentSelectedGroup } =
const { currentSelectedSignificantItem, currentSelectedGroup } =
useLogRateAnalysisResultsTableRowContext();
const [aiopsListState, setAiopsListState] = usePageUrlState<AiOpsPageUrlState>(
@ -88,7 +88,7 @@ export const LogRateAnalysisPage: FC<Props> = ({ stickyHistogram }) => {
'log_rate_analysis',
searchQuery,
setGlobalState,
currentSelectedSignificantTerm,
currentSelectedSignificantItem,
currentSelectedGroup
);

View file

@ -31,7 +31,7 @@ import {
} from '@kbn/aiops-utils';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import type { SignificantTerm, SignificantTermGroup } from '@kbn/ml-agg-utils';
import type { SignificantItem, SignificantItemGroup } from '@kbn/ml-agg-utils';
import { useAiopsAppContext } from '../../hooks/use_aiops_app_context';
import { initialState, streamReducer } from '../../../common/api/stream_reducer';
@ -81,9 +81,9 @@ export interface LogRateAnalysisResultsData {
/** The type of analysis, whether it's a spike or dip */
analysisType: LogRateAnalysisType;
/** Statistically significant field/value items. */
significantTerms: SignificantTerm[];
significantItems: SignificantItem[];
/** Statistically significant groups of field/value items. */
significantTermsGroups: SignificantTermGroup[];
significantItemsGroups: SignificantItemGroup[];
}
/**
@ -234,8 +234,8 @@ export const LogRateAnalysisResults: FC<LogRateAnalysisResultsProps> = ({
if (onAnalysisCompleted) {
onAnalysisCompleted({
analysisType,
significantTerms: data.significantItems,
significantTermsGroups: data.significantItemsGroups,
significantItems: data.significantItems,
significantItemsGroups: data.significantItemsGroups,
});
}
}
@ -246,7 +246,7 @@ export const LogRateAnalysisResults: FC<LogRateAnalysisResultsProps> = ({
const errors = useMemo(() => [...streamErrors, ...data.errors], [streamErrors, data.errors]);
// Start handler clears possibly hovered or pinned
// significant terms on analysis refresh.
// significant items on analysis refresh.
function startHandler(continueAnalysis = false, resetGroupButton = true) {
if (!continueAnalysis) {
setOverrides(undefined);
@ -482,7 +482,7 @@ export const LogRateAnalysisResults: FC<LogRateAnalysisResultsProps> = ({
>
{showLogRateAnalysisResultsTable && groupResults ? (
<LogRateAnalysisResultsGroupsTable
significantTerms={data.significantItems}
significantItems={data.significantItems}
groupTableItems={groupTableItems}
loading={isRunning}
dataView={dataView}
@ -494,7 +494,7 @@ export const LogRateAnalysisResults: FC<LogRateAnalysisResultsProps> = ({
) : null}
{showLogRateAnalysisResultsTable && !groupResults ? (
<LogRateAnalysisResultsTable
significantTerms={data.significantItems}
significantItems={data.significantItems}
loading={isRunning}
dataView={dataView}
timeRangeMs={timeRangeMs}

View file

@ -5,13 +5,13 @@
* 2.0.
*/
import { finalSignificantTermGroups } from '../../../common/__mocks__/artificial_logs/final_significant_term_groups';
import { finalSignificantItemGroups } from '../../../common/__mocks__/artificial_logs/final_significant_item_groups';
import { getGroupTableItems } from './get_group_table_items';
describe('getGroupTableItems', () => {
it('transforms groups into table items', () => {
const groupTableItems = getGroupTableItems(finalSignificantTermGroups);
const groupTableItems = getGroupTableItems(finalSignificantItemGroups);
expect(groupTableItems).toEqual([
{

View file

@ -7,14 +7,14 @@
import { sortBy } from 'lodash';
import type { SignificantTermGroup } from '@kbn/ml-agg-utils';
import type { SignificantItemGroup } from '@kbn/ml-agg-utils';
import type { GroupTableItem, GroupTableItemGroup } from './types';
export function getGroupTableItems(
significantTermsGroups: SignificantTermGroup[]
significantItemsGroups: SignificantItemGroup[]
): GroupTableItem[] {
const tableItems = significantTermsGroups.map(({ id, group, docCount, histogram, pValue }) => {
const tableItems = significantItemsGroups.map(({ id, group, docCount, histogram, pValue }) => {
const sortedGroup = sortBy(group, [(d) => d.fieldName]);
const dedupedGroup: GroupTableItemGroup[] = [];

View file

@ -5,21 +5,21 @@
* 2.0.
*/
import { finalSignificantTermGroups } from '../../../common/__mocks__/artificial_logs/final_significant_term_groups';
import { finalSignificantItemGroups } from '../../../common/__mocks__/artificial_logs/final_significant_item_groups';
import { significantTerms } from '../../../common/__mocks__/artificial_logs/significant_terms';
import { getGroupTableItems } from './get_group_table_items';
import { getTableItemAsKQL } from './get_table_item_as_kql';
describe('getTableItemAsKQL', () => {
it('returns a KQL syntax for a significant term', () => {
it('returns a KQL syntax for a significant item', () => {
expect(getTableItemAsKQL(significantTerms[0])).toBe('user:Peter');
expect(getTableItemAsKQL(significantTerms[1])).toBe('response_code:500');
expect(getTableItemAsKQL(significantTerms[2])).toBe('url:home.php');
expect(getTableItemAsKQL(significantTerms[3])).toBe('url:login.php');
});
it('returns a KQL syntax for a group of significant terms', () => {
const groupTableItems = getGroupTableItems(finalSignificantTermGroups);
it('returns a KQL syntax for a group of significant items', () => {
const groupTableItems = getGroupTableItems(finalSignificantItemGroups);
expect(getTableItemAsKQL(groupTableItems[0])).toBe('user:Peter AND url:login.php');
expect(getTableItemAsKQL(groupTableItems[1])).toBe('response_code:500 AND url:home.php');
expect(getTableItemAsKQL(groupTableItems[2])).toBe('url:login.php AND response_code:500');

View file

@ -6,12 +6,12 @@
*/
import { escapeKuery } from '@kbn/es-query';
import { isSignificantTerm, type SignificantTerm } from '@kbn/ml-agg-utils';
import { isSignificantItem, type SignificantItem } from '@kbn/ml-agg-utils';
import type { GroupTableItem } from './types';
export const getTableItemAsKQL = (tableItem: GroupTableItem | SignificantTerm) => {
if (isSignificantTerm(tableItem)) {
export const getTableItemAsKQL = (tableItem: GroupTableItem | SignificantItem) => {
if (isSignificantItem(tableItem)) {
return `${escapeKuery(tableItem.fieldName)}:${escapeKuery(String(tableItem.fieldValue))}`;
}

View file

@ -27,7 +27,7 @@ import type { FieldStatsServices } from '@kbn/unified-field-list/src/components/
import type { DataView } from '@kbn/data-views-plugin/public';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import { type SignificantTerm, SIGNIFICANT_TERM_TYPE } from '@kbn/ml-agg-utils';
import { type SignificantItem, SIGNIFICANT_ITEM_TYPE } from '@kbn/ml-agg-utils';
import type { TimeRange as TimeRangeMs } from '@kbn/ml-date-picker';
import { getCategoryQuery } from '../../../common/api/log_categorization/get_category_query';
@ -56,7 +56,7 @@ const DEFAULT_SORT_DIRECTION = 'asc';
const TRUNCATE_TEXT_LINES = 3;
interface LogRateAnalysisResultsTableProps {
significantTerms: SignificantTerm[];
significantItems: SignificantItem[];
dataView: DataView;
loading: boolean;
isExpandedRow?: boolean;
@ -69,7 +69,7 @@ interface LogRateAnalysisResultsTableProps {
}
export const LogRateAnalysisResultsTable: FC<LogRateAnalysisResultsTableProps> = ({
significantTerms,
significantItems,
dataView,
loading,
isExpandedRow,
@ -84,16 +84,16 @@ export const LogRateAnalysisResultsTable: FC<LogRateAnalysisResultsTableProps> =
const {
pinnedGroup,
pinnedSignificantTerm,
pinnedSignificantItem,
selectedGroup,
selectedSignificantTerm,
setPinnedSignificantTerm,
setSelectedSignificantTerm,
selectedSignificantItem,
setPinnedSignificantItem,
setSelectedSignificantItem,
} = useLogRateAnalysisResultsTableRowContext();
const [pageIndex, setPageIndex] = useState(0);
const [pageSize, setPageSize] = useState(10);
const [sortField, setSortField] = useState<keyof SignificantTerm>(DEFAULT_SORT_FIELD);
const [sortField, setSortField] = useState<keyof SignificantItem>(DEFAULT_SORT_FIELD);
const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>(DEFAULT_SORT_DIRECTION);
const { data, uiSettings, fieldFormats, charts } = useAiopsAppContext();
@ -112,7 +112,7 @@ export const LogRateAnalysisResultsTable: FC<LogRateAnalysisResultsTableProps> =
const viewInDiscoverAction = useViewInDiscoverAction(dataViewId);
const viewInLogPatternAnalysisAction = useViewInLogPatternAnalysisAction(dataViewId);
const columns: Array<EuiBasicTableColumn<SignificantTerm>> = [
const columns: Array<EuiBasicTableColumn<SignificantItem>> = [
{
'data-test-subj': 'aiopsLogRateAnalysisResultsTableColumnFieldName',
field: 'fieldName',
@ -121,7 +121,7 @@ export const LogRateAnalysisResultsTable: FC<LogRateAnalysisResultsTableProps> =
}),
render: (_, { fieldName, fieldValue, key, type, doc_count: count }) => {
const dslQuery =
type === SIGNIFICANT_TERM_TYPE.KEYWORD
type === SIGNIFICANT_ITEM_TYPE.KEYWORD
? searchQuery
: getCategoryQuery(fieldName, [
{
@ -132,17 +132,17 @@ export const LogRateAnalysisResultsTable: FC<LogRateAnalysisResultsTableProps> =
]);
return (
<>
{type === SIGNIFICANT_TERM_TYPE.KEYWORD && (
{type === SIGNIFICANT_ITEM_TYPE.KEYWORD && (
<FieldStatsPopover
dataView={dataView}
fieldName={fieldName}
fieldValue={type === SIGNIFICANT_TERM_TYPE.KEYWORD ? fieldValue : key}
fieldValue={type === SIGNIFICANT_ITEM_TYPE.KEYWORD ? fieldValue : key}
fieldStatsServices={fieldStatsServices}
dslQuery={dslQuery}
timeRangeMs={timeRangeMs}
/>
)}
{type === SIGNIFICANT_TERM_TYPE.LOG_PATTERN && (
{type === SIGNIFICANT_ITEM_TYPE.LOG_PATTERN && (
<EuiToolTip
content={i18n.translate(
'xpack.aiops.fieldContextPopover.descriptionTooltipLogPattern',
@ -351,12 +351,12 @@ export const LogRateAnalysisResultsTable: FC<LogRateAnalysisResultsTableProps> =
const { pagination, pageOfItems, sorting } = useMemo(() => {
const pageStart = pageIndex * pageSize;
const itemCount = significantTerms?.length ?? 0;
const itemCount = significantItems?.length ?? 0;
let items: SignificantTerm[] = significantTerms ?? [];
let items: SignificantItem[] = significantItems ?? [];
const sortIteratees = [
(item: SignificantTerm) => {
(item: SignificantItem) => {
if (item && typeof item[sortField] === 'string') {
// @ts-ignore Object is possibly null or undefined
return item[sortField].toLowerCase();
@ -368,11 +368,11 @@ export const LogRateAnalysisResultsTable: FC<LogRateAnalysisResultsTableProps> =
// Only if the table is sorted by p-value, add a secondary sort by doc count.
if (sortField === 'pValue') {
sortIteratees.push((item: SignificantTerm) => item.doc_count);
sortIteratees.push((item: SignificantItem) => item.doc_count);
sortDirections.push(sortDirection);
}
items = orderBy(significantTerms, sortIteratees, sortDirections);
items = orderBy(significantItems, sortIteratees, sortDirections);
return {
pageOfItems: items.slice(pageStart, pageStart + pageSize),
@ -389,59 +389,59 @@ export const LogRateAnalysisResultsTable: FC<LogRateAnalysisResultsTableProps> =
},
},
};
}, [pageIndex, pageSize, sortField, sortDirection, significantTerms]);
}, [pageIndex, pageSize, sortField, sortDirection, significantItems]);
useEffect(() => {
// If no row is hovered or pinned or the user switched to a new page,
// fall back to set the first row into a hovered state to make the
// main document count chart show a comparison view by default.
if (
(selectedSignificantTerm === null ||
!pageOfItems.some((item) => isEqual(item, selectedSignificantTerm))) &&
pinnedSignificantTerm === null &&
(selectedSignificantItem === null ||
!pageOfItems.some((item) => isEqual(item, selectedSignificantItem))) &&
pinnedSignificantItem === null &&
pageOfItems.length > 0 &&
selectedGroup === null &&
pinnedGroup === null
) {
setSelectedSignificantTerm(pageOfItems[0]);
setSelectedSignificantItem(pageOfItems[0]);
}
// If a user switched pages and a pinned row is no longer visible
// on the current page, set the status of pinned rows back to `null`.
if (
pinnedSignificantTerm !== null &&
!pageOfItems.some((item) => isEqual(item, pinnedSignificantTerm)) &&
pinnedSignificantItem !== null &&
!pageOfItems.some((item) => isEqual(item, pinnedSignificantItem)) &&
selectedGroup === null &&
pinnedGroup === null
) {
setPinnedSignificantTerm(null);
setPinnedSignificantItem(null);
}
}, [
selectedGroup,
selectedSignificantTerm,
setSelectedSignificantTerm,
setPinnedSignificantTerm,
selectedSignificantItem,
setSelectedSignificantItem,
setPinnedSignificantItem,
pageOfItems,
pinnedGroup,
pinnedSignificantTerm,
pinnedSignificantItem,
]);
// When the analysis results table unmounts,
// make sure to reset any hovered or pinned rows.
useEffect(
() => () => {
setSelectedSignificantTerm(null);
setPinnedSignificantTerm(null);
setSelectedSignificantItem(null);
setPinnedSignificantItem(null);
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[]
);
const getRowStyle = (significantTerm: SignificantTerm) => {
const getRowStyle = (significantItem: SignificantItem) => {
if (
pinnedSignificantTerm &&
pinnedSignificantTerm.fieldName === significantTerm.fieldName &&
pinnedSignificantTerm.fieldValue === significantTerm.fieldValue
pinnedSignificantItem &&
pinnedSignificantItem.fieldName === significantItem.fieldName &&
pinnedSignificantItem.fieldValue === significantItem.fieldValue
) {
return {
backgroundColor: primaryBackgroundColor,
@ -449,9 +449,9 @@ export const LogRateAnalysisResultsTable: FC<LogRateAnalysisResultsTableProps> =
}
if (
selectedSignificantTerm &&
selectedSignificantTerm.fieldName === significantTerm.fieldName &&
selectedSignificantTerm.fieldValue === significantTerm.fieldValue
selectedSignificantItem &&
selectedSignificantItem.fieldName === significantItem.fieldName &&
selectedSignificantItem.fieldValue === significantItem.fieldValue
) {
return {
backgroundColor: euiTheme.euiColorLightestShade,
@ -479,29 +479,29 @@ export const LogRateAnalysisResultsTable: FC<LogRateAnalysisResultsTableProps> =
onChange={onChange}
pagination={pagination.totalItemCount > pagination.pageSize ? pagination : undefined}
loading={false}
sorting={sorting as EuiTableSortingType<SignificantTerm>}
rowProps={(significantTerm) => {
sorting={sorting as EuiTableSortingType<SignificantItem>}
rowProps={(significantItem) => {
return {
'data-test-subj': `aiopsLogRateAnalysisResultsTableRow row-${significantTerm.fieldName}-${significantTerm.fieldValue}`,
'data-test-subj': `aiopsLogRateAnalysisResultsTableRow row-${significantItem.fieldName}-${significantItem.fieldValue}`,
onClick: () => {
if (
significantTerm.fieldName === pinnedSignificantTerm?.fieldName &&
significantTerm.fieldValue === pinnedSignificantTerm?.fieldValue
significantItem.fieldName === pinnedSignificantItem?.fieldName &&
significantItem.fieldValue === pinnedSignificantItem?.fieldValue
) {
setPinnedSignificantTerm(null);
setPinnedSignificantItem(null);
} else {
setPinnedSignificantTerm(significantTerm);
setPinnedSignificantItem(significantItem);
}
},
onMouseEnter: () => {
if (pinnedSignificantTerm === null) {
setSelectedSignificantTerm(significantTerm);
if (pinnedSignificantItem === null) {
setSelectedSignificantItem(significantItem);
}
},
onMouseLeave: () => {
setSelectedSignificantTerm(null);
setSelectedSignificantItem(null);
},
style: getRowStyle(significantTerm),
style: getRowStyle(significantItem),
};
}}
/>

View file

@ -28,7 +28,7 @@ import {
import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import type { SignificantTerm } from '@kbn/ml-agg-utils';
import type { SignificantItem } from '@kbn/ml-agg-utils';
import type { TimeRange as TimeRangeMs } from '@kbn/ml-date-picker';
import type { DataView } from '@kbn/data-views-plugin/public';
@ -53,7 +53,7 @@ const DEFAULT_SORT_FIELD = 'pValue';
const DEFAULT_SORT_DIRECTION = 'asc';
interface LogRateAnalysisResultsTableProps {
significantTerms: SignificantTerm[];
significantItems: SignificantItem[];
groupTableItems: GroupTableItem[];
loading: boolean;
searchQuery: estypes.QueryDslQueryContainer;
@ -66,7 +66,7 @@ interface LogRateAnalysisResultsTableProps {
}
export const LogRateAnalysisResultsGroupsTable: FC<LogRateAnalysisResultsTableProps> = ({
significantTerms,
significantItems,
groupTableItems,
loading,
dataView,
@ -98,9 +98,9 @@ export const LogRateAnalysisResultsGroupsTable: FC<LogRateAnalysisResultsTablePr
} else {
itemIdToExpandedRowMapValues[item.id] = (
<LogRateAnalysisResultsTable
significantTerms={item.groupItemsSortedByUniqueness.reduce<SignificantTerm[]>(
significantItems={item.groupItemsSortedByUniqueness.reduce<SignificantItem[]>(
(p, groupItem) => {
const st = significantTerms.find(
const st = significantItems.find(
(d) => d.fieldName === groupItem.fieldName && d.fieldValue === groupItem.fieldValue
);
@ -139,7 +139,11 @@ export const LogRateAnalysisResultsGroupsTable: FC<LogRateAnalysisResultsTablePr
isExpander: true,
name: (
<EuiScreenReaderOnly>
<span>Expand rows</span>
<span>
{i18n.translate('xpack.aiops.logRateAnalysis.resultsTable.expandRowsLabel', {
defaultMessage: 'Expand rows',
})}
</span>
</EuiScreenReaderOnly>
),
render: (item: GroupTableItem) => (

View file

@ -15,23 +15,23 @@ import React, {
type SetStateAction,
} from 'react';
import type { SignificantTerm } from '@kbn/ml-agg-utils';
import type { SignificantItem } from '@kbn/ml-agg-utils';
import type { GroupTableItem } from './types';
type SignificantTermOrNull = SignificantTerm | null;
type SignificantItemOrNull = SignificantItem | null;
type GroupOrNull = GroupTableItem | null;
interface LogRateAnalysisResultsTableRow {
pinnedSignificantTerm: SignificantTermOrNull;
setPinnedSignificantTerm: Dispatch<SetStateAction<SignificantTermOrNull>>;
pinnedSignificantItem: SignificantItemOrNull;
setPinnedSignificantItem: Dispatch<SetStateAction<SignificantItemOrNull>>;
pinnedGroup: GroupOrNull;
setPinnedGroup: Dispatch<SetStateAction<GroupOrNull>>;
selectedSignificantTerm: SignificantTermOrNull;
setSelectedSignificantTerm: Dispatch<SetStateAction<SignificantTermOrNull>>;
selectedSignificantItem: SignificantItemOrNull;
setSelectedSignificantItem: Dispatch<SetStateAction<SignificantItemOrNull>>;
selectedGroup: GroupOrNull;
setSelectedGroup: Dispatch<SetStateAction<GroupOrNull>>;
currentSelectedSignificantTerm?: SignificantTerm;
currentSelectedSignificantItem?: SignificantItem;
currentSelectedGroup?: GroupTableItem;
clearAllRowState: () => void;
}
@ -42,20 +42,20 @@ export const logRateAnalysisResultsTableRowContext = createContext<
export const LogRateAnalysisResultsTableRowStateProvider: FC = ({ children }) => {
// State that will be shared with all components
const [pinnedSignificantTerm, setPinnedSignificantTerm] = useState<SignificantTermOrNull>(null);
const [pinnedSignificantItem, setPinnedSignificantItem] = useState<SignificantItemOrNull>(null);
const [pinnedGroup, setPinnedGroup] = useState<GroupOrNull>(null);
const [selectedSignificantTerm, setSelectedSignificantTerm] =
useState<SignificantTermOrNull>(null);
const [selectedSignificantItem, setSelectedSignificantItem] =
useState<SignificantItemOrNull>(null);
const [selectedGroup, setSelectedGroup] = useState<GroupOrNull>(null);
// If a row is pinned, still overrule with a potentially hovered row.
const currentSelectedSignificantTerm = useMemo(() => {
if (selectedSignificantTerm) {
return selectedSignificantTerm;
} else if (pinnedSignificantTerm) {
return pinnedSignificantTerm;
const currentSelectedSignificantItem = useMemo(() => {
if (selectedSignificantItem) {
return selectedSignificantItem;
} else if (pinnedSignificantItem) {
return pinnedSignificantItem;
}
}, [pinnedSignificantTerm, selectedSignificantTerm]);
}, [pinnedSignificantItem, selectedSignificantItem]);
// If a group is pinned, still overrule with a potentially hovered group.
const currentSelectedGroup = useMemo(() => {
@ -68,33 +68,33 @@ export const LogRateAnalysisResultsTableRowStateProvider: FC = ({ children }) =>
const contextValue: LogRateAnalysisResultsTableRow = useMemo(
() => ({
pinnedSignificantTerm,
setPinnedSignificantTerm,
pinnedSignificantItem,
setPinnedSignificantItem,
pinnedGroup,
setPinnedGroup,
selectedSignificantTerm,
setSelectedSignificantTerm,
selectedSignificantItem,
setSelectedSignificantItem,
selectedGroup,
setSelectedGroup,
currentSelectedSignificantTerm,
currentSelectedSignificantItem,
currentSelectedGroup,
clearAllRowState: () => {
setPinnedSignificantTerm(null);
setPinnedSignificantItem(null);
setPinnedGroup(null);
setSelectedSignificantTerm(null);
setSelectedSignificantItem(null);
setSelectedGroup(null);
},
}),
[
pinnedSignificantTerm,
setPinnedSignificantTerm,
pinnedSignificantItem,
setPinnedSignificantItem,
pinnedGroup,
setPinnedGroup,
selectedSignificantTerm,
setSelectedSignificantTerm,
selectedSignificantItem,
setSelectedSignificantItem,
selectedGroup,
setSelectedGroup,
currentSelectedSignificantTerm,
currentSelectedSignificantItem,
currentSelectedGroup,
]
);

View file

@ -7,10 +7,10 @@
import type { EuiTableActionsColumnType } from '@elastic/eui';
import type { SignificantTerm, SignificantTermGroupItem } from '@kbn/ml-agg-utils';
import type { SignificantItem, SignificantItemGroupItem } from '@kbn/ml-agg-utils';
export type GroupTableItemGroup = Pick<
SignificantTermGroupItem,
SignificantItemGroupItem,
'key' | 'type' | 'fieldName' | 'fieldValue' | 'docCount' | 'pValue' | 'duplicate'
>;
@ -20,9 +20,9 @@ export interface GroupTableItem {
pValue: number | null;
uniqueItemsCount: number;
groupItemsSortedByUniqueness: GroupTableItemGroup[];
histogram: SignificantTerm['histogram'];
histogram: SignificantItem['histogram'];
}
export type TableItemAction = EuiTableActionsColumnType<
SignificantTerm | GroupTableItem
SignificantItem | GroupTableItem
>['actions'][number];

View file

@ -10,9 +10,9 @@ import userEvent from '@testing-library/user-event';
import { render, act } from '@testing-library/react';
import { renderHook } from '@testing-library/react-hooks';
import type { SignificantTerm } from '@kbn/ml-agg-utils';
import type { SignificantItem } from '@kbn/ml-agg-utils';
import { finalSignificantTermGroups } from '../../../common/__mocks__/artificial_logs/final_significant_term_groups';
import { finalSignificantItemGroups } from '../../../common/__mocks__/artificial_logs/final_significant_item_groups';
import { significantTerms } from '../../../common/__mocks__/artificial_logs/significant_terms';
import { getGroupTableItems } from './get_group_table_items';
@ -20,14 +20,14 @@ import { useCopyToClipboardAction } from './use_copy_to_clipboard_action';
import type { GroupTableItem } from './types';
interface Action {
render: (tableItem: SignificantTerm | GroupTableItem) => ReactElement;
render: (tableItem: SignificantItem | GroupTableItem) => ReactElement;
}
const execCommandMock = (global.document.execCommand = jest.fn());
const warn = jest.spyOn(console, 'warn').mockImplementation(() => {});
describe('useCopyToClipboardAction', () => {
it('renders the action for a single significant term', async () => {
it('renders the action for a single significant item', async () => {
execCommandMock.mockImplementationOnce(() => true);
const { result } = renderHook(() => useCopyToClipboardAction());
const { findByText, getByTestId } = render(
@ -57,7 +57,7 @@ describe('useCopyToClipboardAction', () => {
it('renders the action for a group of items', async () => {
execCommandMock.mockImplementationOnce(() => true);
const groupTableItems = getGroupTableItems(finalSignificantTermGroups);
const groupTableItems = getGroupTableItems(finalSignificantItemGroups);
const { result } = renderHook(useCopyToClipboardAction);
const { findByText, getByText } = render((result.current as Action).render(groupTableItems[0]));

View file

@ -10,7 +10,7 @@ import React from 'react';
import { EuiCopy, EuiToolTip } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { isSignificantTerm, type SignificantTerm } from '@kbn/ml-agg-utils';
import { isSignificantItem, type SignificantItem } from '@kbn/ml-agg-utils';
import { TableActionButton } from './table_action_button';
import { getTableItemAsKQL } from './get_table_item_as_kql';
@ -23,8 +23,8 @@ const copyToClipboardButtonLabel = i18n.translate(
}
);
const copyToClipboardSignificantTermMessage = i18n.translate(
'xpack.aiops.logRateAnalysis.resultsTable.linksMenu.copyToClipboardSignificantTermMessage',
const copyToClipboardSignificantItemMessage = i18n.translate(
'xpack.aiops.logRateAnalysis.resultsTable.linksMenu.copyToClipboardSignificantItemMessage',
{
defaultMessage: 'Copy field/value pair as KQL syntax to clipboard',
}
@ -38,9 +38,9 @@ const copyToClipboardGroupMessage = i18n.translate(
);
export const useCopyToClipboardAction = (): TableItemAction => ({
render: (tableItem: SignificantTerm | GroupTableItem) => {
const message = isSignificantTerm(tableItem)
? copyToClipboardSignificantTermMessage
render: (tableItem: SignificantItem | GroupTableItem) => {
const message = isSignificantItem(tableItem)
? copyToClipboardSignificantItemMessage
: copyToClipboardGroupMessage;
return (
<EuiToolTip content={message}>

View file

@ -8,7 +8,7 @@
import React, { useMemo } from 'react';
import { i18n } from '@kbn/i18n';
import type { SignificantTerm } from '@kbn/ml-agg-utils';
import type { SignificantItem } from '@kbn/ml-agg-utils';
import { SEARCH_QUERY_LANGUAGE } from '@kbn/ml-query-utils';
import { useAiopsAppContext } from '../../hooks/use_aiops_app_context';
@ -65,7 +65,7 @@ export const useViewInDiscoverAction = (dataViewId?: string): TableItemAction =>
}
}, [application.capabilities.discover?.show, dataViewId, discoverLocator]);
const generateDiscoverUrl = async (groupTableItem: GroupTableItem | SignificantTerm) => {
const generateDiscoverUrl = async (groupTableItem: GroupTableItem | SignificantItem) => {
if (discoverLocator !== undefined) {
const url = await discoverLocator.getRedirectUrl({
indexPatternId: dataViewId,
@ -82,7 +82,7 @@ export const useViewInDiscoverAction = (dataViewId?: string): TableItemAction =>
};
return {
render: (tableItem: SignificantTerm | GroupTableItem) => {
render: (tableItem: SignificantItem | GroupTableItem) => {
const tooltipText = discoverUrlError ? discoverUrlError : viewInDiscoverMessage;
const clickHandler = async () => {

View file

@ -10,7 +10,7 @@ import React, { useMemo } from 'react';
import { SerializableRecord } from '@kbn/utility-types';
import { fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query';
import { i18n } from '@kbn/i18n';
import { isSignificantTerm, type SignificantTerm, SIGNIFICANT_TERM_TYPE } from '@kbn/ml-agg-utils';
import { isSignificantItem, type SignificantItem, SIGNIFICANT_ITEM_TYPE } from '@kbn/ml-agg-utils';
import { SEARCH_QUERY_LANGUAGE } from '@kbn/ml-query-utils';
import { useAiopsAppContext } from '../../hooks/use_aiops_app_context';
@ -19,8 +19,8 @@ import { TableActionButton } from './table_action_button';
import { getTableItemAsKQL } from './get_table_item_as_kql';
import type { GroupTableItem, TableItemAction } from './types';
const isLogPattern = (tableItem: SignificantTerm | GroupTableItem) =>
isSignificantTerm(tableItem) && tableItem.type === SIGNIFICANT_TERM_TYPE.LOG_PATTERN;
const isLogPattern = (tableItem: SignificantItem | GroupTableItem) =>
isSignificantItem(tableItem) && tableItem.type === SIGNIFICANT_ITEM_TYPE.LOG_PATTERN;
const viewInLogPatternAnalysisMessage = i18n.translate(
'xpack.aiops.logRateAnalysis.resultsTable.linksMenu.viewInLogPatternAnalysis',
@ -35,7 +35,7 @@ export const useViewInLogPatternAnalysisAction = (dataViewId?: string): TableIte
const mlLocator = useMemo(() => share.url.locators.get('ML_APP_LOCATOR'), [share.url.locators]);
const generateLogPatternAnalysisUrl = async (
groupTableItem: GroupTableItem | SignificantTerm
groupTableItem: GroupTableItem | SignificantItem
) => {
if (mlLocator !== undefined) {
const searchString = getTableItemAsKQL(groupTableItem);
@ -85,7 +85,7 @@ export const useViewInLogPatternAnalysisAction = (dataViewId?: string): TableIte
}, [dataViewId, mlLocator]);
return {
render: (tableItem: SignificantTerm | GroupTableItem) => {
render: (tableItem: SignificantItem | GroupTableItem) => {
const message = logPatternAnalysisUrlError
? logPatternAnalysisUrlError
: viewInLogPatternAnalysisMessage;

View file

@ -20,14 +20,14 @@ import {
import { EuiLoadingChart, EuiTextColor } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react';
import type { SignificantTermHistogramItem } from '@kbn/ml-agg-utils';
import type { SignificantItemHistogramItem } from '@kbn/ml-agg-utils';
import { i18n } from '@kbn/i18n';
import { useAiopsAppContext } from '../../hooks/use_aiops_app_context';
import { useEuiTheme } from '../../hooks/use_eui_theme';
interface MiniHistogramProps {
chartData?: SignificantTermHistogramItem[];
chartData?: SignificantItemHistogramItem[];
isLoading: boolean;
label: string;
/** Optional color override for the default bar color for charts */

View file

@ -10,7 +10,7 @@ import { each, get } from 'lodash';
import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { isPopulatedObject } from '@kbn/ml-is-populated-object';
import type { SignificantTerm } from '@kbn/ml-agg-utils';
import type { SignificantItem } from '@kbn/ml-agg-utils';
import type { Query } from '@kbn/es-query';
import type { RandomSamplerWrapper } from '@kbn/ml-random-sampler-utils';
@ -34,8 +34,8 @@ export interface DocumentStatsSearchStrategyParams {
timeFieldName?: string;
runtimeFieldMap?: estypes.MappingRuntimeFields;
fieldsToFetch?: string[];
selectedSignificantTerm?: SignificantTerm;
includeSelectedSignificantTerm?: boolean;
selectedSignificantItem?: SignificantItem;
includeSelectedSignificantItem?: boolean;
selectedGroup?: GroupTableItem | null;
trackTotalHits?: boolean;
}
@ -54,8 +54,8 @@ export const getDocumentCountStatsRequest = (
searchQuery,
intervalMs,
fieldsToFetch,
selectedSignificantTerm,
includeSelectedSignificantTerm,
selectedSignificantItem,
includeSelectedSignificantItem,
selectedGroup,
trackTotalHits,
} = params;
@ -66,8 +66,8 @@ export const getDocumentCountStatsRequest = (
earliestMs,
latestMs,
searchQuery,
selectedSignificantTerm,
includeSelectedSignificantTerm,
selectedSignificantItem,
includeSelectedSignificantItem,
selectedGroup
);

View file

@ -11,7 +11,7 @@ import type { Moment } from 'moment';
import { useExecutionContext } from '@kbn/kibana-react-plugin/public';
import type { DataView } from '@kbn/data-views-plugin/public';
import type { SignificantTerm } from '@kbn/ml-agg-utils';
import type { SignificantItem } from '@kbn/ml-agg-utils';
import type { Dictionary } from '@kbn/ml-url-state';
import { mlTimefilterRefresh$, useTimefilter } from '@kbn/ml-date-picker';
@ -34,7 +34,7 @@ export const useData = (
contextId: string,
searchQuery: estypes.QueryDslQueryContainer,
onUpdate?: (params: Dictionary<unknown>) => void,
selectedSignificantTerm?: SignificantTerm,
selectedSignificantItem?: SignificantItem,
selectedGroup: GroupTableItem | null = null,
barTarget: number = DEFAULT_BAR_TARGET,
timeRange?: { min: Moment; max: Moment }
@ -78,27 +78,27 @@ export const useData = (
return fieldStatsRequest
? {
...fieldStatsRequest,
selectedSignificantTerm,
selectedSignificantItem,
selectedGroup,
includeSelectedSignificantTerm: false,
includeSelectedSignificantItem: false,
}
: undefined;
}, [fieldStatsRequest, selectedSignificantTerm, selectedGroup]);
}, [fieldStatsRequest, selectedSignificantItem, selectedGroup]);
const selectedSignificantTermStatsRequest = useMemo(() => {
return fieldStatsRequest && (selectedSignificantTerm || selectedGroup)
const selectedSignificantItemStatsRequest = useMemo(() => {
return fieldStatsRequest && (selectedSignificantItem || selectedGroup)
? {
...fieldStatsRequest,
selectedSignificantTerm,
selectedSignificantItem,
selectedGroup,
includeSelectedSignificantTerm: true,
includeSelectedSignificantItem: true,
}
: undefined;
}, [fieldStatsRequest, selectedSignificantTerm, selectedGroup]);
}, [fieldStatsRequest, selectedSignificantItem, selectedGroup]);
const documentStats = useDocumentCountStats(
overallStatsRequest,
selectedSignificantTermStatsRequest,
selectedSignificantItemStatsRequest,
lastRefresh
);

View file

@ -94,7 +94,7 @@ export function useDocumentCountStats<TParams extends DocumentStatsSearchStrateg
const totalHitsParams = {
...searchParams,
selectedSignificantTerm: undefined,
selectedSignificantItem: undefined,
trackTotalHits: true,
};

View file

@ -5,12 +5,12 @@
* 2.0.
*/
import type { SignificantTerm } from '@kbn/ml-agg-utils';
import type { SignificantItem } from '@kbn/ml-agg-utils';
// To optimize the `frequent_item_sets` query, we identify duplicate significant terms by count attributes.
// Note this is a compromise and not 100% accurate because there could be significant terms that
// To optimize the `frequent_item_sets` query, we identify duplicate significant items by count attributes.
// Note this is a compromise and not 100% accurate because there could be significant items that
// have the exact same counts but still don't co-occur.
export const duplicateIdentifier: Array<keyof SignificantTerm> = [
export const duplicateIdentifier: Array<keyof SignificantItem> = [
'doc_count',
'bg_count',
'total_doc_count',

View file

@ -12,12 +12,12 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server';
import type { Logger } from '@kbn/logging';
import { type SignificantTerm } from '@kbn/ml-agg-utils';
import { type SignificantItem } from '@kbn/ml-agg-utils';
import { createRandomSamplerWrapper } from '@kbn/ml-random-sampler-utils';
import { RANDOM_SAMPLER_SEED, LOG_RATE_ANALYSIS_SETTINGS } from '../../../../common/constants';
import type {
SignificantTermDuplicateGroup,
SignificantItemDuplicateGroup,
ItemSet,
FetchFrequentItemSetsResponse,
} from '../../../../common/types';
@ -29,10 +29,10 @@ interface FrequentItemSetsAggregation extends estypes.AggregationsSamplerAggrega
}
export function groupDuplicates(
cps: SignificantTerm[],
uniqueFields: Array<keyof SignificantTerm>
cps: SignificantItem[],
uniqueFields: Array<keyof SignificantItem>
) {
const groups: SignificantTermDuplicateGroup[] = [];
const groups: SignificantItemDuplicateGroup[] = [];
for (const cp of cps) {
const compareAttributes = pick(cp, uniqueFields);
@ -51,16 +51,16 @@ export function groupDuplicates(
return groups;
}
export function getShouldClauses(significantTerms: SignificantTerm[]) {
export function getShouldClauses(significantItems: SignificantItem[]) {
return Array.from(
group(significantTerms, ({ fieldName }) => fieldName),
group(significantItems, ({ fieldName }) => fieldName),
([field, values]) => ({ terms: { [field]: values.map((d) => d.fieldValue) } })
);
}
export function getFrequentItemSetsAggFields(significantTerms: SignificantTerm[]) {
export function getFrequentItemSetsAggFields(significantItems: SignificantItem[]) {
return Array.from(
group(significantTerms, ({ fieldName }) => fieldName),
group(significantItems, ({ fieldName }) => fieldName),
([field, values]) => ({ field, include: values.map((d) => String(d.fieldValue)) })
);
}
@ -69,7 +69,7 @@ export async function fetchFrequentItemSets(
client: ElasticsearchClient,
index: string,
searchQuery: estypes.QueryDslQueryContainer,
significantTerms: SignificantTerm[],
significantItems: SignificantItem[],
timeFieldName: string,
deviationMin: number,
deviationMax: number,
@ -80,7 +80,7 @@ export async function fetchFrequentItemSets(
abortSignal?: AbortSignal
): Promise<FetchFrequentItemSetsResponse> {
// Sort significant terms by ascending p-value, necessary to apply the field limit correctly.
const sortedSignificantTerms = significantTerms.slice().sort((a, b) => {
const sortedSignificantItems = significantItems.slice().sort((a, b) => {
return (a.pValue ?? 0) - (b.pValue ?? 0);
});
@ -98,7 +98,7 @@ export async function fetchFrequentItemSets(
},
},
],
should: getShouldClauses(sortedSignificantTerms),
should: getShouldClauses(sortedSignificantItems),
},
};
@ -108,7 +108,7 @@ export async function fetchFrequentItemSets(
minimum_set_size: 2,
size: 200,
minimum_support: LOG_RATE_ANALYSIS_SETTINGS.FREQUENT_ITEMS_SETS_MINIMUM_SUPPORT,
fields: getFrequentItemSetsAggFields(sortedSignificantTerms),
fields: getFrequentItemSetsAggFields(sortedSignificantItems),
},
},
};
@ -177,7 +177,7 @@ export async function fetchFrequentItemSets(
Object.entries(fis.key).forEach(([key, value]) => {
result.set[key] = value[0];
const pValue = sortedSignificantTerms.find(
const pValue = sortedSignificantItems.find(
(t) => t.fieldName === key && t.fieldValue === value[0]
)?.pValue;

View file

@ -10,7 +10,7 @@ import { uniq } from 'lodash';
import { ElasticsearchClient } from '@kbn/core/server';
import type { Logger } from '@kbn/logging';
import { criticalTableLookup, type Histogram } from '@kbn/ml-chi2test';
import { type SignificantTerm, SIGNIFICANT_TERM_TYPE } from '@kbn/ml-agg-utils';
import { type SignificantItem, SIGNIFICANT_ITEM_TYPE } from '@kbn/ml-agg-utils';
import type { Category } from '../../../../common/api/log_categorization/types';
import type { AiopsLogRateAnalysisSchema } from '../../../../common/api/log_rate_analysis/schema';
@ -83,7 +83,7 @@ export const fetchSignificantCategories = async (
if (categoriesOverall.length !== fieldNames.length) return [];
const significantCategories: SignificantTerm[] = [];
const significantCategories: SignificantItem[] = [];
// Using for...of to allow `await` within the loop.
for (const [i, fieldName] of fieldNames.entries()) {
@ -152,7 +152,7 @@ export const fetchSignificantCategories = async (
score,
pValue,
normalizedScore: getNormalizedScore(score),
type: SIGNIFICANT_TERM_TYPE.LOG_PATTERN,
type: SIGNIFICANT_ITEM_TYPE.LOG_PATTERN,
});
}
});

View file

@ -9,7 +9,7 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { ElasticsearchClient } from '@kbn/core/server';
import type { Logger } from '@kbn/logging';
import { type SignificantTerm, SIGNIFICANT_TERM_TYPE } from '@kbn/ml-agg-utils';
import { type SignificantItem, SIGNIFICANT_ITEM_TYPE } from '@kbn/ml-agg-utils';
import {
createRandomSamplerWrapper,
type RandomSamplerWrapper,
@ -111,13 +111,13 @@ export const fetchSignificantTermPValues = async (
sampleProbability: number = 1,
emitError: (m: string) => void,
abortSignal?: AbortSignal
): Promise<SignificantTerm[]> => {
): Promise<SignificantItem[]> => {
const randomSamplerWrapper = createRandomSamplerWrapper({
probability: sampleProbability,
seed: RANDOM_SAMPLER_SEED,
});
const result: SignificantTerm[] = [];
const result: SignificantItem[] = [];
const settledPromises = await Promise.allSettled(
fieldNames.map((fieldName) =>
@ -168,7 +168,7 @@ export const fetchSignificantTermPValues = async (
if (typeof pValue === 'number' && pValue < LOG_RATE_ANALYSIS_SETTINGS.P_VALUE_THRESHOLD) {
result.push({
key: `${fieldName}:${String(bucket.key)}`,
type: SIGNIFICANT_TERM_TYPE.KEYWORD,
type: SIGNIFICANT_ITEM_TYPE.KEYWORD,
fieldName,
fieldValue: String(bucket.key),
doc_count: bucket.doc_count,

View file

@ -11,7 +11,7 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server';
import type { Logger } from '@kbn/logging';
import type { FieldValuePair, SignificantTerm } from '@kbn/ml-agg-utils';
import type { FieldValuePair, SignificantItem } from '@kbn/ml-agg-utils';
import { isPopulatedObject } from '@kbn/ml-is-populated-object';
import type { AiopsLogRateAnalysisSchema } from '../../../../common/api/log_rate_analysis/schema';
@ -68,9 +68,9 @@ export async function fetchTerms2CategoriesCounts(
esClient: ElasticsearchClient,
params: AiopsLogRateAnalysisSchema,
searchQuery: estypes.QueryDslQueryContainer,
significantTerms: SignificantTerm[],
significantTerms: SignificantItem[],
itemSets: ItemSet[],
significantCategories: SignificantTerm[],
significantCategories: SignificantItem[],
from: number,
to: number,
logger: Logger,

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import { significantTermGroups } from '../../../../common/__mocks__/farequote/significant_term_groups';
import { significantItemGroups } from '../../../../common/__mocks__/farequote/significant_item_groups';
import { fields } from '../../../../common/__mocks__/artificial_logs/fields';
import { filteredFrequentItemSets } from '../../../../common/__mocks__/artificial_logs/filtered_frequent_item_sets';
import { significantTerms } from '../../../../common/__mocks__/artificial_logs/significant_terms';
@ -16,7 +16,7 @@ import { getSimpleHierarchicalTreeLeaves } from './get_simple_hierarchical_tree_
describe('getFieldValuePairCounts', () => {
it('returns a nested record with field/value pair counts for farequote', () => {
const fieldValuePairCounts = getFieldValuePairCounts(significantTermGroups);
const fieldValuePairCounts = getFieldValuePairCounts(significantItemGroups);
expect(fieldValuePairCounts).toEqual({
airline: {

View file

@ -5,14 +5,14 @@
* 2.0.
*/
import type { SignificantTermGroup } from '@kbn/ml-agg-utils';
import type { SignificantItemGroup } from '@kbn/ml-agg-utils';
import type { FieldValuePairCounts } from '../../../../common/types';
/**
* Get a nested record of field/value pairs with counts
*/
export function getFieldValuePairCounts(cpgs: SignificantTermGroup[]): FieldValuePairCounts {
export function getFieldValuePairCounts(cpgs: SignificantItemGroup[]): FieldValuePairCounts {
return cpgs.reduce<FieldValuePairCounts>((p, { group }) => {
group.forEach(({ fieldName, fieldValue }) => {
if (p[fieldName] === undefined) {

View file

@ -5,13 +5,13 @@
* 2.0.
*/
import { finalSignificantTermGroups } from '../../../../common/__mocks__/artificial_logs/final_significant_term_groups';
import { finalSignificantItemGroups } from '../../../../common/__mocks__/artificial_logs/final_significant_item_groups';
import { getGroupFilter } from './get_group_filter';
describe('getGroupFilter', () => {
it('gets a query filter for the significant terms of a group', () => {
expect(getGroupFilter(finalSignificantTermGroups[0])).toStrictEqual([
it('gets a query filter for the significant items of a group', () => {
expect(getGroupFilter(finalSignificantItemGroups[0])).toStrictEqual([
{
term: {
url: 'login.php',

View file

@ -7,21 +7,21 @@
import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { type SignificantTermGroup, SIGNIFICANT_TERM_TYPE } from '@kbn/ml-agg-utils';
import { type SignificantItemGroup, SIGNIFICANT_ITEM_TYPE } from '@kbn/ml-agg-utils';
import { getCategoryQuery } from '../../../../common/api/log_categorization/get_category_query';
// Transforms a list of significant terms from a group in a query filter.
// Transforms a list of significant items from a group in a query filter.
// Uses a `term` filter for single field value combinations.
// For fields with multiple values it creates a single `terms` filter that includes
// all values. This avoids queries not returning any results otherwise because
// separate `term` filter for multiple values for the same field would rule each other out.
export function getGroupFilter(
significantTermGroup: SignificantTermGroup
significantItemGroup: SignificantItemGroup
): estypes.QueryDslQueryContainer[] {
const groupKeywordFilter = Object.entries(
significantTermGroup.group
.filter((d) => d.type === SIGNIFICANT_TERM_TYPE.KEYWORD)
significantItemGroup.group
.filter((d) => d.type === SIGNIFICANT_ITEM_TYPE.KEYWORD)
.reduce<Record<string, Array<string | number>>>((p, c) => {
if (p[c.fieldName]) {
p[c.fieldName].push(c.fieldValue);
@ -35,8 +35,8 @@ export function getGroupFilter(
return p;
}, []);
const groupLogPatternFilter = significantTermGroup.group
.filter((d) => d.type === SIGNIFICANT_TERM_TYPE.LOG_PATTERN)
const groupLogPatternFilter = significantItemGroup.group
.filter((d) => d.type === SIGNIFICANT_ITEM_TYPE.LOG_PATTERN)
.map((d) =>
getCategoryQuery(d.fieldName, [
{

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import { significantTermGroups } from '../../../../common/__mocks__/artificial_logs/significant_term_groups';
import { significantItemGroups } from '../../../../common/__mocks__/artificial_logs/significant_item_groups';
import { significantTerms } from '../../../../common/__mocks__/artificial_logs/significant_terms';
import { duplicateIdentifier } from './duplicate_identifier';
@ -16,15 +16,15 @@ import { getMarkedDuplicates } from './get_marked_duplicates';
describe('getGroupsWithReaddedDuplicates', () => {
it('gets groups with readded duplicates', () => {
const groupedSignificantTerms = groupDuplicates(significantTerms, duplicateIdentifier).filter(
const groupedSignificantItems = groupDuplicates(significantTerms, duplicateIdentifier).filter(
(g) => g.group.length > 1
);
const fieldValuePairCounts = getFieldValuePairCounts(significantTermGroups);
const markedDuplicates = getMarkedDuplicates(significantTermGroups, fieldValuePairCounts);
const fieldValuePairCounts = getFieldValuePairCounts(significantItemGroups);
const markedDuplicates = getMarkedDuplicates(significantItemGroups, fieldValuePairCounts);
const groupsWithReaddedDuplicates = getGroupsWithReaddedDuplicates(
markedDuplicates,
groupedSignificantTerms
groupedSignificantItems
);
expect(groupsWithReaddedDuplicates).toEqual([

View file

@ -7,20 +7,20 @@
import { uniqWith, isEqual } from 'lodash';
import type { SignificantTermGroup } from '@kbn/ml-agg-utils';
import type { SignificantItemGroup } from '@kbn/ml-agg-utils';
import type { SignificantTermDuplicateGroup } from '../../../../common/types';
import type { SignificantItemDuplicateGroup } from '../../../../common/types';
export function getGroupsWithReaddedDuplicates(
groups: SignificantTermGroup[],
groupedSignificantTerms: SignificantTermDuplicateGroup[]
): SignificantTermGroup[] {
groups: SignificantItemGroup[],
groupedSignificantItems: SignificantItemDuplicateGroup[]
): SignificantItemGroup[] {
return groups.map((g) => {
const group = [...g.group];
for (const groupItem of g.group) {
const { duplicate } = groupItem;
const duplicates = groupedSignificantTerms.find((d) =>
const duplicates = groupedSignificantItems.find((d) =>
d.group.some(
(dg) => dg.fieldName === groupItem.fieldName && dg.fieldValue === groupItem.fieldValue
)

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import { significantTermGroups } from '../../../../common/__mocks__/farequote/significant_term_groups';
import { significantItemGroups } from '../../../../common/__mocks__/farequote/significant_item_groups';
import { fields } from '../../../../common/__mocks__/artificial_logs/fields';
import { filteredFrequentItemSets } from '../../../../common/__mocks__/artificial_logs/filtered_frequent_item_sets';
import { significantTerms } from '../../../../common/__mocks__/artificial_logs/significant_terms';
@ -16,9 +16,9 @@ import { getSimpleHierarchicalTree } from './get_simple_hierarchical_tree';
import { getSimpleHierarchicalTreeLeaves } from './get_simple_hierarchical_tree_leaves';
describe('markDuplicates', () => {
it('marks duplicates based on significant terms groups for farequote', () => {
const fieldValuePairCounts = getFieldValuePairCounts(significantTermGroups);
const markedDuplicates = getMarkedDuplicates(significantTermGroups, fieldValuePairCounts);
it('marks duplicates based on significant items groups for farequote', () => {
const fieldValuePairCounts = getFieldValuePairCounts(significantItemGroups);
const markedDuplicates = getMarkedDuplicates(significantItemGroups, fieldValuePairCounts);
expect(markedDuplicates).toEqual([
{
@ -74,7 +74,7 @@ describe('markDuplicates', () => {
]);
});
it('marks duplicates based on significant terms groups for artificial logs', () => {
it('marks duplicates based on significant items groups for artificial logs', () => {
const simpleHierarchicalTree = getSimpleHierarchicalTree(
filteredFrequentItemSets,
true,

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import type { SignificantTermGroup } from '@kbn/ml-agg-utils';
import type { SignificantItemGroup } from '@kbn/ml-agg-utils';
import type { FieldValuePairCounts } from '../../../../common/types';
@ -13,9 +13,9 @@ import type { FieldValuePairCounts } from '../../../../common/types';
* Analyse duplicate field/value pairs in groups.
*/
export function getMarkedDuplicates(
cpgs: SignificantTermGroup[],
cpgs: SignificantItemGroup[],
fieldValuePairCounts: FieldValuePairCounts
): SignificantTermGroup[] {
): SignificantItemGroup[] {
return cpgs.map((cpg) => {
return {
...cpg,

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import { significantTermGroups } from '../../../../common/__mocks__/artificial_logs/significant_term_groups';
import { significantItemGroups } from '../../../../common/__mocks__/artificial_logs/significant_item_groups';
import { significantTerms } from '../../../../common/__mocks__/artificial_logs/significant_terms';
import { duplicateIdentifier } from './duplicate_identifier';
@ -13,27 +13,27 @@ import { getGroupsWithReaddedDuplicates } from './get_groups_with_readded_duplic
import { groupDuplicates } from './fetch_frequent_item_sets';
import { getFieldValuePairCounts } from './get_field_value_pair_counts';
import { getMarkedDuplicates } from './get_marked_duplicates';
import { getMissingSignificantTerms } from './get_missing_significant_terms';
import { getMissingSignificantItems } from './get_missing_significant_items';
describe('getMissingSignificantTerms', () => {
it('get missing significant terms', () => {
const groupedSignificantTerms = groupDuplicates(significantTerms, duplicateIdentifier).filter(
describe('getMissingSignificantItems', () => {
it('get missing significant items', () => {
const groupedSignificantItems = groupDuplicates(significantTerms, duplicateIdentifier).filter(
(g) => g.group.length > 1
);
const fieldValuePairCounts = getFieldValuePairCounts(significantTermGroups);
const markedDuplicates = getMarkedDuplicates(significantTermGroups, fieldValuePairCounts);
const fieldValuePairCounts = getFieldValuePairCounts(significantItemGroups);
const markedDuplicates = getMarkedDuplicates(significantItemGroups, fieldValuePairCounts);
const groupsWithReaddedDuplicates = getGroupsWithReaddedDuplicates(
markedDuplicates,
groupedSignificantTerms
groupedSignificantItems
);
const missingSignificantTerms = getMissingSignificantTerms(
const missingSignificantItems = getMissingSignificantItems(
significantTerms,
groupsWithReaddedDuplicates
);
expect(missingSignificantTerms).toEqual([
expect(missingSignificantItems).toEqual([
{
key: 'user:Peter',
type: 'keyword',

View file

@ -5,14 +5,14 @@
* 2.0.
*/
import type { SignificantTerm, SignificantTermGroup } from '@kbn/ml-agg-utils';
import type { SignificantItem, SignificantItemGroup } from '@kbn/ml-agg-utils';
export function getMissingSignificantTerms(
significantTerms: SignificantTerm[],
significantTermGroups: SignificantTermGroup[]
export function getMissingSignificantItems(
significantItems: SignificantItem[],
significantItemGroups: SignificantItemGroup[]
) {
return significantTerms.filter((cp) => {
return !significantTermGroups.some((cpg) => {
return significantItems.filter((cp) => {
return !significantItemGroups.some((cpg) => {
return cpg.group.some((d) => d.fieldName === cp.fieldName && d.fieldValue === cp.fieldValue);
});
});

View file

@ -10,20 +10,20 @@ import { orderBy } from 'lodash';
import { fields } from '../../../../common/__mocks__/artificial_logs/fields';
import { frequentItemSets } from '../../../../common/__mocks__/artificial_logs/frequent_item_sets';
import { significantTerms } from '../../../../common/__mocks__/artificial_logs/significant_terms';
import { finalSignificantTermGroups } from '../../../../common/__mocks__/artificial_logs/final_significant_term_groups';
import { finalSignificantItemGroups } from '../../../../common/__mocks__/artificial_logs/final_significant_item_groups';
import { getSignificantTermGroups } from './get_significant_term_groups';
import { getSignificantItemGroups } from './get_significant_item_groups';
describe('getSignificantTermGroups', () => {
it('gets significant terms groups', () => {
const significantTermGroups = getSignificantTermGroups(
describe('getSignificantItemGroups', () => {
it('gets significant items groups', () => {
const significantItemGroups = getSignificantItemGroups(
frequentItemSets,
significantTerms,
fields
);
expect(orderBy(significantTermGroups, ['docCount'])).toEqual(
orderBy(finalSignificantTermGroups, ['docCount'])
expect(orderBy(significantItemGroups, ['docCount'])).toEqual(
orderBy(finalSignificantItemGroups, ['docCount'])
);
});
});

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import type { SignificantTerm, SignificantTermGroup } from '@kbn/ml-agg-utils';
import type { SignificantItem, SignificantItemGroup } from '@kbn/ml-agg-utils';
import { duplicateIdentifier } from './duplicate_identifier';
import { groupDuplicates } from './fetch_frequent_item_sets';
@ -13,18 +13,18 @@ import { getFieldValuePairCounts } from './get_field_value_pair_counts';
import { getMarkedDuplicates } from './get_marked_duplicates';
import { getSimpleHierarchicalTree } from './get_simple_hierarchical_tree';
import { getSimpleHierarchicalTreeLeaves } from './get_simple_hierarchical_tree_leaves';
import { getMissingSignificantTerms } from './get_missing_significant_terms';
import { transformSignificantTermToGroup } from './transform_significant_term_to_group';
import { getMissingSignificantItems } from './get_missing_significant_items';
import { transformSignificantItemToGroup } from './transform_significant_item_to_group';
import type { ItemSet } from '../../../../common/types';
export function getSignificantTermGroups(
export function getSignificantItemGroups(
itemsets: ItemSet[],
significantTerms: SignificantTerm[],
significantItems: SignificantItem[],
fields: string[]
): SignificantTermGroup[] {
// We use the grouped significant terms to later repopulate
): SignificantItemGroup[] {
// We use the grouped significant items to later repopulate
// the `frequent_item_sets` result with the missing duplicates.
const groupedSignificantTerms = groupDuplicates(significantTerms, duplicateIdentifier).filter(
const groupedSignificantItems = groupDuplicates(significantItems, duplicateIdentifier).filter(
(g) => g.group.length > 1
);
@ -33,7 +33,7 @@ export function getSignificantTermGroups(
// and then summarize them in larger groups where possible.
// Get a tree structure based on `frequent_item_sets`.
const { root } = getSimpleHierarchicalTree(itemsets, false, false, significantTerms, fields);
const { root } = getSimpleHierarchicalTree(itemsets, false, false, significantItems, fields);
// Each leave of the tree will be a summarized group of co-occuring field/value pairs.
const treeLeaves = getSimpleHierarchicalTreeLeaves(root, []);
@ -42,21 +42,21 @@ export function getSignificantTermGroups(
// that occur in multiple groups. This will allow us to highlight field/value pairs that are
// unique to a group in a better way.
const fieldValuePairCounts = getFieldValuePairCounts(treeLeaves);
const significantTermGroups = getMarkedDuplicates(treeLeaves, fieldValuePairCounts);
const significantItemGroups = getMarkedDuplicates(treeLeaves, fieldValuePairCounts);
// Some field/value pairs might not be part of the `frequent_item_sets` result set, for example
// because they don't co-occur with other field/value pairs or because of the limits we set on the query.
// In this next part we identify those missing pairs and add them as individual groups.
const missingSignificantTerms = getMissingSignificantTerms(
significantTerms,
significantTermGroups
const missingSignificantItems = getMissingSignificantItems(
significantItems,
significantItemGroups
);
significantTermGroups.push(
...missingSignificantTerms.map((significantTerm) =>
transformSignificantTermToGroup(significantTerm, groupedSignificantTerms)
significantItemGroups.push(
...missingSignificantItems.map((significantItem) =>
transformSignificantItemToGroup(significantItem, groupedSignificantItems)
)
);
return significantTermGroups;
return significantItemGroups;
}

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import type { SignificantTerm } from '@kbn/ml-agg-utils';
import type { SignificantItem } from '@kbn/ml-agg-utils';
import type { ItemSet, SimpleHierarchicalTreeNode } from '../../../../common/types';
@ -34,7 +34,7 @@ function NewNodeFactory(name: string): SimpleHierarchicalTreeNode {
* The resulting tree components are non-overlapping subsets of the data.
* In summary, we start with the most inclusive itemset (highest count), and perform a depth first search in field order.
*
* @param significantTerms
* @param significantItems
* @param fields
* @param displayParent
* @param parentDocCount
@ -47,7 +47,7 @@ function NewNodeFactory(name: string): SimpleHierarchicalTreeNode {
* @returns
*/
function dfDepthFirstSearch(
significantTerms: SignificantTerm[],
significantItems: SignificantItem[],
fields: string[],
displayParent: SimpleHierarchicalTreeNode,
parentDocCount: number,
@ -79,10 +79,10 @@ function dfDepthFirstSearch(
let displayNode: SimpleHierarchicalTreeNode;
const significantTerm = significantTerms.find(
const significantItem = significantItems.find(
(d) => d.fieldName === field && d.fieldValue === value
);
if (!significantTerm) {
if (!significantItem) {
return 0;
}
@ -91,8 +91,8 @@ function dfDepthFirstSearch(
displayParent.name += ` ${value}`;
displayParent.set.push({
key: significantTerm.key,
type: significantTerm.type,
key: significantItem.key,
type: significantItem.type,
fieldName: field,
fieldValue: value,
docCount,
@ -105,8 +105,8 @@ function dfDepthFirstSearch(
displayNode = NewNodeFactory(`${docCount}/${totalDocCount}${label}`);
displayNode.set = [...displayParent.set];
displayNode.set.push({
key: significantTerm.key,
type: significantTerm.type,
key: significantItem.key,
type: significantItem.type,
fieldName: field,
fieldValue: value,
docCount,
@ -148,7 +148,7 @@ function dfDepthFirstSearch(
let subCount = 0;
for (const nextValue of getValuesDescending(filteredItemSets, nextField)) {
subCount += dfDepthFirstSearch(
significantTerms,
significantItems,
fields,
displayNode,
docCount,
@ -181,7 +181,7 @@ export function getSimpleHierarchicalTree(
itemSets: ItemSet[],
collapseRedundant: boolean,
displayOther: boolean,
significantTerms: SignificantTerm[],
significantItems: SignificantItem[],
fields: string[] = []
) {
const totalDocCount = Math.max(...itemSets.map((d) => d.total_doc_count));
@ -191,7 +191,7 @@ export function getSimpleHierarchicalTree(
for (const field of fields) {
for (const value of getValuesDescending(itemSets, field)) {
dfDepthFirstSearch(
significantTerms,
significantItems,
fields,
newRoot,
totalDocCount + 1,

View file

@ -6,7 +6,7 @@
*/
import { orderBy } from 'lodash';
import type { SignificantTermGroup } from '@kbn/ml-agg-utils';
import type { SignificantItemGroup } from '@kbn/ml-agg-utils';
import { stringHash } from '@kbn/ml-string-hash';
import type { SimpleHierarchicalTreeNode } from '../../../../common/types';
@ -16,7 +16,7 @@ import type { SimpleHierarchicalTreeNode } from '../../../../common/types';
*/
export function getSimpleHierarchicalTreeLeaves(
tree: SimpleHierarchicalTreeNode,
leaves: SignificantTermGroup[],
leaves: SignificantItemGroup[],
level = 1
) {
if (tree.children.length === 0) {
@ -43,7 +43,7 @@ export function getSimpleHierarchicalTreeLeaves(
const sortedLeaves = orderBy(leaves, [(d) => d.group.length], ['desc']);
// Checks if a group is a subset of items already present in a larger group.
const filteredLeaves = sortedLeaves.reduce<SignificantTermGroup[]>((p, c) => {
const filteredLeaves = sortedLeaves.reduce<SignificantItemGroup[]>((p, c) => {
const isSubset = p.some((pG) =>
c.group.every((cGI) =>
pG.group.some((pGI) => pGI.fieldName === cGI.fieldName && pGI.fieldValue === cGI.fieldValue)

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import { significantTermGroups } from '../../../../common/__mocks__/artificial_logs/significant_term_groups';
import { significantItemGroups } from '../../../../common/__mocks__/artificial_logs/significant_item_groups';
import { significantTerms } from '../../../../common/__mocks__/artificial_logs/significant_terms';
import { duplicateIdentifier } from './duplicate_identifier';
@ -13,30 +13,30 @@ import { getGroupsWithReaddedDuplicates } from './get_groups_with_readded_duplic
import { groupDuplicates } from './fetch_frequent_item_sets';
import { getFieldValuePairCounts } from './get_field_value_pair_counts';
import { getMarkedDuplicates } from './get_marked_duplicates';
import { getMissingSignificantTerms } from './get_missing_significant_terms';
import { transformSignificantTermToGroup } from './transform_significant_term_to_group';
import { getMissingSignificantItems } from './get_missing_significant_items';
import { transformSignificantItemToGroup } from './transform_significant_item_to_group';
describe('getMissingSignificantTerms', () => {
it('get missing significant terms', () => {
const groupedSignificantTerms = groupDuplicates(significantTerms, duplicateIdentifier).filter(
describe('getMissingSignificantItems', () => {
it('get missing significant items', () => {
const groupedSignificantItems = groupDuplicates(significantTerms, duplicateIdentifier).filter(
(g) => g.group.length > 1
);
const fieldValuePairCounts = getFieldValuePairCounts(significantTermGroups);
const markedDuplicates = getMarkedDuplicates(significantTermGroups, fieldValuePairCounts);
const fieldValuePairCounts = getFieldValuePairCounts(significantItemGroups);
const markedDuplicates = getMarkedDuplicates(significantItemGroups, fieldValuePairCounts);
const groupsWithReaddedDuplicates = getGroupsWithReaddedDuplicates(
markedDuplicates,
groupedSignificantTerms
groupedSignificantItems
);
const missingSignificantTerms = getMissingSignificantTerms(
const missingSignificantItems = getMissingSignificantItems(
significantTerms,
groupsWithReaddedDuplicates
);
const transformed = transformSignificantTermToGroup(
missingSignificantTerms[0],
groupedSignificantTerms
const transformed = transformSignificantItemToGroup(
missingSignificantItems[0],
groupedSignificantItems
);
expect(transformed).toEqual({

View file

@ -6,17 +6,17 @@
*/
import { stringHash } from '@kbn/ml-string-hash';
import type { SignificantTerm, SignificantTermGroup } from '@kbn/ml-agg-utils';
import type { SignificantItem, SignificantItemGroup } from '@kbn/ml-agg-utils';
import type { SignificantTermDuplicateGroup } from '../../../../common/types';
import type { SignificantItemDuplicateGroup } from '../../../../common/types';
export function transformSignificantTermToGroup(
significantTerm: SignificantTerm,
groupedSignificantTerms: SignificantTermDuplicateGroup[]
): SignificantTermGroup {
const { key, type, fieldName, fieldValue, doc_count: docCount, pValue } = significantTerm;
export function transformSignificantItemToGroup(
significantItem: SignificantItem,
groupedSignificantItems: SignificantItemDuplicateGroup[]
): SignificantItemGroup {
const { key, type, fieldName, fieldValue, doc_count: docCount, pValue } = significantItem;
const duplicates = groupedSignificantTerms.find((d) =>
const duplicates = groupedSignificantItems.find((d) =>
d.group.some((dg) => dg.fieldName === fieldName && dg.fieldValue === fieldValue)
);

View file

@ -21,23 +21,23 @@ import { i18n } from '@kbn/i18n';
import { KBN_FIELD_TYPES } from '@kbn/field-types';
import { streamFactory } from '@kbn/ml-response-stream/server';
import type {
SignificantTerm,
SignificantTermGroup,
SignificantTermHistogramItem,
SignificantItem,
SignificantItemGroup,
SignificantItemHistogramItem,
NumericChartData,
NumericHistogramField,
} from '@kbn/ml-agg-utils';
import { SIGNIFICANT_TERM_TYPE } from '@kbn/ml-agg-utils';
import { SIGNIFICANT_ITEM_TYPE } from '@kbn/ml-agg-utils';
import { fetchHistogramsForFields } from '@kbn/ml-agg-utils';
import { createExecutionContext } from '@kbn/ml-route-utils';
import type { UsageCounter } from '@kbn/usage-collection-plugin/server';
import { RANDOM_SAMPLER_SEED, AIOPS_TELEMETRY_ID } from '../../../common/constants';
import {
addSignificantTermsAction,
addSignificantTermsGroupAction,
addSignificantTermsGroupHistogramAction,
addSignificantTermsHistogramAction,
addSignificantItemsAction,
addSignificantItemsGroupAction,
addSignificantItemsGroupHistogramAction,
addSignificantItemsHistogramAction,
addErrorAction,
pingAction,
resetAllAction,
@ -65,7 +65,7 @@ import { fetchFrequentItemSets } from './queries/fetch_frequent_item_sets';
import { fetchTerms2CategoriesCounts } from './queries/fetch_terms_2_categories_counts';
import { getHistogramQuery } from './queries/get_histogram_query';
import { getGroupFilter } from './queries/get_group_filter';
import { getSignificantTermGroups } from './queries/get_significant_term_groups';
import { getSignificantItemGroups } from './queries/get_significant_item_groups';
import { trackAIOpsRouteUsage } from '../../lib/track_route_usage';
// 10s ping frequency to keep the stream alive.
@ -287,19 +287,19 @@ export function routeHandlerFactory<T extends ApiVersion>(
}
}
// Step 2: Significant Categories and Terms
// Step 2: Significant Categories and Items
// This will store the combined count of detected significant log patterns and keywords
let fieldValuePairsCount = 0;
const significantCategories: SignificantTerm[] = [];
const significantCategories: SignificantItem[] = [];
if (version === '1') {
significantCategories.push(
...((
request.body as AiopsLogRateAnalysisSchema<'1'>
).overrides?.significantTerms?.filter(
(d) => d.type === SIGNIFICANT_TERM_TYPE.LOG_PATTERN
(d) => d.type === SIGNIFICANT_ITEM_TYPE.LOG_PATTERN
) ?? [])
);
}
@ -309,7 +309,7 @@ export function routeHandlerFactory<T extends ApiVersion>(
...((
request.body as AiopsLogRateAnalysisSchema<'2'>
).overrides?.significantItems?.filter(
(d) => d.type === SIGNIFICANT_TERM_TYPE.LOG_PATTERN
(d) => d.type === SIGNIFICANT_ITEM_TYPE.LOG_PATTERN
) ?? [])
);
}
@ -329,18 +329,18 @@ export function routeHandlerFactory<T extends ApiVersion>(
);
if (significantCategories.length > 0) {
push(addSignificantTermsAction(significantCategories, version));
push(addSignificantItemsAction(significantCategories, version));
}
}
const significantTerms: SignificantTerm[] = [];
const significantTerms: SignificantItem[] = [];
if (version === '1') {
significantTerms.push(
...((
request.body as AiopsLogRateAnalysisSchema<'1'>
).overrides?.significantTerms?.filter(
(d) => d.type === SIGNIFICANT_TERM_TYPE.KEYWORD
(d) => d.type === SIGNIFICANT_ITEM_TYPE.KEYWORD
) ?? [])
);
}
@ -350,7 +350,7 @@ export function routeHandlerFactory<T extends ApiVersion>(
...((
request.body as AiopsLogRateAnalysisSchema<'2'>
).overrides?.significantItems?.filter(
(d) => d.type === SIGNIFICANT_TERM_TYPE.KEYWORD
(d) => d.type === SIGNIFICANT_ITEM_TYPE.KEYWORD
) ?? [])
);
}
@ -411,7 +411,7 @@ export function routeHandlerFactory<T extends ApiVersion>(
});
significantTerms.push(...pValues);
push(addSignificantTermsAction(pValues, version));
push(addSignificantItemsAction(pValues, version));
}
push(
@ -571,7 +571,7 @@ export function routeHandlerFactory<T extends ApiVersion>(
}
if (fields.length > 0 && itemSets.length > 0) {
const significantTermGroups = getSignificantTermGroups(
const significantItemGroups = getSignificantItemGroups(
itemSets,
[...significantTerms, ...significantCategories],
fields
@ -579,10 +579,10 @@ export function routeHandlerFactory<T extends ApiVersion>(
// We'll find out if there's at least one group with at least two items,
// only then will we return the groups to the clients and make the grouping option available.
const maxItems = Math.max(...significantTermGroups.map((g) => g.group.length));
const maxItems = Math.max(...significantItemGroups.map((g) => g.group.length));
if (maxItems > 1) {
push(addSignificantTermsGroupAction(significantTermGroups, version));
push(addSignificantItemsGroupAction(significantItemGroups, version));
}
loaded += PROGRESS_STEP_GROUPING;
@ -595,9 +595,9 @@ export function routeHandlerFactory<T extends ApiVersion>(
return;
}
logDebugMessage(`Fetch ${significantTermGroups.length} group histograms.`);
logDebugMessage(`Fetch ${significantItemGroups.length} group histograms.`);
const groupHistogramQueue = queue(async function (cpg: SignificantTermGroup) {
const groupHistogramQueue = queue(async function (cpg: SignificantItemGroup) {
if (shouldStop) {
logDebugMessage('shouldStop abort fetching group histograms.');
groupHistogramQueue.kill();
@ -644,7 +644,7 @@ export function routeHandlerFactory<T extends ApiVersion>(
}
return;
}
const histogram: SignificantTermHistogramItem[] =
const histogram: SignificantItemHistogramItem[] =
overallTimeSeries.data.map((o) => {
const current = cpgTimeSeries.data.find(
(d1) => d1.key_as_string === o.key_as_string
@ -670,7 +670,7 @@ export function routeHandlerFactory<T extends ApiVersion>(
}) ?? [];
push(
addSignificantTermsGroupHistogramAction(
addSignificantItemsGroupHistogramAction(
[
{
id: cpg.id,
@ -683,7 +683,7 @@ export function routeHandlerFactory<T extends ApiVersion>(
}
}, MAX_CONCURRENT_QUERIES);
groupHistogramQueue.push(significantTermGroups);
groupHistogramQueue.push(significantItemGroups);
await groupHistogramQueue.drain();
}
} catch (e) {
@ -706,7 +706,7 @@ export function routeHandlerFactory<T extends ApiVersion>(
overallTimeSeries !== undefined &&
!request.body.overrides?.regroupOnly
) {
const fieldValueHistogramQueue = queue(async function (cp: SignificantTerm) {
const fieldValueHistogramQueue = queue(async function (cp: SignificantItem) {
if (shouldStop) {
logDebugMessage('shouldStop abort fetching field/value histograms.');
fieldValueHistogramQueue.kill();
@ -759,7 +759,7 @@ export function routeHandlerFactory<T extends ApiVersion>(
return;
}
const histogram: SignificantTermHistogramItem[] =
const histogram: SignificantItemHistogramItem[] =
overallTimeSeries.data.map((o) => {
const current = cpTimeSeries.data.find(
(d1) => d1.key_as_string === o.key_as_string
@ -788,7 +788,7 @@ export function routeHandlerFactory<T extends ApiVersion>(
loaded += (1 / fieldValuePairsCount) * PROGRESS_STEP_HISTOGRAMS;
pushHistogramDataLoadingState();
push(
addSignificantTermsHistogramAction(
addSignificantItemsHistogramAction(
[
{
fieldName,
@ -863,7 +863,7 @@ export function routeHandlerFactory<T extends ApiVersion>(
return;
}
const histogram: SignificantTermHistogramItem[] =
const histogram: SignificantItemHistogramItem[] =
overallTimeSeries.data.map((o) => {
const current = catTimeSeries.data.find(
(d1) => d1.key_as_string === o.key_as_string
@ -893,7 +893,7 @@ export function routeHandlerFactory<T extends ApiVersion>(
loaded += (1 / fieldValuePairsCount) * PROGRESS_STEP_HISTOGRAMS;
pushHistogramDataLoadingState();
push(
addSignificantTermsHistogramAction(
addSignificantItemsHistogramAction(
[
{
fieldName,

View file

@ -10,7 +10,7 @@ import { stringHash } from '@kbn/ml-string-hash';
import { extractErrorProperties } from '@kbn/ml-error-utils';
import { Query } from '@kbn/es-query';
import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { SignificantTerm } from '@kbn/ml-agg-utils';
import { SignificantItem } from '@kbn/ml-agg-utils';
import {
createRandomSamplerWrapper,
RandomSampler,
@ -50,8 +50,8 @@ export interface DocumentStatsSearchStrategyParams {
timeFieldName?: string;
runtimeFieldMap?: estypes.MappingRuntimeFields;
fieldsToFetch?: string[];
selectedSignificantTerm?: SignificantTerm;
includeSelectedSignificantTerm?: boolean;
selectedSignificantItem?: SignificantItem;
includeSelectedSignificantItem?: boolean;
trackTotalHits?: boolean;
}
@ -167,8 +167,8 @@ export interface DocumentStatsSearchStrategyParams {
timeFieldName?: string;
runtimeFieldMap?: estypes.MappingRuntimeFields;
fieldsToFetch?: string[];
selectedSignificantTerm?: SignificantTerm;
includeSelectedSignificantTerm?: boolean;
selectedSignificantItem?: SignificantItem;
includeSelectedSignificantItem?: boolean;
trackTotalHits?: boolean;
}

View file

@ -162,7 +162,7 @@ export const LogRateAnalysis: FC<AlertDetailsLogRateAnalysisSectionProps> = ({ r
const onAnalysisCompleted = (analysisResults: LogRateAnalysisResultsData | undefined) => {
const significantFieldValues = orderBy(
analysisResults?.significantTerms?.map((item) => ({
analysisResults?.significantItems?.map((item) => ({
field: item.fieldName,
value: item.fieldValue,
docCount: item.doc_count,

View file

@ -7956,7 +7956,7 @@
"xpack.aiops.logRateAnalysis.resultsTable.impactLabelColumnTooltip": "Le niveau d'impact du champ sur la différence de taux de messages.",
"xpack.aiops.logRateAnalysis.resultsTable.linksMenu.copyToClipboardButtonLabel": "Copier dans le presse-papiers",
"xpack.aiops.logRateAnalysis.resultsTable.linksMenu.copyToClipboardGroupMessage": "Copier les éléments de groupe en tant que syntaxe KQL dans le Presse-papiers",
"xpack.aiops.logRateAnalysis.resultsTable.linksMenu.copyToClipboardSignificantTermMessage": "Copier la paire clé-valeur en tant que syntaxe KQL dans le Presse-papiers",
"xpack.aiops.logRateAnalysis.resultsTable.linksMenu.copyToClipboardSignificantItemMessage": "Copier la paire clé-valeur en tant que syntaxe KQL dans le Presse-papiers",
"xpack.aiops.logRateAnalysis.resultsTable.linksMenu.viewInDiscover": "Afficher dans Discover",
"xpack.aiops.logRateAnalysis.resultsTable.linksMenu.viewInLogPatternAnalysis": "Voir dans l'analyse du modèle de log",
"xpack.aiops.logRateAnalysis.resultsTable.logPatternLinkNotAvailableTooltipMessage": "Le lien n'est pas disponible si l'élément du tableau est lui-même un modèle de log.",

View file

@ -7971,7 +7971,7 @@
"xpack.aiops.logRateAnalysis.resultsTable.impactLabelColumnTooltip": "メッセージレート差異に対するフィールドの影響のレベル。",
"xpack.aiops.logRateAnalysis.resultsTable.linksMenu.copyToClipboardButtonLabel": "クリップボードにコピー",
"xpack.aiops.logRateAnalysis.resultsTable.linksMenu.copyToClipboardGroupMessage": "グループアイテムをKQL構文としてクリップボードにコピー",
"xpack.aiops.logRateAnalysis.resultsTable.linksMenu.copyToClipboardSignificantTermMessage": "フィールド/値のペアをKQL構文としてクリップボードにコピー",
"xpack.aiops.logRateAnalysis.resultsTable.linksMenu.copyToClipboardSignificantItemMessage": "フィールド/値のペアをKQL構文としてクリップボードにコピー",
"xpack.aiops.logRateAnalysis.resultsTable.linksMenu.viewInDiscover": "Discoverに表示",
"xpack.aiops.logRateAnalysis.resultsTable.linksMenu.viewInLogPatternAnalysis": "ログパターン分析で表示",
"xpack.aiops.logRateAnalysis.resultsTable.logPatternLinkNotAvailableTooltipMessage": "テーブル項目がログパターン自体の場合は、このリンクは使用できません。",

View file

@ -7970,7 +7970,7 @@
"xpack.aiops.logRateAnalysis.resultsTable.impactLabelColumnTooltip": "字段对消息速率差异的影响水平。",
"xpack.aiops.logRateAnalysis.resultsTable.linksMenu.copyToClipboardButtonLabel": "复制到剪贴板",
"xpack.aiops.logRateAnalysis.resultsTable.linksMenu.copyToClipboardGroupMessage": "将组项目作为 KQL 语法复制到剪贴板",
"xpack.aiops.logRateAnalysis.resultsTable.linksMenu.copyToClipboardSignificantTermMessage": "将字段/值对作为 KQL 语法复制到剪贴板",
"xpack.aiops.logRateAnalysis.resultsTable.linksMenu.copyToClipboardSignificantItemMessage": "将字段/值对作为 KQL 语法复制到剪贴板",
"xpack.aiops.logRateAnalysis.resultsTable.linksMenu.viewInDiscover": "在 Discover 中查看",
"xpack.aiops.logRateAnalysis.resultsTable.linksMenu.viewInLogPatternAnalysis": "在日志模式分析中查看",
"xpack.aiops.logRateAnalysis.resultsTable.logPatternLinkNotAvailableTooltipMessage": "如果表项目为日志模式本身,则此链接不可用。",

View file

@ -70,8 +70,8 @@ export default ({ getService }: FtrProviderContext) => {
);
expect(significantItems).to.eql(
testData.expected.significantTerms,
'Significant terms do not match expected values.'
testData.expected.significantItems,
'Significant items do not match expected values.'
);
const histogramActions = getHistogramActions(data, apiVersion);

View file

@ -41,7 +41,7 @@ export default ({ getService }: FtrProviderContext) => {
overrides = {
loaded: 0,
remainingFieldCandidates: [],
significantTerms: testData.expected.significantTerms,
significantTerms: testData.expected.significantItems,
regroupOnly: true,
} as AiopsLogRateAnalysisSchema<typeof apiVersion>['overrides'];
}
@ -51,7 +51,7 @@ export default ({ getService }: FtrProviderContext) => {
loaded: 0,
remainingFieldCandidates: [],
significantItems: testData.expected
.significantTerms as AiopsLogRateAnalysisSchemaSignificantItem[],
.significantItems as AiopsLogRateAnalysisSchemaSignificantItem[],
regroupOnly: true,
} as AiopsLogRateAnalysisSchema<typeof apiVersion>['overrides'];
}

View file

@ -10,8 +10,8 @@
// that also the jest unit tests use mocks that are not outdated.
import { significantTerms as artificialLogSignificantTerms } from '@kbn/aiops-plugin/common/__mocks__/artificial_logs/significant_terms';
import { significantLogPatterns as artificialLogSignificantLogPatterns } from '@kbn/aiops-plugin/common/__mocks__/artificial_logs/significant_log_patterns';
import { finalSignificantTermGroups as artificialLogsSignificantTermGroups } from '@kbn/aiops-plugin/common/__mocks__/artificial_logs/final_significant_term_groups';
import { finalSignificantTermGroupsTextfield as artificialLogsSignificantTermGroupsTextfield } from '@kbn/aiops-plugin/common/__mocks__/artificial_logs/final_significant_term_groups_textfield';
import { finalSignificantItemGroups as artificialLogsSignificantItemGroups } from '@kbn/aiops-plugin/common/__mocks__/artificial_logs/final_significant_item_groups';
import { finalSignificantItemGroupsTextfield as artificialLogsSignificantItemGroupsTextfield } from '@kbn/aiops-plugin/common/__mocks__/artificial_logs/final_significant_item_groups_textfield';
import type {
AiopsLogRateAnalysisSchema,
@ -45,7 +45,7 @@ export const getLogRateAnalysisTestData = <T extends ApiVersion>(): Array<TestDa
actionsLengthGroupOnly: 4,
noIndexChunksLength: 4,
noIndexActionsLength: 3,
significantTerms: [
significantItems: [
{
key: 'day_of_week:Thursday',
type: 'keyword',
@ -99,8 +99,8 @@ export const getLogRateAnalysisTestData = <T extends ApiVersion>(): Array<TestDa
actionsLengthGroupOnly: 10,
noIndexChunksLength: 4,
noIndexActionsLength: 3,
significantTerms: artificialLogSignificantTerms,
groups: artificialLogsSignificantTermGroups,
significantItems: artificialLogSignificantTerms,
groups: artificialLogsSignificantItemGroups,
histogramLength: 20,
},
},
@ -126,8 +126,8 @@ export const getLogRateAnalysisTestData = <T extends ApiVersion>(): Array<TestDa
actionsLengthGroupOnly: 10,
noIndexChunksLength: 4,
noIndexActionsLength: 3,
significantTerms: [...artificialLogSignificantTerms, ...artificialLogSignificantLogPatterns],
groups: artificialLogsSignificantTermGroupsTextfield,
significantItems: [...artificialLogSignificantTerms, ...artificialLogSignificantLogPatterns],
groups: artificialLogsSignificantItemGroupsTextfield,
histogramLength: 20,
},
},
@ -153,8 +153,8 @@ export const getLogRateAnalysisTestData = <T extends ApiVersion>(): Array<TestDa
actionsLengthGroupOnly: 10,
noIndexChunksLength: 4,
noIndexActionsLength: 3,
significantTerms: artificialLogSignificantTerms,
groups: artificialLogsSignificantTermGroups,
significantItems: artificialLogSignificantTerms,
groups: artificialLogsSignificantItemGroups,
histogramLength: 20,
},
},
@ -180,8 +180,8 @@ export const getLogRateAnalysisTestData = <T extends ApiVersion>(): Array<TestDa
actionsLengthGroupOnly: 10,
noIndexChunksLength: 4,
noIndexActionsLength: 3,
significantTerms: [...artificialLogSignificantTerms, ...artificialLogSignificantLogPatterns],
groups: artificialLogsSignificantTermGroupsTextfield,
significantItems: [...artificialLogSignificantTerms, ...artificialLogSignificantLogPatterns],
groups: artificialLogsSignificantItemGroupsTextfield,
histogramLength: 20,
},
},

View file

@ -9,7 +9,7 @@ import type {
AiopsLogRateAnalysisSchema,
AiopsLogRateAnalysisApiVersion as ApiVersion,
} from '@kbn/aiops-plugin/common/api/log_rate_analysis/schema';
import type { SignificantTerm, SignificantTermGroup } from '@kbn/ml-agg-utils';
import type { SignificantItem, SignificantItemGroup } from '@kbn/ml-agg-utils';
import type { LogRateAnalysisDataGenerator } from '../../../functional/services/aiops/log_rate_analysis_data_generator';
@ -25,8 +25,8 @@ export interface TestData<T extends ApiVersion> {
actionsLengthGroupOnly: number;
noIndexChunksLength: number;
noIndexActionsLength: number;
significantTerms: SignificantTerm[];
groups: SignificantTermGroup[];
significantItems: SignificantItem[];
groups: SignificantItemGroup[];
histogramLength: number;
};
}