grafana/public/app/features/explore/LogsVolumePanel.tsx

115 lines
3.2 KiB
TypeScript
Raw Normal View History

Loki: Full range logs volume (#39327) * Basic implementation of getLogsVolumeQuery method * Add todos * Add a switcher to automatically load logs volume * De-scope dismissing logs volume panel * De-scope logs volume query cancellation * Remove todo * Aggregate logs volume components in single panel * Show logs volume only when it's available * Aggregate logs volume by level * Simplify aggregation * Handle no logs volume data * Add error handling * Do not show auto-load logs volume switcher when loading logs volume is not available * Remove old logs volume graph * Clean up * Make getting data provider more generic * Provide complete logs volume data (error, isLoading) * Display more specific error message * Add missing props to mocks * Remove setRequest method * Mark getQueryRelatedDataProviders as internal * Add missing dataQueryRequest and add a todo * Remove redundant loading state * Do not mutate existing queries * Apply fix for zooming-in from main * Post-merge fixes * Create collection for data provider results * Use more generic names * Move aggregation logic to Loki logs volume provider * Move LogsVolume to common types * Update tests * Post-merge fixes * Fix mapping related data values * Simplify prop mappings * Add docs * Fix property name * Clean-up * Mark new types as internal * Reduce number of providers to logs volume only * Simplify data structure to DataQueryResponse * Move Logs Volume panel to a separate component * Test logsVolumeProvider.ts * Add observable version of datasource mock * Test getLogsVolumeDataProvider method * Test LogsVolumePanel * Test logs volume reducer * Clean up * Clean up * Fix test * Use sum by to use level field directly * Fix strict type errors * Fix strict type errors * Use "logs" instead of "unknown" if only one level was detected * Add docs about logs volume * Rename histogramRequest to logsVolumeRequest * Use LogsVolumeContentWrapper all content types * Move `autoLoadLogsVolume` local storage handling * Fix strict error * Move getting autoLoadLogsVolume to initial state * Cancel current logs volume subscription * Test cancelling subscriptions * Update docs/sources/datasources/loki.md Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> * Update packages/grafana-data/src/types/explore.ts Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> * Inline container styles * Ensure logs volume is aggregated per each subscription separately * Simplify logs volume provider * Type-guard support for logs volume provider * Simplify event handlers to avoid casting * Clean up and docs * Move auto-load switcher to logs volume panel * Fix test * Move DataSourceWithLogsVolumeSupport to avoid cross referencing * Simplify interface * Bring back old histogram and hide the new one behind a feature flag * Add missing props to logs histogram panel * Clean up the provider when it's not supported * Simplify storing autoLoadLogsVolume * Remove docs * Update packages/grafana-data/src/types/logsVolume.ts Co-authored-by: Andrej Ocenas <mr.ocenas@gmail.com> * Skip dataframes without fields (instant queries) * Revert styles changes * Revert styles changes * Add release tag Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> Co-authored-by: Andrej Ocenas <mr.ocenas@gmail.com>
2021-09-30 08:46:11 -05:00
import { AbsoluteTimeRange, DataQueryResponse, LoadingState, SplitOpen, TimeZone } from '@grafana/data';
import { Button, Collapse, InlineField, InlineFieldRow, InlineSwitch, useTheme2 } from '@grafana/ui';
import { ExploreGraph } from './ExploreGraph';
import React, { useCallback } from 'react';
import { ExploreId } from '../../types';
import { css } from '@emotion/css';
type Props = {
exploreId: ExploreId;
loadLogsVolumeData: (exploreId: ExploreId) => void;
logsVolumeData?: DataQueryResponse;
absoluteRange: AbsoluteTimeRange;
timeZone: TimeZone;
splitOpen: SplitOpen;
width: number;
onUpdateTimeRange: (timeRange: AbsoluteTimeRange) => void;
autoLoadLogsVolume: boolean;
onChangeAutoLogsVolume: (value: boolean) => void;
};
export function LogsVolumePanel(props: Props) {
const {
width,
logsVolumeData,
exploreId,
loadLogsVolumeData,
absoluteRange,
timeZone,
splitOpen,
onUpdateTimeRange,
autoLoadLogsVolume,
onChangeAutoLogsVolume,
} = props;
const theme = useTheme2();
const spacing = parseInt(theme.spacing(2).slice(0, -2), 10);
const height = 150;
let LogsVolumePanelContent;
if (!logsVolumeData) {
LogsVolumePanelContent = (
<Button
onClick={() => {
loadLogsVolumeData(exploreId);
}}
>
Load logs volume
</Button>
);
} else if (logsVolumeData?.error) {
LogsVolumePanelContent = (
<span>
Failed to load volume logs for this query:{' '}
{logsVolumeData.error.data?.message || logsVolumeData.error.statusText}
</span>
);
} else if (logsVolumeData?.state === LoadingState.Loading) {
LogsVolumePanelContent = <span>Logs volume is loading...</span>;
} else if (logsVolumeData?.data) {
if (logsVolumeData.data.length > 0) {
LogsVolumePanelContent = (
<ExploreGraph
loadingState={LoadingState.Done}
data={logsVolumeData.data}
height={height}
width={width - spacing}
absoluteRange={absoluteRange}
onChangeTime={onUpdateTimeRange}
timeZone={timeZone}
splitOpenFn={splitOpen}
/>
);
} else {
LogsVolumePanelContent = <span>No volume data.</span>;
}
}
const handleOnChangeAutoLogsVolume = useCallback(
(event: React.ChangeEvent<HTMLInputElement>) => {
const { target } = event;
if (target) {
onChangeAutoLogsVolume(target.checked);
}
},
[onChangeAutoLogsVolume]
);
return (
<Collapse label="Logs volume" isOpen={true} loading={logsVolumeData?.state === LoadingState.Loading}>
<div
style={{ height }}
className={css({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
})}
>
{LogsVolumePanelContent}
</div>
<div
className={css({
display: 'flex',
justifyContent: 'end',
})}
>
<InlineFieldRow>
<InlineField label="Auto-load logs volume" transparent>
<InlineSwitch value={autoLoadLogsVolume} onChange={handleOnChangeAutoLogsVolume} transparent />
</InlineField>
</InlineFieldRow>
</div>
</Collapse>
);
}