LogsContainer.tsx 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. import React, { PureComponent } from 'react';
  2. import { hot } from 'react-hot-loader';
  3. import { connect } from 'react-redux';
  4. import {
  5. RawTimeRange,
  6. TimeRange,
  7. LogLevel,
  8. TimeZone,
  9. AbsoluteTimeRange,
  10. toUtc,
  11. dateTime,
  12. DataSourceApi,
  13. LogsModel,
  14. LogRowModel,
  15. LogsDedupStrategy,
  16. LoadingState,
  17. } from '@grafana/ui';
  18. import { ExploreId, ExploreItemState } from 'app/types/explore';
  19. import { StoreState } from 'app/types';
  20. import { changeDedupStrategy, changeTime } from './state/actions';
  21. import Logs from './Logs';
  22. import Panel from './Panel';
  23. import { toggleLogLevelAction, changeRefreshIntervalAction } from 'app/features/explore/state/actionTypes';
  24. import { deduplicatedLogsSelector, exploreItemUIStateSelector } from 'app/features/explore/state/selectors';
  25. import { getTimeZone } from '../profile/state/selectors';
  26. import { LiveLogsWithTheme } from './LiveLogs';
  27. import { offOption } from '@grafana/ui/src/components/RefreshPicker/RefreshPicker';
  28. interface LogsContainerProps {
  29. datasourceInstance: DataSourceApi | null;
  30. exploreId: ExploreId;
  31. loading: boolean;
  32. logsHighlighterExpressions?: string[];
  33. logsResult?: LogsModel;
  34. dedupedResult?: LogsModel;
  35. onClickLabel: (key: string, value: string) => void;
  36. onStartScanning: () => void;
  37. onStopScanning: () => void;
  38. range: TimeRange;
  39. timeZone: TimeZone;
  40. scanning?: boolean;
  41. scanRange?: RawTimeRange;
  42. toggleLogLevelAction: typeof toggleLogLevelAction;
  43. changeDedupStrategy: typeof changeDedupStrategy;
  44. dedupStrategy: LogsDedupStrategy;
  45. hiddenLogLevels: Set<LogLevel>;
  46. width: number;
  47. changeTime: typeof changeTime;
  48. isLive: boolean;
  49. stopLive: typeof changeRefreshIntervalAction;
  50. }
  51. export class LogsContainer extends PureComponent<LogsContainerProps> {
  52. onChangeTime = (absRange: AbsoluteTimeRange) => {
  53. const { exploreId, timeZone, changeTime } = this.props;
  54. const range = {
  55. from: timeZone === 'utc' ? toUtc(absRange.from) : dateTime(absRange.from),
  56. to: timeZone === 'utc' ? toUtc(absRange.to) : dateTime(absRange.to),
  57. };
  58. changeTime(exploreId, range);
  59. };
  60. onStopLive = () => {
  61. const { exploreId } = this.props;
  62. this.props.stopLive({ exploreId, refreshInterval: offOption.value });
  63. };
  64. handleDedupStrategyChange = (dedupStrategy: LogsDedupStrategy) => {
  65. this.props.changeDedupStrategy(this.props.exploreId, dedupStrategy);
  66. };
  67. hangleToggleLogLevel = (hiddenLogLevels: Set<LogLevel>) => {
  68. const { exploreId } = this.props;
  69. this.props.toggleLogLevelAction({
  70. exploreId,
  71. hiddenLogLevels,
  72. });
  73. };
  74. getLogRowContext = async (row: LogRowModel, options?: any) => {
  75. const { datasourceInstance } = this.props;
  76. if (datasourceInstance) {
  77. return datasourceInstance.getLogRowContext(row, options);
  78. }
  79. return [];
  80. };
  81. // Limit re-rendering to when a query is finished executing or when the deduplication strategy changes
  82. // for performance reasons.
  83. shouldComponentUpdate(nextProps: LogsContainerProps): boolean {
  84. return (
  85. nextProps.loading !== this.props.loading ||
  86. nextProps.dedupStrategy !== this.props.dedupStrategy ||
  87. nextProps.logsHighlighterExpressions !== this.props.logsHighlighterExpressions
  88. );
  89. }
  90. render() {
  91. const {
  92. exploreId,
  93. loading,
  94. logsHighlighterExpressions,
  95. logsResult,
  96. dedupedResult,
  97. onClickLabel,
  98. onStartScanning,
  99. onStopScanning,
  100. range,
  101. timeZone,
  102. scanning,
  103. scanRange,
  104. width,
  105. hiddenLogLevels,
  106. isLive,
  107. } = this.props;
  108. if (isLive) {
  109. return (
  110. <Panel label="Logs" loading={false} isOpen>
  111. <LiveLogsWithTheme logsResult={logsResult} stopLive={this.onStopLive} />
  112. </Panel>
  113. );
  114. }
  115. return (
  116. <Panel label="Logs" loading={loading} isOpen>
  117. <Logs
  118. dedupStrategy={this.props.dedupStrategy || LogsDedupStrategy.none}
  119. data={logsResult}
  120. dedupedData={dedupedResult}
  121. exploreId={exploreId}
  122. highlighterExpressions={logsHighlighterExpressions}
  123. loading={loading}
  124. onChangeTime={this.onChangeTime}
  125. onClickLabel={onClickLabel}
  126. onStartScanning={onStartScanning}
  127. onStopScanning={onStopScanning}
  128. onDedupStrategyChange={this.handleDedupStrategyChange}
  129. onToggleLogLevel={this.hangleToggleLogLevel}
  130. range={range}
  131. timeZone={timeZone}
  132. scanning={scanning}
  133. scanRange={scanRange}
  134. width={width}
  135. hiddenLogLevels={hiddenLogLevels}
  136. getRowContext={this.getLogRowContext}
  137. />
  138. </Panel>
  139. );
  140. }
  141. }
  142. function mapStateToProps(state: StoreState, { exploreId }) {
  143. const explore = state.explore;
  144. const item: ExploreItemState = explore[exploreId];
  145. const {
  146. logsHighlighterExpressions,
  147. logsResult,
  148. loadingState,
  149. scanning,
  150. scanRange,
  151. range,
  152. datasourceInstance,
  153. isLive,
  154. } = item;
  155. const loading = loadingState === LoadingState.Loading || loadingState === LoadingState.Streaming;
  156. const { dedupStrategy } = exploreItemUIStateSelector(item);
  157. const hiddenLogLevels = new Set(item.hiddenLogLevels);
  158. const dedupedResult = deduplicatedLogsSelector(item);
  159. const timeZone = getTimeZone(state.user);
  160. return {
  161. loading,
  162. logsHighlighterExpressions,
  163. logsResult,
  164. scanning,
  165. scanRange,
  166. range,
  167. timeZone,
  168. dedupStrategy,
  169. hiddenLogLevels,
  170. dedupedResult,
  171. datasourceInstance,
  172. isLive,
  173. };
  174. }
  175. const mapDispatchToProps = {
  176. changeDedupStrategy,
  177. toggleLogLevelAction,
  178. changeTime,
  179. stopLive: changeRefreshIntervalAction,
  180. };
  181. export default hot(module)(
  182. connect(
  183. mapStateToProps,
  184. mapDispatchToProps
  185. )(LogsContainer)
  186. );