grafana/public/app/features/explore/LogsContainer.tsx
Andrej Ocenas ae09ccbf79
Trace UI demo (#20297)
* Add integration with Jeager
Add Jaeger datasource and modify derived fields in loki to allow for opening a trace in Jager in separate split.
Modifies build so that this branch docker images are pushed to docker hub
Add a traceui dir with docker-compose and provision files for demoing.:wq

* Enable docker logger plugin to send logs to loki

* Add placeholder zipkin datasource

* Fixed rebase issues, added enhanceDataFrame to non-legacy code path

* Trace selector for jaeger query field

* Fix logs default mode for Loki

* Fix loading jaeger query field services on split

* Updated grafana image in traceui/compose file

* Fix prettier error

* Hide behind feature flag, clean up unused code.

* Fix tests

* Fix tests

* Cleanup code and review feedback

* Remove traceui directory

* Remove circle build changes

* Fix feature toggles object

* Fix merge issues

* Fix some null errors

* Fix test after strict null changes

* Review feedback fixes

* Fix toggle name

Co-authored-by: David Kaltschmidt <david.kaltschmidt@gmail.com>
2020-03-25 12:25:39 +01:00

232 lines
6.8 KiB
TypeScript

import React, { PureComponent } from 'react';
import { hot } from 'react-hot-loader';
import { connect } from 'react-redux';
import { Collapse } from '@grafana/ui';
import {
DataSourceApi,
RawTimeRange,
LogLevel,
TimeZone,
AbsoluteTimeRange,
LogRowModel,
LogsDedupStrategy,
TimeRange,
LogsMetaItem,
GraphSeriesXY,
Field,
} from '@grafana/data';
import { ExploreId, ExploreItemState } from 'app/types/explore';
import { StoreState } from 'app/types';
import { changeDedupStrategy, updateTimeRange, splitOpen } from './state/actions';
import { toggleLogLevelAction } from 'app/features/explore/state/actionTypes';
import { deduplicatedRowsSelector } from 'app/features/explore/state/selectors';
import { getTimeZone } from '../profile/state/selectors';
import { LiveLogsWithTheme } from './LiveLogs';
import { Logs } from './Logs';
import { LogsCrossFadeTransition } from './utils/LogsCrossFadeTransition';
import { LiveTailControls } from './useLiveTailControls';
import { getLinksFromLogsField } from '../panel/panellinks/linkSuppliers';
interface LogsContainerProps {
datasourceInstance?: DataSourceApi;
exploreId: ExploreId;
loading: boolean;
logsHighlighterExpressions?: string[];
logRows?: LogRowModel[];
logsMeta?: LogsMetaItem[];
logsSeries?: GraphSeriesXY[];
dedupedRows?: LogRowModel[];
onClickFilterLabel?: (key: string, value: string) => void;
onClickFilterOutLabel?: (key: string, value: string) => void;
onStartScanning: () => void;
onStopScanning: () => void;
timeZone: TimeZone;
scanning?: boolean;
scanRange?: RawTimeRange;
toggleLogLevelAction: typeof toggleLogLevelAction;
changeDedupStrategy: typeof changeDedupStrategy;
dedupStrategy: LogsDedupStrategy;
width: number;
isLive: boolean;
updateTimeRange: typeof updateTimeRange;
range: TimeRange;
syncedTimes: boolean;
absoluteRange: AbsoluteTimeRange;
isPaused: boolean;
splitOpen: typeof splitOpen;
}
export class LogsContainer extends PureComponent<LogsContainerProps> {
onChangeTime = (absoluteRange: AbsoluteTimeRange) => {
const { exploreId, updateTimeRange } = this.props;
updateTimeRange({ exploreId, absoluteRange });
};
handleDedupStrategyChange = (dedupStrategy: LogsDedupStrategy) => {
this.props.changeDedupStrategy(this.props.exploreId, dedupStrategy);
};
handleToggleLogLevel = (hiddenLogLevels: LogLevel[]) => {
const { exploreId } = this.props;
this.props.toggleLogLevelAction({
exploreId,
hiddenLogLevels,
});
};
getLogRowContext = async (row: LogRowModel, options?: any): Promise<any> => {
const { datasourceInstance } = this.props;
if (datasourceInstance?.getLogRowContext) {
return datasourceInstance.getLogRowContext(row, options);
}
return [];
};
/**
* Get links from the filed of a dataframe that was given to as and in addition check if there is associated
* metadata with datasource in which case we will add onClick to open the link in new split window. This assumes
* that we just supply datasource name and field value and Explore split window will know how to render that
* appropriately. This is for example used for transition from log with traceId to trace datasource to show that
* trace.
* @param field
* @param rowIndex
*/
getFieldLinks = (field: Field, rowIndex: number) => {
const data = getLinksFromLogsField(field, rowIndex);
return data.map(d => {
if (d.link.meta?.datasourceName) {
return {
...d.linkModel,
onClick: () => {
this.props.splitOpen(d.link.meta.datasourceName, field.values.get(rowIndex));
},
};
}
return d.linkModel;
});
};
render() {
const {
loading,
logsHighlighterExpressions,
logRows,
logsMeta,
logsSeries,
dedupedRows,
onClickFilterLabel,
onClickFilterOutLabel,
onStartScanning,
onStopScanning,
absoluteRange,
timeZone,
scanning,
range,
width,
isLive,
exploreId,
} = this.props;
return (
<>
<LogsCrossFadeTransition visible={isLive}>
<Collapse label="Logs" loading={false} isOpen>
<LiveTailControls exploreId={exploreId}>
{controls => (
<LiveLogsWithTheme
logRows={logRows}
timeZone={timeZone}
stopLive={controls.stop}
isPaused={this.props.isPaused}
onPause={controls.pause}
onResume={controls.resume}
/>
)}
</LiveTailControls>
</Collapse>
</LogsCrossFadeTransition>
<LogsCrossFadeTransition visible={!isLive}>
<Collapse label="Logs" loading={loading} isOpen>
<Logs
dedupStrategy={this.props.dedupStrategy || LogsDedupStrategy.none}
logRows={logRows}
logsMeta={logsMeta}
logsSeries={logsSeries}
dedupedRows={dedupedRows}
highlighterExpressions={logsHighlighterExpressions}
loading={loading}
onChangeTime={this.onChangeTime}
onClickFilterLabel={onClickFilterLabel}
onClickFilterOutLabel={onClickFilterOutLabel}
onStartScanning={onStartScanning}
onStopScanning={onStopScanning}
onDedupStrategyChange={this.handleDedupStrategyChange}
onToggleLogLevel={this.handleToggleLogLevel}
absoluteRange={absoluteRange}
timeZone={timeZone}
scanning={scanning}
scanRange={range.raw}
width={width}
getRowContext={this.getLogRowContext}
getFieldLinks={this.getFieldLinks}
/>
</Collapse>
</LogsCrossFadeTransition>
</>
);
}
}
function mapStateToProps(state: StoreState, { exploreId }: { exploreId: string }) {
const explore = state.explore;
// @ts-ignore
const item: ExploreItemState = explore[exploreId];
const {
logsHighlighterExpressions,
logsResult,
loading,
scanning,
datasourceInstance,
isLive,
isPaused,
range,
absoluteRange,
dedupStrategy,
} = item;
const dedupedRows = deduplicatedRowsSelector(item);
const timeZone = getTimeZone(state.user);
return {
loading,
logsHighlighterExpressions,
logRows: logsResult && logsResult.rows,
logsMeta: logsResult && logsResult.meta,
logsSeries: logsResult && logsResult.series,
scanning,
timeZone,
dedupStrategy,
dedupedRows,
datasourceInstance,
isLive,
isPaused,
range,
absoluteRange,
};
}
const mapDispatchToProps = {
changeDedupStrategy,
toggleLogLevelAction,
updateTimeRange,
splitOpen,
};
export default hot(module)(connect(mapStateToProps, mapDispatchToProps)(LogsContainer));