Skip to content

Commit

Permalink
feat: serve aggregated metrics from Loki
Browse files Browse the repository at this point in the history
  • Loading branch information
trevorwhitney committed Jul 29, 2024
1 parent e490065 commit b9e7af5
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 29 deletions.
135 changes: 114 additions & 21 deletions src/Components/ServiceScene/LogsVolumePanel.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,37 @@
import React from 'react';

import { PanelBuilders, SceneComponentProps, SceneObjectBase, SceneObjectState, VizPanel } from '@grafana/scenes';
import {
AdHocFiltersVariable,
CustomVariable,
PanelBuilders,
SceneComponentProps,
sceneGraph,
SceneObjectBase,
SceneObjectState,
VizPanel,
} from '@grafana/scenes';
import { DrawStyle, LegendDisplayMode, PanelContext, SeriesVisibilityChangeMode, StackingMode } from '@grafana/ui';
import { getQueryRunner, setLevelSeriesOverrides, setLeverColorOverrides } from 'services/panel';
import { buildLokiQuery } from 'services/query';
import { getAdHocFiltersVariable, getLabelsVariable, LEVEL_VARIABLE_VALUE, VAR_LEVELS } from 'services/variables';
import {
LEVEL_VARIABLE_VALUE,
LOG_STREAM_SELECTOR_EXPR,
VAR_FIELDS,
VAR_LEVELS,
VAR_LABELS,
VAR_LINE_FILTER,
VAR_PATTERNS,
getAdHocFiltersVariable,
// getLabelsVariable,
} from 'services/variables';
import { SERVICE_NAME } from '../ServiceSelectionScene/ServiceSelectionScene';
import { addToFilters, replaceFilter } from './Breakdowns/AddToFiltersButton';
import { reportAppInteraction, USER_EVENTS_ACTIONS, USER_EVENTS_PAGES } from 'services/analytics';
import { getTimeSeriesExpr } from '../../services/expressions';
import { SERVICE_NAME } from '../ServiceSelectionScene/ServiceSelectionScene';
// import { getTimeSeriesExpr } from '../../services/expressions';

export interface LogsVolumePanelState extends SceneObjectState {
panel?: VizPanel;
filter?: AdHocFiltersVariable;
}

export class LogsVolumePanel extends SceneObjectBase<LogsVolumePanelState> {
Expand All @@ -28,31 +48,73 @@ export class LogsVolumePanel extends SceneObjectBase<LogsVolumePanelState> {
});
}

const labels = getLabelsVariable(this);
const fields = sceneGraph.lookupVariable(VAR_FIELDS, this) as AdHocFiltersVariable;
const patterns = sceneGraph.lookupVariable(VAR_PATTERNS, this) as CustomVariable;
const lineFilter = sceneGraph.lookupVariable(VAR_LINE_FILTER, this) as CustomVariable;
const labels = sceneGraph.lookupVariable(VAR_LABELS, this) as AdHocFiltersVariable;

labels.subscribeToState((newState, prevState) => {
const newService = newState.filters.find((f) => f.key === SERVICE_NAME);
const prevService = prevState.filters.find((f) => f.key === SERVICE_NAME);
if (newService !== prevService) {
this.setState({
panel: this.getVizPanel(),
});
}
});
this._subs.add(
fields.subscribeToState((newState, prevState) => {
if (newState.filters.length !== prevState.filters.length) {
this.updateVolumePanel();
}
})
);
this._subs.add(
labels.subscribeToState((newState, prevState) => {
if (newState.filters.length !== prevState.filters.length) {
this.updateVolumePanel();
}

const newService = newState.filters.find((f) => f.key === SERVICE_NAME);
const prevService = prevState.filters.find((f) => f.key === SERVICE_NAME);
if (newService !== prevService) {
this.setState({
panel: this.getVizPanel(),
});
}
})
);
this._subs.add(
patterns.subscribeToState((newState, prevState) => {
if (newState.value !== prevState.value) {
this.updateVolumePanel();
}
})
);
this._subs.add(
lineFilter.subscribeToState((newState, prevState) => {
if (newState.value !== prevState.value) {
this.updateVolumePanel();
}
})
);
}

public updateVolumePanel = () => {
this.setState({
panel: this.getVizPanel(),
});
};

private getVizPanel() {
const service = this.service();
const queryString = this.hasSingleServiceSelector()
? `sum by (${LEVEL_VARIABLE_VALUE}) (sum_over_time({__aggregated_metric__=\`${service}\`} | logfmt | unwrap count [$__auto]))`
: `sum by (${LEVEL_VARIABLE_VALUE}) (count_over_time(${LOG_STREAM_SELECTOR_EXPR} | drop __error__ [$__auto]))`;

const viz = PanelBuilders.timeseries()
.setTitle('Log volume')
.setOption('legend', { showLegend: true, calcs: ['sum'], displayMode: LegendDisplayMode.List })
.setUnit('short')
.setData(
getQueryRunner(
buildLokiQuery(getTimeSeriesExpr(this, LEVEL_VARIABLE_VALUE, false), {
legendFormat: `{{${LEVEL_VARIABLE_VALUE}}}`,
})
)
)
// .setData(
// getQueryRunner(
// buildLokiQuery(getTimeSeriesExpr(this, LEVEL_VARIABLE_VALUE, false), {
// legendFormat: `{{${LEVEL_VARIABLE_VALUE}}}`,
// })
// )
// )
.setData(getQueryRunner(buildLokiQuery(queryString, { legendFormat: `{{${LEVEL_VARIABLE_VALUE}}}` })))
.setCustomFieldConfig('stacking', { mode: StackingMode.Normal })
.setCustomFieldConfig('fillOpacity', 100)
.setCustomFieldConfig('lineWidth', 0)
Expand All @@ -74,6 +136,37 @@ export class LogsVolumePanel extends SceneObjectBase<LogsVolumePanelState> {
return panel;
}

private hasSingleServiceSelector(): boolean {
const fields = sceneGraph.lookupVariable(VAR_FIELDS, this) as AdHocFiltersVariable;
const patterns = sceneGraph.lookupVariable(VAR_PATTERNS, this) as CustomVariable;
const lineFilter = sceneGraph.lookupVariable(VAR_LINE_FILTER, this) as CustomVariable;

if (fields.state.filters.length !== 0 || patterns.state.value !== '') {
return false;
}

const labels = sceneGraph.lookupVariable(VAR_LABELS, this) as AdHocFiltersVariable;
if (labels.state.filters.length > 1) {
return false;
}

const filter = (lineFilter.state.value as string).trim();
if (labels.state.filters[0].key === SERVICE_NAME) {
if (filter === '|~ `(?i)`' || !filter) {
return true;
}
}

return false;
}

private service(): string {
const labels = sceneGraph.lookupVariable(VAR_LABELS, this) as AdHocFiltersVariable;
const filters = labels?.state.filters ?? [];

return filters.find((filter) => filter.key === SERVICE_NAME)?.value ?? '';
}

private extendTimeSeriesLegendBus = (context: PanelContext) => {
const originalOnToggleSeriesVisibility = context.onToggleSeriesVisibility;

Expand Down
20 changes: 12 additions & 8 deletions src/Components/ServiceSelectionScene/ServiceSelectionScene.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ interface ServiceSelectionSceneState extends SceneObjectState {
serviceLevel: Map<string, string[]>;
}

function getMetricExpression(service: string) {
return `sum by (${LEVEL_VARIABLE_VALUE}) (count_over_time({${SERVICE_NAME}=\`${service}\`} | drop __error__ [$__auto]))`;
}
// function getMetricExpression(service: string) {
// return `sum by (${LEVEL_VARIABLE_VALUE}) (count_over_time({${SERVICE_NAME}=\`${service}\`} | drop __error__ [$__auto]))`;
// }

function getLogExpression(service: string, levelFilter: string) {
return `{${SERVICE_NAME}=\`${service}\`}${levelFilter}`;
Expand Down Expand Up @@ -288,11 +288,15 @@ export class ServiceSelectionScene extends SceneObjectBase<ServiceSelectionScene
.setTitle(service)
.setData(
getQueryRunner(
buildLokiQuery(getMetricExpression(service), {
legendFormat: `{{${LEVEL_VARIABLE_VALUE}}}`,
splitDuration,
refId: `ts-${service}`,
})
// buildLokiQuery(getMetricExpression(service), {
// legendFormat: `{{${LEVEL_VARIABLE_VALUE}}}`,
// splitDuration,
// refId: `ts-${service}`,
// })
buildLokiQuery(
`sum by (${LEVEL_VARIABLE_VALUE}) (sum_over_time({__aggregated_metric__=\`${service}\`} | logfmt | unwrap count [$__auto]))`,
{ legendFormat: `{{${LEVEL_VARIABLE_VALUE}}}`, splitDuration, refId: `ts-${service}` }
)
)
)
.setCustomFieldConfig('stacking', { mode: StackingMode.Normal })
Expand Down

0 comments on commit b9e7af5

Please sign in to comment.