2020-12-02 03:43:35 +08:00
// Libraries
import React , { memo } from 'react' ;
2021-04-01 20:15:23 +08:00
import { css , cx } from '@emotion/css' ;
2021-08-16 20:02:13 +08:00
import { map } from 'lodash' ;
2020-12-02 03:43:35 +08:00
// Types
2021-08-16 20:02:13 +08:00
import { InlineFormLabel , RadioButtonGroup , InlineField , Input , Select } from '@grafana/ui' ;
import { SelectableValue } from '@grafana/data' ;
import { LokiQuery } from '../types' ;
2020-12-02 03:43:35 +08:00
export interface LokiOptionFieldsProps {
lineLimitValue : string ;
2021-08-16 20:02:13 +08:00
resolution : number ;
2020-12-02 03:43:35 +08:00
queryType : LokiQueryType ;
query : LokiQuery ;
onChange : ( value : LokiQuery ) = > void ;
onRunQuery : ( ) = > void ;
runOnBlur? : boolean ;
}
type LokiQueryType = 'instant' | 'range' ;
2021-07-23 17:33:26 +08:00
const queryTypeOptions : Array < SelectableValue < LokiQueryType > > = [
2021-03-09 21:17:04 +08:00
{ value : 'range' , label : 'Range' , description : 'Run query over a range of time.' } ,
{
value : 'instant' ,
label : 'Instant' ,
description : 'Run query against a single point in time. For this query, the "To" time is used.' ,
} ,
2020-12-02 03:43:35 +08:00
] ;
2021-08-16 20:02:13 +08:00
export const DEFAULT_RESOLUTION : SelectableValue < number > = {
value : 1 ,
label : '1/1' ,
} ;
const RESOLUTION_OPTIONS : Array < SelectableValue < number > > = [ DEFAULT_RESOLUTION ] . concat (
map ( [ 2 , 3 , 4 , 5 , 10 ] , ( value : number ) = > ( {
value ,
label : '1/' + value ,
} ) )
) ;
2020-12-02 03:43:35 +08:00
export function LokiOptionFields ( props : LokiOptionFieldsProps ) {
2021-08-16 20:02:13 +08:00
const { lineLimitValue , resolution , queryType , query , onRunQuery , runOnBlur , onChange } = props ;
2020-12-02 03:43:35 +08:00
function onChangeQueryLimit ( value : string ) {
const nextQuery = { . . . query , maxLines : preprocessMaxLines ( value ) } ;
onChange ( nextQuery ) ;
}
function onQueryTypeChange ( value : LokiQueryType ) {
let nextQuery ;
if ( value === 'instant' ) {
nextQuery = { . . . query , instant : true , range : false } ;
} else {
nextQuery = { . . . query , instant : false , range : true } ;
}
onChange ( nextQuery ) ;
}
function preprocessMaxLines ( value : string ) : number {
if ( value . length === 0 ) {
// empty input - falls back to dataSource.maxLines limit
return NaN ;
} else if ( value . length > 0 && ( isNaN ( + value ) || + value < 0 ) ) {
// input with at least 1 character and that is either incorrect (value in the input field is not a number) or negative
// falls back to the limit of 0 lines
return 0 ;
} else {
// default case - correct input
return + value ;
}
}
function onMaxLinesChange ( e : React.SyntheticEvent < HTMLInputElement > ) {
if ( query . maxLines !== preprocessMaxLines ( e . currentTarget . value ) ) {
onChangeQueryLimit ( e . currentTarget . value ) ;
}
}
function onReturnKeyDown ( e : React.KeyboardEvent < HTMLInputElement > ) {
if ( e . key === 'Enter' ) {
onRunQuery ( ) ;
}
}
2021-08-16 20:02:13 +08:00
function onResolutionChange ( option : SelectableValue < number > ) {
const nextQuery = { . . . query , resolution : option.value } ;
onChange ( nextQuery ) ;
}
2020-12-02 03:43:35 +08:00
return (
< div aria - label = "Loki extra field" className = "gf-form-inline" >
{ /*Query type field*/ }
< div
data - testid = "queryTypeField"
className = { cx (
'gf-form explore-input-margin' ,
css `
flex - wrap : nowrap ;
`
) }
aria - label = "Query type field"
>
2021-03-09 21:17:04 +08:00
< InlineFormLabel width = "auto" > Query type < / InlineFormLabel >
2020-12-02 03:43:35 +08:00
< RadioButtonGroup
options = { queryTypeOptions }
value = { queryType }
onChange = { ( type : LokiQueryType ) = > {
onQueryTypeChange ( type ) ;
if ( runOnBlur ) {
onRunQuery ( ) ;
}
} }
/ >
< / div >
{ /*Line limit field*/ }
< div
data - testid = "lineLimitField"
className = { cx (
'gf-form' ,
css `
flex - wrap : nowrap ;
`
) }
aria - label = "Line limit field"
>
2021-08-16 20:02:13 +08:00
< InlineField label = "Line limit" tooltip = { 'Upper limit for number of log lines returned by query.' } >
2021-03-01 23:08:53 +08:00
< Input
className = "width-4"
placeholder = "auto"
type = "number"
min = { 0 }
onChange = { onMaxLinesChange }
onKeyDown = { onReturnKeyDown }
value = { lineLimitValue }
onBlur = { ( ) = > {
if ( runOnBlur ) {
onRunQuery ( ) ;
}
} }
/ >
< / InlineField >
2021-08-16 20:02:13 +08:00
< InlineField
label = "Resolution"
tooltip = {
'Resolution 1/1 sets step parameter of Loki metrics range queries such that each pixel corresponds to one data point. For better performance, lower resolutions can be picked. 1/2 only retrieves a data point for every other pixel, and 1/10 retrieves one data point per 10 pixels.'
}
>
2021-12-03 21:14:51 +08:00
< Select
isSearchable = { false }
onChange = { onResolutionChange }
options = { RESOLUTION_OPTIONS }
value = { resolution }
aria - label = "Select resolution"
/ >
2021-08-16 20:02:13 +08:00
< / InlineField >
2020-12-02 03:43:35 +08:00
< / div >
< / div >
) ;
}
export default memo ( LokiOptionFields ) ;