1import { Labels } from './data';
2import { DataFrame } from './dataFrame';
3import { DataQuery } from './query';
4import { AbsoluteTimeRange } from './time';
5import { DataQueryResponse } from './datasource';
6
7/**
8 * Mapping of log level abbreviation to canonical log level.
9 * Supported levels are reduce to limit color variation.
10 */
11export enum LogLevel {
12  emerg = 'critical',
13  fatal = 'critical',
14  alert = 'critical',
15  crit = 'critical',
16  critical = 'critical',
17  warn = 'warning',
18  warning = 'warning',
19  err = 'error',
20  eror = 'error',
21  error = 'error',
22  info = 'info',
23  information = 'info',
24  informational = 'info',
25  notice = 'info',
26  dbug = 'debug',
27  debug = 'debug',
28  trace = 'trace',
29  unknown = 'unknown',
30}
31
32// Used for meta information such as common labels or returned log rows in logs view in Explore
33export enum LogsMetaKind {
34  Number,
35  String,
36  LabelsMap,
37  Error,
38}
39
40export enum LogsSortOrder {
41  Descending = 'Descending',
42  Ascending = 'Ascending',
43}
44
45export interface LogsMetaItem {
46  label: string;
47  value: string | number | Labels;
48  kind: LogsMetaKind;
49}
50
51export interface LogRowModel {
52  // Index of the field from which the entry has been created so that we do not show it later in log row details.
53  entryFieldIndex: number;
54
55  // Index of the row in the dataframe. As log rows can be stitched from multiple dataFrames, this does not have to be
56  // the same as rows final index when rendered.
57  rowIndex: number;
58
59  // Full DataFrame from which we parsed this log.
60  // TODO: refactor this so we do not need to pass whole dataframes in addition to also parsed data.
61  dataFrame: DataFrame;
62  duplicates?: number;
63
64  // Actual log line
65  entry: string;
66  hasAnsi: boolean;
67  hasUnescapedContent: boolean;
68  labels: Labels;
69  logLevel: LogLevel;
70  raw: string;
71  searchWords?: string[];
72  timeFromNow: string;
73  timeEpochMs: number;
74  // timeEpochNs stores time with nanosecond-level precision,
75  // as millisecond-level precision is usually not enough for proper sorting of logs
76  timeEpochNs: string;
77  timeLocal: string;
78  timeUtc: string;
79  uid: string;
80  uniqueLabels?: Labels;
81}
82
83export interface LogsModel {
84  hasUniqueLabels: boolean;
85  meta?: LogsMetaItem[];
86  rows: LogRowModel[];
87  series?: DataFrame[];
88  visibleRange?: AbsoluteTimeRange;
89  queries?: DataQuery[];
90}
91
92export interface LogSearchMatch {
93  start: number;
94  length: number;
95  text: string;
96}
97
98export interface LogLabelStatsModel {
99  active?: boolean;
100  count: number;
101  proportion: number;
102  value: string;
103}
104
105export enum LogsDedupStrategy {
106  none = 'none',
107  exact = 'exact',
108  numbers = 'numbers',
109  signature = 'signature',
110}
111
112export interface LogsParser {
113  /**
114   * Value-agnostic matcher for a field label.
115   * Used to filter rows, and first capture group contains the value.
116   */
117  buildMatcher: (label: string) => RegExp;
118
119  /**
120   * Returns all parsable substrings from a line, used for highlighting
121   */
122  getFields: (line: string) => string[];
123
124  /**
125   * Gets the label name from a parsable substring of a line
126   */
127  getLabelFromField: (field: string) => string;
128
129  /**
130   * Gets the label value from a parsable substring of a line
131   */
132  getValueFromField: (field: string) => string;
133  /**
134   * Function to verify if this is a valid parser for the given line.
135   * The parser accepts the line if it returns true.
136   */
137  test: (line: string) => boolean;
138}
139
140export enum LogsDedupDescription {
141  none = 'No de-duplication',
142  exact = 'De-duplication of successive lines that are identical, ignoring ISO datetimes.',
143  numbers = 'De-duplication of successive lines that are identical when ignoring numbers, e.g., IP addresses, latencies.',
144  signature = 'De-duplication of successive lines that have identical punctuation and whitespace.',
145}
146
147/**
148 * @alpha
149 */
150export interface DataSourceWithLogsContextSupport {
151  /**
152   * Retrieve context for a given log row
153   */
154  getLogRowContext: <TContextQueryOptions extends {}>(
155    row: LogRowModel,
156    options?: TContextQueryOptions
157  ) => Promise<DataQueryResponse>;
158
159  showContextToggle(row?: LogRowModel): boolean;
160}
161
162/**
163 * @alpha
164 */
165export const hasLogsContextSupport = (datasource: any): datasource is DataSourceWithLogsContextSupport => {
166  if (!datasource) {
167    return false;
168  }
169
170  const withLogsSupport = datasource as DataSourceWithLogsContextSupport;
171
172  return withLogsSupport.getLogRowContext !== undefined && withLogsSupport.showContextToggle !== undefined;
173};
174