Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
nexpie-grafana-theme
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Registry
Registry
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kornkitt Poolsup
nexpie-grafana-theme
Commits
39f7cff7
Unverified
Commit
39f7cff7
authored
Jan 24, 2020
by
Andrej Ocenas
Committed by
GitHub
Jan 24, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Loki: Refactor editor and syntax hooks (#21687)
parent
b28eac26
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
98 additions
and
69 deletions
+98
-69
public/app/plugins/datasource/loki/components/AnnotationsQueryEditor.tsx
+5
-4
public/app/plugins/datasource/loki/components/LokiQueryEditor.tsx
+0
-10
public/app/plugins/datasource/loki/components/LokiQueryField.tsx
+14
-6
public/app/plugins/datasource/loki/components/LokiQueryFieldForm.tsx
+0
-2
public/app/plugins/datasource/loki/components/useLokiLabels.test.ts
+4
-2
public/app/plugins/datasource/loki/components/useLokiLabels.ts
+19
-9
public/app/plugins/datasource/loki/components/useLokiSyntaxAndLabels.test.ts
+4
-4
public/app/plugins/datasource/loki/components/useLokiSyntaxAndLabels.ts
+47
-28
public/app/plugins/datasource/loki/language_provider.ts
+2
-1
public/app/plugins/datasource/prometheus/components/PromQueryField.tsx
+3
-3
No files found.
public/app/plugins/datasource/loki/components/AnnotationsQueryEditor.tsx
View file @
39f7cff7
...
...
@@ -3,7 +3,7 @@ import React, { memo } from 'react';
// Types
import
{
LokiQuery
}
from
'../types'
;
import
{
useLokiSyntax
}
from
'./useLokiSyntax
'
;
import
{
useLokiSyntax
AndLabels
}
from
'./useLokiSyntaxAndLabels
'
;
import
{
LokiQueryFieldForm
}
from
'./LokiQueryFieldForm'
;
import
LokiDatasource
from
'../datasource'
;
...
...
@@ -22,7 +22,7 @@ export const LokiAnnotationsQueryEditor = memo(function LokiAnnotationQueryEdito
to
:
Date
.
now
(),
};
const
{
isSyntaxReady
,
setActiveOption
,
refreshLabels
,
...
syntaxProps
}
=
useLokiSyntax
(
const
{
isSyntaxReady
,
setActiveOption
,
refreshLabels
,
syntax
,
logLabelOptions
}
=
useLokiSyntaxAndLabels
(
datasource
.
languageProvider
,
absolute
);
...
...
@@ -43,9 +43,10 @@ export const LokiAnnotationsQueryEditor = memo(function LokiAnnotationQueryEdito
data=
{
null
}
onLoadOptions=
{
setActiveOption
}
onLabelsRefresh=
{
refreshLabels
}
syntaxLoaded=
{
isSyntaxReady
}
absoluteRange=
{
absolute
}
{
...
syntaxProps
}
syntax=
{
syntax
}
syntaxLoaded=
{
isSyntaxReady
}
logLabelOptions=
{
logLabelOptions
}
/>
</
div
>
);
...
...
public/app/plugins/datasource/loki/components/LokiQueryEditor.tsx
View file @
39f7cff7
...
...
@@ -6,7 +6,6 @@ import { AbsoluteTimeRange, QueryEditorProps } from '@grafana/data';
import
{
LokiDatasource
}
from
'../datasource'
;
import
{
LokiQuery
}
from
'../types'
;
import
{
LokiQueryField
}
from
'./LokiQueryField'
;
import
{
useLokiSyntax
}
from
'./useLokiSyntax'
;
type
Props
=
QueryEditorProps
<
LokiDatasource
,
LokiQuery
>
;
...
...
@@ -27,11 +26,6 @@ export const LokiQueryEditor = memo(function LokiQueryEditor(props: Props) {
};
}
const
{
isSyntaxReady
,
setActiveOption
,
refreshLabels
,
...
syntaxProps
}
=
useLokiSyntax
(
datasource
.
languageProvider
,
absolute
);
return
(
<
div
>
<
LokiQueryField
...
...
@@ -41,11 +35,7 @@ export const LokiQueryEditor = memo(function LokiQueryEditor(props: Props) {
onRunQuery=
{
onRunQuery
}
history=
{
[]
}
data=
{
data
}
onLoadOptions=
{
setActiveOption
}
onLabelsRefresh=
{
refreshLabels
}
syntaxLoaded=
{
isSyntaxReady
}
absoluteRange=
{
absolute
}
{
...
syntaxProps
}
/>
</
div
>
);
...
...
public/app/plugins/datasource/loki/components/LokiQueryField.tsx
View file @
39f7cff7
import
React
,
{
FunctionComponent
}
from
'react'
;
import
{
LokiQueryFieldForm
,
LokiQueryFieldFormProps
}
from
'./LokiQueryFieldForm'
;
import
{
useLokiSyntax
}
from
'./useLokiSyntax
'
;
import
{
useLokiSyntax
AndLabels
}
from
'./useLokiSyntaxAndLabels
'
;
import
LokiLanguageProvider
from
'../language_provider'
;
export
const
LokiQueryField
:
FunctionComponent
<
LokiQueryFieldFormProps
>
=
({
datasource
,
...
otherProps
})
=>
{
const
{
isSyntaxReady
,
setActiveOption
,
refreshLabels
,
...
syntaxProps
}
=
useLokiSyntax
(
type
LokiQueryFieldProps
=
Omit
<
LokiQueryFieldFormProps
,
'syntax'
|
'syntaxLoaded'
|
'onLoadOptions'
|
'onLabelsRefresh'
|
'logLabelOptions'
>
;
export
const
LokiQueryField
:
FunctionComponent
<
LokiQueryFieldProps
>
=
props
=>
{
const
{
datasource
,
absoluteRange
,
...
otherProps
}
=
props
;
const
{
isSyntaxReady
,
setActiveOption
,
refreshLabels
,
syntax
,
logLabelOptions
}
=
useLokiSyntaxAndLabels
(
datasource
.
languageProvider
as
LokiLanguageProvider
,
otherProps
.
absoluteRange
absoluteRange
);
return
(
<
LokiQueryFieldForm
datasource=
{
datasource
}
syntaxLoaded=
{
isSyntaxReady
}
/**
* setActiveOption name is intentional. Because of the way rc-cascader requests additional data
* https://github.com/react-component/cascader/blob/master/src/Cascader.jsx#L165
...
...
@@ -21,7 +26,10 @@ export const LokiQueryField: FunctionComponent<LokiQueryFieldFormProps> = ({ dat
*/
onLoadOptions=
{
setActiveOption
}
onLabelsRefresh=
{
refreshLabels
}
{
...
syntaxProps
}
absoluteRange=
{
absoluteRange
}
syntax=
{
syntax
}
syntaxLoaded=
{
isSyntaxReady
}
logLabelOptions=
{
logLabelOptions
}
{
...
otherProps
}
/>
);
...
...
public/app/plugins/datasource/loki/components/LokiQueryFieldForm.tsx
View file @
39f7cff7
...
...
@@ -73,8 +73,6 @@ export interface LokiQueryFieldFormProps extends ExploreQueryFieldProps<LokiData
export
class
LokiQueryFieldForm
extends
React
.
PureComponent
<
LokiQueryFieldFormProps
>
{
plugins
:
Plugin
[];
modifiedSearch
:
string
;
modifiedQuery
:
string
;
constructor
(
props
:
LokiQueryFieldFormProps
,
context
:
React
.
Context
<
any
>
)
{
super
(
props
,
context
);
...
...
public/app/plugins/datasource/loki/components/useLokiLabels.test.ts
View file @
39f7cff7
...
...
@@ -14,14 +14,16 @@ describe('useLokiLabels hook', () => {
to
:
1560153109000
,
};
languageProvider
.
logLabelOptions
=
[
'initial'
];
languageProvider
.
refreshLogLabels
=
()
=>
{
languageProvider
.
logLabelOptions
=
logLabelOptionsMock
;
return
Promise
.
resolve
();
};
const
{
result
,
waitForNextUpdate
}
=
renderHook
(()
=>
useLokiLabels
(
languageProvider
,
true
,
[],
rangeMock
));
const
{
result
,
waitForNextUpdate
}
=
renderHook
(()
=>
useLokiLabels
(
languageProvider
,
true
,
rangeMock
));
expect
(
result
.
current
.
logLabelOptions
).
toEqual
([
'initial'
]);
act
(()
=>
result
.
current
.
refreshLabels
());
expect
(
result
.
current
.
logLabelOptions
).
toEqual
([]);
await
waitForNextUpdate
();
expect
(
result
.
current
.
logLabelOptions
).
toEqual
(
logLabelOptionsMock
);
});
...
...
public/app/plugins/datasource/loki/components/useLokiLabels.ts
View file @
39f7cff7
...
...
@@ -9,14 +9,13 @@ import { useRefMounted } from 'app/core/hooks/useRefMounted';
*
* @param languageProvider
* @param languageProviderInitialised
* @param a
ctiveOption rc-cascader provided option used to fetch option's values that hasn't been loaded yet
* @param a
bsoluteRange
*
* @description Fetches missing labels and enables labels refresh
*/
export
const
useLokiLabels
=
(
languageProvider
:
LokiLanguageProvider
,
languageProviderInitialised
:
boolean
,
activeOption
:
CascaderOption
[],
absoluteRange
:
AbsoluteTimeRange
)
=>
{
const
mounted
=
useRefMounted
();
...
...
@@ -24,7 +23,12 @@ export const useLokiLabels = (
// State
const
[
logLabelOptions
,
setLogLabelOptions
]
=
useState
([]);
const
[
shouldTryRefreshLabels
,
setRefreshLabels
]
=
useState
(
false
);
const
[
shouldForceRefreshLabels
,
setForceRefreshLabels
]
=
useState
(
false
);
/**
* Holds information about currently selected option from rc-cascader to perform effect
* that loads option values not fetched yet. Based on that useLokiLabels hook decides whether or not
* the option requires additional data fetching
*/
const
[
activeOption
,
setActiveOption
]
=
useState
<
CascaderOption
[]
>
([]);
// Async
const
fetchOptionValues
=
async
(
option
:
string
)
=>
{
...
...
@@ -35,11 +39,10 @@ export const useLokiLabels = (
};
const
tryLabelsRefresh
=
async
()
=>
{
await
languageProvider
.
refreshLogLabels
(
absoluteRange
,
shouldForceRefreshLabels
);
await
languageProvider
.
refreshLogLabels
(
absoluteRange
);
if
(
mounted
.
current
)
{
setRefreshLabels
(
false
);
setForceRefreshLabels
(
false
);
setLogLabelOptions
(
languageProvider
.
logLabelOptions
);
}
};
...
...
@@ -68,18 +71,25 @@ export const useLokiLabels = (
}
},
[
activeOption
]);
// This effect is performed on shouldTryRefreshLabels
or shouldForceRefreshLabels
state change only.
// This effect is performed on shouldTryRefreshLabels state change only.
// Since shouldTryRefreshLabels is reset AFTER the labels are refreshed we are secured in case of trying to refresh
// when previous refresh hasn't finished yet
useEffect
(()
=>
{
if
(
shouldTryRefreshLabels
||
shouldForceRefreshLabels
)
{
if
(
shouldTryRefreshLabels
)
{
tryLabelsRefresh
();
}
},
[
shouldTryRefreshLabels
,
shouldForceRefreshLabels
]);
},
[
shouldTryRefreshLabels
]);
// Initialize labels from the provider after it gets initialized (it's initialisation happens outside of this hook)
useEffect
(()
=>
{
if
(
languageProviderInitialised
)
{
setLogLabelOptions
(
languageProvider
.
logLabelOptions
);
}
},
[
languageProviderInitialised
]);
return
{
logLabelOptions
,
setLogLabelOptions
,
refreshLabels
:
()
=>
setRefreshLabels
(
true
),
setActiveOption
,
};
};
public/app/plugins/datasource/loki/components/useLokiSyntax.test.ts
→
public/app/plugins/datasource/loki/components/useLokiSyntax
AndLabels
.test.ts
View file @
39f7cff7
...
...
@@ -4,7 +4,7 @@ import { CascaderOption } from '@grafana/ui';
import
LanguageProvider
from
'app/plugins/datasource/loki/language_provider'
;
import
{
useLokiSyntax
}
from
'./useLokiSyntax
'
;
import
{
useLokiSyntax
AndLabels
}
from
'./useLokiSyntaxAndLabels
'
;
import
{
makeMockLokiDatasource
}
from
'../mocks'
;
describe
(
'useLokiSyntax hook'
,
()
=>
{
...
...
@@ -35,7 +35,7 @@ describe('useLokiSyntax hook', () => {
};
it
(
'should provide Loki syntax when used'
,
async
()
=>
{
const
{
result
,
waitForNextUpdate
}
=
renderHook
(()
=>
useLokiSyntax
(
languageProvider
,
rangeMock
));
const
{
result
,
waitForNextUpdate
}
=
renderHook
(()
=>
useLokiSyntax
AndLabels
(
languageProvider
,
rangeMock
));
expect
(
result
.
current
.
syntax
).
toEqual
(
null
);
await
waitForNextUpdate
();
...
...
@@ -44,7 +44,7 @@ describe('useLokiSyntax hook', () => {
});
it
(
'should fetch labels on first call'
,
async
()
=>
{
const
{
result
,
waitForNextUpdate
}
=
renderHook
(()
=>
useLokiSyntax
(
languageProvider
,
rangeMock
));
const
{
result
,
waitForNextUpdate
}
=
renderHook
(()
=>
useLokiSyntax
AndLabels
(
languageProvider
,
rangeMock
));
expect
(
result
.
current
.
isSyntaxReady
).
toBeFalsy
();
expect
(
result
.
current
.
logLabelOptions
).
toEqual
([]);
...
...
@@ -55,7 +55,7 @@ describe('useLokiSyntax hook', () => {
});
it
(
'should try to fetch missing options when active option changes'
,
async
()
=>
{
const
{
result
,
waitForNextUpdate
}
=
renderHook
(()
=>
useLokiSyntax
(
languageProvider
,
rangeMock
));
const
{
result
,
waitForNextUpdate
}
=
renderHook
(()
=>
useLokiSyntax
AndLabels
(
languageProvider
,
rangeMock
));
await
waitForNextUpdate
();
expect
(
result
.
current
.
logLabelOptions
).
toEqual
(
logLabelOptionsMock2
);
...
...
public/app/plugins/datasource/loki/components/useLokiSyntax.ts
→
public/app/plugins/datasource/loki/components/useLokiSyntax
AndLabels
.ts
View file @
39f7cff7
import
{
useState
,
useEffect
}
from
'react'
;
import
Prism
from
'prismjs'
;
import
Prism
,
{
Grammar
}
from
'prismjs'
;
import
{
AbsoluteTimeRange
}
from
'@grafana/data'
;
import
{
CascaderOption
}
from
'@grafana/ui'
;
import
LokiLanguageProvider
from
'app/plugins/datasource/loki/language_provider'
;
import
{
useLokiLabels
}
from
'app/plugins/datasource/loki/components/useLokiLabels'
;
import
{
useRefMounted
}
from
'app/core/hooks/useRefMounted'
;
...
...
@@ -9,49 +8,69 @@ import { useRefMounted } from 'app/core/hooks/useRefMounted';
const
PRISM_SYNTAX
=
'promql'
;
/**
*
*
@param languageProvider
*
@description Initializes given language provider, exposes Loki syntax and enables loading label option values
*
Initialise the language provider. Returns a languageProviderInitialized boolean cause there does not seem other way
*
to know if the provider is already initialised or not. By the initialisation it modifies the provided
*
languageProvider directly.
*/
export
const
useLokiSyntax
=
(
languageProvider
:
LokiLanguageProvider
,
absoluteRange
:
AbsoluteTimeRange
)
=>
{
const
useInitLanguageProvider
=
(
languageProvider
:
LokiLanguageProvider
,
absoluteRange
:
AbsoluteTimeRange
)
=>
{
const
mounted
=
useRefMounted
();
// State
const
[
languageProviderInitialized
,
setLanguageProviderInitilized
]
=
useState
(
false
);
const
[
syntax
,
setSyntax
]
=
useState
(
null
);
/**
* Holds information about currently selected option from rc-cascader to perform effect
* that loads option values not fetched yet. Based on that useLokiLabels hook decides whether or not
* the option requires additional data fetching
*/
const
[
activeOption
,
setActiveOption
]
=
useState
<
CascaderOption
[]
>
();
const
{
logLabelOptions
,
setLogLabelOptions
,
refreshLabels
}
=
useLokiLabels
(
languageProvider
,
languageProviderInitialized
,
activeOption
,
absoluteRange
);
const
[
languageProviderInitialized
,
setLanguageProviderInitialized
]
=
useState
(
false
);
// Async
const
initializeLanguageProvider
=
async
()
=>
{
languageProvider
.
initialRange
=
absoluteRange
;
await
languageProvider
.
start
();
Prism
.
languages
[
PRISM_SYNTAX
]
=
languageProvider
.
getSyntax
();
if
(
mounted
.
current
)
{
setLogLabelOptions
(
languageProvider
.
logLabelOptions
);
setSyntax
(
languageProvider
.
getSyntax
());
setLanguageProviderInitilized
(
true
);
setLanguageProviderInitialized
(
true
);
}
};
// Effects
useEffect
(()
=>
{
initializeLanguageProvider
();
},
[]);
return
languageProviderInitialized
;
};
/**
* Returns syntax from languageProvider and initialises global Prism syntax. Waits until languageProvider itself is
* initialised (outside of this hook).
*/
const
useLokiSyntax
=
(
languageProvider
:
LokiLanguageProvider
,
languageProviderInitialized
:
boolean
)
=>
{
// State
const
[
syntax
,
setSyntax
]
=
useState
<
Grammar
>
(
null
);
// Effects
useEffect
(()
=>
{
if
(
languageProviderInitialized
)
{
const
syntax
=
languageProvider
.
getSyntax
();
Prism
.
languages
[
PRISM_SYNTAX
]
=
syntax
;
setSyntax
(
syntax
);
}
},
[
languageProviderInitialized
,
languageProvider
]);
return
{
isSyntaxReady
:
!!
syntax
,
syntax
,
};
};
/**
* Initializes given language provider, exposes Loki syntax and enables loading label option values
*/
export
const
useLokiSyntaxAndLabels
=
(
languageProvider
:
LokiLanguageProvider
,
absoluteRange
:
AbsoluteTimeRange
)
=>
{
const
languageProviderInitialized
=
useInitLanguageProvider
(
languageProvider
,
absoluteRange
);
const
{
logLabelOptions
,
refreshLabels
,
setActiveOption
}
=
useLokiLabels
(
languageProvider
,
languageProviderInitialized
,
absoluteRange
);
const
{
isSyntaxReady
,
syntax
}
=
useLokiSyntax
(
languageProvider
,
languageProviderInitialized
);
return
{
isSyntaxReady
:
languageProviderInitialized
,
isSyntaxReady
,
syntax
,
logLabelOptions
,
setActiveOption
,
...
...
public/app/plugins/datasource/loki/language_provider.ts
View file @
39f7cff7
...
...
@@ -13,6 +13,7 @@ import { RATE_RANGES } from '../prometheus/promql';
import
LokiDatasource
from
'./datasource'
;
import
{
CompletionItem
,
TypeaheadInput
,
TypeaheadOutput
}
from
'@grafana/ui'
;
import
{
Grammar
}
from
'prismjs'
;
const
DEFAULT_KEYS
=
[
'job'
,
'namespace'
];
const
EMPTY_SELECTOR
=
'{}'
;
...
...
@@ -70,7 +71,7 @@ export default class LokiLanguageProvider extends LanguageProvider {
// Strip syntax chars
cleanText
=
(
s
:
string
)
=>
s
.
replace
(
/
[
{}[
\]
="(),!~+
\-
*
/
^%
]
/g
,
''
).
trim
();
getSyntax
()
{
getSyntax
()
:
Grammar
{
return
syntax
;
}
...
...
public/app/plugins/datasource/prometheus/components/PromQueryField.tsx
View file @
39f7cff7
...
...
@@ -188,9 +188,9 @@ class PromQueryField extends React.PureComponent<PromQueryFieldProps, PromQueryF
remaining
.
map
((
task
:
Promise
<
any
>
)
=>
task
.
then
(
this
.
onUpdateLanguage
).
catch
(()
=>
{}));
})
.
then
(()
=>
this
.
onUpdateLanguage
())
.
catch
(
({
isCanceled
})
=>
{
if
(
isCanceled
)
{
console
.
warn
(
'PromQueryField has unmounted, language provider intialization was canceled'
)
;
.
catch
(
err
=>
{
if
(
!
err
.
isCanceled
)
{
throw
err
;
}
});
};
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment