2019-09-16 00:17:34 -05:00
import React , { PureComponent } from 'react' ;
import { shuffle } from 'lodash' ;
2021-06-14 09:13:48 -05:00
import { QueryEditorHelpProps } from '@grafana/data' ;
2019-09-16 00:17:34 -05:00
import LokiLanguageProvider from '../language_provider' ;
2021-06-14 09:13:48 -05:00
import { LokiQuery } from '../types' ;
2019-09-16 00:17:34 -05:00
const DEFAULT_EXAMPLES = [ '{job="default/prometheus"}' ] ;
const PREFERRED_LABELS = [ 'job' , 'app' , 'k8s_app' ] ;
const EXAMPLES_LIMIT = 5 ;
2019-11-15 09:38:25 -06:00
const LOGQL_EXAMPLES = [
2020-10-28 03:16:10 -05:00
{
title : 'Log pipeline' ,
expression : '{job="mysql"} |= "metrics" | logfmt | duration > 10s' ,
label :
'This query targets the MySQL job, filters out logs that don’ t contain the word "metrics" and parses each log line to extract more labels and filters with them.' ,
} ,
2019-11-15 09:38:25 -06:00
{
title : 'Count over time' ,
expression : 'count_over_time({job="mysql"}[5m])' ,
label : 'This query counts all the log lines within the last five minutes for the MySQL job.' ,
} ,
{
title : 'Rate' ,
expression : 'rate(({job="mysql"} |= "error" != "timeout")[10s])' ,
label :
'This query gets the per-second rate of all non-timeout errors within the last ten seconds for the MySQL job.' ,
} ,
{
title : 'Aggregate, count, and group' ,
expression : 'sum(count_over_time({job="mysql"}[5m])) by (level)' ,
label : 'Get the count of logs during the last five minutes, grouping by level.' ,
} ,
] ;
2021-06-14 09:13:48 -05:00
export default class LokiCheatSheet extends PureComponent < QueryEditorHelpProps < LokiQuery > , { userExamples : string [ ] } > {
2019-09-16 00:17:34 -05:00
userLabelTimer : NodeJS.Timeout ;
state = {
userExamples : DEFAULT_EXAMPLES ,
} ;
componentDidMount() {
this . scheduleUserLabelChecking ( ) ;
}
componentWillUnmount() {
clearTimeout ( this . userLabelTimer ) ;
}
scheduleUserLabelChecking() {
this . userLabelTimer = setTimeout ( this . checkUserLabels , 1000 ) ;
}
checkUserLabels = async ( ) = > {
// Set example from user labels
2020-07-09 09:14:55 -05:00
const provider : LokiLanguageProvider = this . props . datasource ? . languageProvider ;
2019-09-16 00:17:34 -05:00
if ( provider . started ) {
const labels = provider . getLabelKeys ( ) || [ ] ;
2021-01-20 00:59:48 -06:00
const preferredLabel = PREFERRED_LABELS . find ( ( l ) = > labels . includes ( l ) ) ;
2019-09-16 00:17:34 -05:00
if ( preferredLabel ) {
const values = await provider . getLabelValues ( preferredLabel ) ;
const userExamples = shuffle ( values )
. slice ( 0 , EXAMPLES_LIMIT )
2021-01-20 00:59:48 -06:00
. map ( ( value ) = > ` { ${ preferredLabel } =" ${ value } "} ` ) ;
2019-09-16 00:17:34 -05:00
this . setState ( { userExamples } ) ;
}
} else {
this . scheduleUserLabelChecking ( ) ;
}
} ;
renderExpression ( expr : string ) {
const { onClickExample } = this . props ;
return (
2021-06-14 09:13:48 -05:00
< div className = "cheat-sheet-item__example" key = { expr } onClick = { ( e ) = > onClickExample ( { refId : 'A' , expr } ) } >
2019-09-16 00:17:34 -05:00
< code > { expr } < / code >
< / div >
) ;
}
2020-07-09 09:14:55 -05:00
render() {
2019-09-16 00:17:34 -05:00
const { userExamples } = this . state ;
return (
2020-07-09 09:14:55 -05:00
< div >
2019-09-16 00:17:34 -05:00
< h2 > Loki Cheat Sheet < / h2 >
< div className = "cheat-sheet-item" >
< div className = "cheat-sheet-item__title" > See your logs < / div >
< div className = "cheat-sheet-item__label" > Start by selecting a log stream from the Log labels selector . < / div >
< div className = "cheat-sheet-item__label" >
Alternatively , you can write a stream selector into the query field :
< / div >
{ this . renderExpression ( '{job="default/prometheus"}' ) }
{ userExamples !== DEFAULT_EXAMPLES && userExamples . length > 0 ? (
< div >
< div className = "cheat-sheet-item__label" > Here are some example streams from your logs : < / div >
2021-01-20 00:59:48 -06:00
{ userExamples . map ( ( example ) = > this . renderExpression ( example ) ) }
2019-09-16 00:17:34 -05:00
< / div >
) : null }
< / div >
< div className = "cheat-sheet-item" >
< div className = "cheat-sheet-item__title" > Combine stream selectors < / div >
{ this . renderExpression ( '{app="cassandra",namespace="prod"}' ) }
< div className = "cheat-sheet-item__label" > Returns all log lines from streams that have both labels . < / div >
< / div >
< div className = "cheat-sheet-item" >
< div className = "cheat-sheet-item__title" > Filtering for search terms . < / div >
{ this . renderExpression ( '{app="cassandra"} |~ "(duration|latency)s*(=|is|of)s*[d.]+"' ) }
{ this . renderExpression ( '{app="cassandra"} |= "exact match"' ) }
{ this . renderExpression ( '{app="cassandra"} != "do not match"' ) }
< div className = "cheat-sheet-item__label" >
2020-11-11 13:00:47 -06:00
< a href = "https://grafana.com/docs/loki/latest/logql/#log-pipeline" target = "logql" >
2019-09-16 00:17:34 -05:00
LogQL
< / a > { ' ' }
supports exact and regular expression filters .
2018-12-09 11:44:59 -06:00
< / div >
2019-09-16 00:17:34 -05:00
< / div >
2021-01-20 00:59:48 -06:00
{ LOGQL_EXAMPLES . map ( ( item ) = > (
2019-11-15 09:38:25 -06:00
< div className = "cheat-sheet-item" key = { item . expression } >
< div className = "cheat-sheet-item__title" > { item . title } < / div >
{ this . renderExpression ( item . expression ) }
< div className = "cheat-sheet-item__label" > { item . label } < / div >
< / div >
) ) }
< / div >
) ;
}
2019-09-16 00:17:34 -05:00
}