diff --git a/src/LogContext/LogContextProvider.ts b/src/LogContext/LogContextProvider.ts
index 6919e29..5401550 100644
--- a/src/LogContext/LogContextProvider.ts
+++ b/src/LogContext/LogContextProvider.ts
@@ -13,7 +13,7 @@ import {
rangeUtil,
} from '@grafana/data';
-import { ElasticsearchQuery, Logs} from '../types';
+import { ElasticsearchQuery, Logs, LogsSortDirection} from '../types';
import { LogContextUI } from './components/LogContextUI';
@@ -64,7 +64,7 @@ export class LogContextProvider {
settings: {
limit: options?.limit ? options?.limit.toString() : '10',
// Sorting of results in the context query
- sortDirection: direction === LogRowContextQueryDirection.Backward ? 'desc' : 'asc',
+ sortDirection: direction === LogRowContextQueryDirection.Backward ? LogsSortDirection.DESC : LogsSortDirection.ASC,
// Used to get the next log lines before/after the current log line using sort field of selected log line
searchAfter: searchAfter,
},
diff --git a/src/components/QueryEditor/MetricAggregationsEditor/SettingsEditor/LogsSettingsEditor.tsx b/src/components/QueryEditor/MetricAggregationsEditor/SettingsEditor/LogsSettingsEditor.tsx
new file mode 100644
index 0000000..09055a5
--- /dev/null
+++ b/src/components/QueryEditor/MetricAggregationsEditor/SettingsEditor/LogsSettingsEditor.tsx
@@ -0,0 +1,31 @@
+import { css } from "@emotion/css";
+import { RadioButtonGroup } from "@grafana/ui";
+import React from "react";
+import { Logs, LogsSortDirection, LogsEnd } from "types";
+import { SettingField } from "./SettingField";
+import { useDispatch } from "hooks/useStatelessReducer";
+import { changeMetricSetting } from '../state/actions';
+import { metricAggregationConfig } from "../utils";
+
+
+// type LogsSortDirection = 'asc' | 'desc'
+
+interface Props { metric: Logs }
+
+export const LogsSettingsEditor = ({metric}: Props)=>{
+ const config = metricAggregationConfig['logs']
+ const dispatch = useDispatch();
+ return (
+
+ ({label:LogsEnd[v], value:v}))}
+ value={metric.settings?.sortDirection || config.defaults.settings?.sortDirection }
+ onChange={(v)=>{ dispatch(
+ changeMetricSetting({ metric, settingName: 'sortDirection', newValue: v })
+ )}}/>
+
+
+ )
+
+}
diff --git a/src/components/QueryEditor/MetricAggregationsEditor/SettingsEditor/index.tsx b/src/components/QueryEditor/MetricAggregationsEditor/SettingsEditor/index.tsx
index 3d56d04..9b5b8c4 100644
--- a/src/components/QueryEditor/MetricAggregationsEditor/SettingsEditor/index.tsx
+++ b/src/components/QueryEditor/MetricAggregationsEditor/SettingsEditor/index.tsx
@@ -16,9 +16,10 @@ import { MovingAverageSettingsEditor } from './MovingAverageSettingsEditor';
import { SettingField } from './SettingField';
import { TopMetricsSettingsEditor } from './TopMetricsSettingsEditor';
import { useDescription } from './useDescription';
+import { LogsSettingsEditor } from './LogsSettingsEditor';
// TODO: Move this somewhere and share it with BucketsAggregation Editor
-const inlineFieldProps: Partial> = {
+export const inlineFieldProps: Partial> = {
labelWidth: 16,
};
@@ -84,7 +85,9 @@ export const SettingsEditor = ({ metric, previousMetrics }: Props) => {
)}
- {metric.type === 'logs' && }
+ {metric.type === 'logs' && (
+
+ )}
{metric.type === 'cardinality' && (
diff --git a/src/components/QueryEditor/MetricAggregationsEditor/SettingsEditor/useDescription.ts b/src/components/QueryEditor/MetricAggregationsEditor/SettingsEditor/useDescription.ts
index b143c59..6cf1e16 100644
--- a/src/components/QueryEditor/MetricAggregationsEditor/SettingsEditor/useDescription.ts
+++ b/src/components/QueryEditor/MetricAggregationsEditor/SettingsEditor/useDescription.ts
@@ -1,5 +1,6 @@
import { extendedStats } from 'queryDef';
-import { MetricAggregation } from '@/types';
+import { Logs, LogsEnd, MetricAggregation } from '@/types';
+import { metricAggregationConfig } from '../utils';
const hasValue = (value: string) => (object: { value: string }) => object.value === value;
@@ -34,6 +35,14 @@ export const useDescription = (metric: MetricAggregation): string => {
return `Size: ${size}`;
}
+ case 'logs': {
+ const config = metricAggregationConfig['logs']
+ const logsmetric: Logs = metric
+ const sort = LogsEnd[logsmetric.settings?.sortDirection || config.defaults.settings!.sortDirection!]
+ const limit = logsmetric.settings?.limit || 100
+ return `${sort} ${limit}`
+ }
+
default:
return 'Options';
}
diff --git a/src/components/QueryEditor/MetricAggregationsEditor/index.tsx b/src/components/QueryEditor/MetricAggregationsEditor/index.tsx
index 3296612..2c877b5 100644
--- a/src/components/QueryEditor/MetricAggregationsEditor/index.tsx
+++ b/src/components/QueryEditor/MetricAggregationsEditor/index.tsx
@@ -3,13 +3,13 @@ import React from 'react';
import { useDispatch } from '@/hooks/useStatelessReducer';
import { IconButton } from '../../IconButton';
import { useQuery } from '../ElasticsearchQueryContext';
-import { QueryEditorRow } from '../QueryEditorRow';
+import { QueryEditorRow, QueryEditorBaseRow } from '../QueryEditorRow';
import { MetricAggregation } from '@/types';
import { MetricEditor } from './MetricEditor';
import { addMetric, removeMetric, toggleMetricVisibility } from './state/actions';
import { metricAggregationConfig } from './utils';
-import { QueryEditorSpecialMetricRow } from '../QueryEditorSpecialMetricRow';
+import { SettingsEditor } from './SettingsEditor';
interface Props {
nextId: MetricAggregation['id'];
@@ -25,9 +25,13 @@ export const MetricAggregationsEditor = ({ nextId }: Props) => {
{metrics?.map((metric, index) => {
switch (metric.type) {
case 'logs':
- return ;
+ return
+
+ ;
case 'raw_data':
- return ;
+ return
+
+ ;
default:
return (
{
+ return {
+ iconWrapper: css`
+ display: flex;
+ `,
+ icon: css`
+ color: ${theme.colors.text.secondary};
+ margin-left: ${theme.spacing(0.25)};
+ `,
+ };
+};
+
+interface BaseRowProps { label: ReactNode; };
+export const QueryEditorBaseRow = ({ label, children }: PropsWithChildren) => {
+ return (
+
+
+
+ {label}
+
+
+ {children}
+
+ );
+};
+
+interface RowProps extends BaseRowProps {
onRemoveClick?: false | (() => void);
onHideClick?: false | (() => void);
hidden?: boolean;
}
-
export const QueryEditorRow = ({
children,
label,
onRemoveClick,
onHideClick,
hidden = false,
-}: PropsWithChildren) => {
+}: PropsWithChildren) => {
const styles = useStyles2(getStyles);
return (
-
-
-
- {label}
-
- {onHideClick && (
-
- )}
+
+ {label}
+
+ {onHideClick && (
-
-
-
+ )}
+
+
+ >)}>
{children}
-
+
);
};
-const getStyles = (theme: GrafanaTheme2) => {
- return {
- iconWrapper: css`
- display: flex;
- `,
- icon: css`
- color: ${theme.colors.text.secondary};
- margin-left: ${theme.spacing(0.25)};
- `,
- };
-};
+
diff --git a/src/components/QueryEditor/QueryEditorSpecialMetricRow.tsx b/src/components/QueryEditor/QueryEditorSpecialMetricRow.tsx
deleted file mode 100644
index ab34c00..0000000
--- a/src/components/QueryEditor/QueryEditorSpecialMetricRow.tsx
+++ /dev/null
@@ -1,30 +0,0 @@
-import React from 'react';
-
-import { InlineFieldRow, InlineLabel, InlineSegmentGroup } from '@grafana/ui';
-
-import { MetricAggregation } from '@/types';
-
-import { SettingsEditor } from './MetricAggregationsEditor/SettingsEditor';
-
-type Props = {
- name: string;
- metric: MetricAggregation;
-};
-
-export const QueryEditorSpecialMetricRow = ({ name, metric }: Props) => {
- // this widget is only used in scenarios when there is only a single
- // metric, so the array of "previousMetrics" (meaning all the metrics
- // before the current metric), is an ampty-array
- const previousMetrics: MetricAggregation[] = [];
-
- return (
-
-
-
- {name}
-
-
-
-
- );
-};
diff --git a/src/queryDef.ts b/src/queryDef.ts
index 66e5160..780253a 100644
--- a/src/queryDef.ts
+++ b/src/queryDef.ts
@@ -32,7 +32,7 @@ export function defaultMetricAgg(id = '1'): MetricAggregation {
}
export function defaultLogsAgg(id = '1'): MetricAggregation {
- return { type: 'logs', id };
+ return { type: 'logs', id, ...metricAggregationConfig['logs'].defaults };
}
export function defaultBucketAgg(id = '1'): DateHistogram {
diff --git a/src/types.ts b/src/types.ts
index 1dba31c..ed57465 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -15,14 +15,24 @@ import {
} from './dataquery.gen';
export * from './dataquery.gen';
-export { Elasticsearch as ElasticsearchQuery } from './dataquery.gen';
+export { type Elasticsearch as ElasticsearchQuery } from './dataquery.gen';
// We want to extend the settings of the Logs query with additional properties that
// are not part of the schema. This is a workaround, because exporting LogsSettings
// from dataquery.gen.ts and extending that produces error in SettingKeyOf.
+export enum LogsSortDirection {
+ DESC = 'desc',
+ ASC = 'asc',
+}
+
+export const LogsEnd = {
+ [LogsSortDirection.ASC]: 'Head',
+ [LogsSortDirection.DESC]: 'Tail'
+}
+
type ExtendedLogsSettings = SchemaLogs['settings'] & {
searchAfter?: unknown[];
- sortDirection?: 'asc' | 'desc';
+ sortDirection?: LogsSortDirection;
};
export interface Logs extends SchemaLogs {
@@ -65,7 +75,7 @@ interface MetricConfiguration {
impliedQueryType: QueryType;
hasSettings: boolean;
hasMeta: boolean;
- defaults: Omit, 'id' | 'type'>;
+ defaults: Omit|Logs, { type: T }>, 'id' | 'type'>;
}
type BucketConfiguration = {