LokiCheatSheet.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. import React, { PureComponent } from 'react';
  2. import { shuffle } from 'lodash';
  3. import { ExploreStartPageProps, DataQuery } from '@grafana/ui';
  4. import LokiLanguageProvider from '../language_provider';
  5. const DEFAULT_EXAMPLES = ['{job="default/prometheus"}'];
  6. const PREFERRED_LABELS = ['job', 'app', 'k8s_app'];
  7. const EXAMPLES_LIMIT = 5;
  8. export default class LokiCheatSheet extends PureComponent<ExploreStartPageProps, { userExamples: string[] }> {
  9. userLabelTimer: NodeJS.Timeout;
  10. state = {
  11. userExamples: DEFAULT_EXAMPLES,
  12. };
  13. componentDidMount() {
  14. this.scheduleUserLabelChecking();
  15. }
  16. componentWillUnmount() {
  17. clearTimeout(this.userLabelTimer);
  18. }
  19. scheduleUserLabelChecking() {
  20. this.userLabelTimer = setTimeout(this.checkUserLabels, 1000);
  21. }
  22. checkUserLabels = async () => {
  23. // Set example from user labels
  24. const provider: LokiLanguageProvider = this.props.datasource.languageProvider;
  25. if (provider.started) {
  26. const labels = provider.getLabelKeys() || [];
  27. const preferredLabel = PREFERRED_LABELS.find(l => labels.includes(l));
  28. if (preferredLabel) {
  29. const values = await provider.getLabelValues(preferredLabel);
  30. const userExamples = shuffle(values)
  31. .slice(0, EXAMPLES_LIMIT)
  32. .map(value => `{${preferredLabel}="${value}"}`);
  33. this.setState({ userExamples });
  34. }
  35. } else {
  36. this.scheduleUserLabelChecking();
  37. }
  38. };
  39. renderExpression(expr: string) {
  40. const { onClickExample } = this.props;
  41. return (
  42. <div
  43. className="cheat-sheet-item__example"
  44. key={expr}
  45. onClick={e => onClickExample({ refId: 'A', expr } as DataQuery)}
  46. >
  47. <code>{expr}</code>
  48. </div>
  49. );
  50. }
  51. render() {
  52. const { userExamples } = this.state;
  53. return (
  54. <div>
  55. <h2>Loki Cheat Sheet</h2>
  56. <div className="cheat-sheet-item">
  57. <div className="cheat-sheet-item__title">See your logs</div>
  58. <div className="cheat-sheet-item__label">Start by selecting a log stream from the Log labels selector.</div>
  59. <div className="cheat-sheet-item__label">
  60. Alternatively, you can write a stream selector into the query field:
  61. </div>
  62. {this.renderExpression('{job="default/prometheus"}')}
  63. {userExamples !== DEFAULT_EXAMPLES && userExamples.length > 0 ? (
  64. <div>
  65. <div className="cheat-sheet-item__label">Here are some example streams from your logs:</div>
  66. {userExamples.map(example => this.renderExpression(example))}
  67. </div>
  68. ) : null}
  69. </div>
  70. <div className="cheat-sheet-item">
  71. <div className="cheat-sheet-item__title">Combine stream selectors</div>
  72. {this.renderExpression('{app="cassandra",namespace="prod"}')}
  73. <div className="cheat-sheet-item__label">Returns all log lines from streams that have both labels.</div>
  74. </div>
  75. <div className="cheat-sheet-item">
  76. <div className="cheat-sheet-item__title">Filtering for search terms.</div>
  77. {this.renderExpression('{app="cassandra"} |~ "(duration|latency)s*(=|is|of)s*[d.]+"')}
  78. {this.renderExpression('{app="cassandra"} |= "exact match"')}
  79. {this.renderExpression('{app="cassandra"} != "do not match"')}
  80. <div className="cheat-sheet-item__label">
  81. <a href="https://github.com/grafana/loki/blob/master/docs/usage.md#filter-expression" target="logql">
  82. LogQL
  83. </a>{' '}
  84. supports exact and regular expression filters.
  85. </div>
  86. </div>
  87. </div>
  88. );
  89. }
  90. }