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
0e8638ec
Unverified
Commit
0e8638ec
authored
May 14, 2020
by
kay delaney
Committed by
GitHub
May 14, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Datasource/CloudWatch: Allows a user to search for log groups that aren't there initially (#24695)
Closes #24554
parent
bc8c0513
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
189 additions
and
2 deletions
+189
-2
packages/grafana-ui/src/components/Select/types.ts
+4
-1
public/app/plugins/datasource/cloudwatch/components/LogsQueryField.test.tsx
+154
-0
public/app/plugins/datasource/cloudwatch/components/LogsQueryField.tsx
+31
-1
No files found.
packages/grafana-ui/src/components/Select/types.ts
View file @
0e8638ec
...
...
@@ -2,6 +2,9 @@ import { SelectableValue } from '@grafana/data';
import
React
from
'react'
;
export
type
SelectValue
<
T
>
=
T
|
SelectableValue
<
T
>
|
T
[]
|
Array
<
SelectableValue
<
T
>>
;
export
type
InputActionMeta
=
{
action
:
'set-value'
|
'input-change'
|
'input-blur'
|
'menu-close'
;
};
export
interface
SelectCommonProps
<
T
>
{
allowCustomValue
?:
boolean
;
...
...
@@ -39,7 +42,7 @@ export interface SelectCommonProps<T> {
onCloseMenu
?:
()
=>
void
;
/** allowCustomValue must be enabled. Function decides what to do with that custom value. */
onCreateOption
?:
(
value
:
string
)
=>
void
;
onInputChange
?:
(
label
:
string
)
=>
void
;
onInputChange
?:
(
value
:
string
,
actionMeta
:
InputActionMeta
)
=>
void
;
onKeyDown
?:
(
event
:
React
.
KeyboardEvent
)
=>
void
;
onOpenMenu
?:
()
=>
void
;
openMenuOnFocus
?:
boolean
;
...
...
public/app/plugins/datasource/cloudwatch/components/LogsQueryField.test.tsx
View file @
0e8638ec
...
...
@@ -2,6 +2,13 @@ import React from 'react';
import
{
shallow
}
from
'enzyme'
;
import
{
CloudWatchLogsQueryField
}
from
'./LogsQueryField'
;
import
{
ExploreId
}
from
'../../../../types'
;
import
{
DescribeLogGroupsRequest
}
from
'../types'
;
import
{
SelectableValue
}
from
'@grafana/data'
;
jest
.
mock
(
'lodash/debounce'
,
()
=>
{
const
fakeDebounce
=
(
func
:
()
=>
any
,
period
:
number
)
=>
func
;
return
fakeDebounce
;
});
describe
(
'CloudWatchLogsQueryField'
,
()
=>
{
it
(
'updates upstream query log groups on region change'
,
async
()
=>
{
...
...
@@ -58,4 +65,151 @@ describe('CloudWatchLogsQueryField', () => {
// Make sure we correctly updated the upstream state
expect
(
onChange
.
mock
.
calls
[
onChange
.
mock
.
calls
.
length
-
1
][
0
]).
toEqual
({
region
:
'region2'
,
logGroupNames
:
[]
});
});
it
(
'should merge results of remote log groups search with existing results'
,
async
()
=>
{
const
allLogGroups
=
[
'AmazingGroup'
,
'AmazingGroup2'
,
'AmazingGroup3'
,
'BeautifulGroup'
,
'BeautifulGroup2'
,
'BeautifulGroup3'
,
'CrazyGroup'
,
'CrazyGroup2'
,
'CrazyGroup3'
,
'DeliciousGroup'
,
'DeliciousGroup2'
,
'DeliciousGroup3'
,
'EnjoyableGroup'
,
'EnjoyableGroup2'
,
'EnjoyableGroup3'
,
'FavouriteGroup'
,
'FavouriteGroup2'
,
'FavouriteGroup3'
,
'GorgeousGroup'
,
'GorgeousGroup2'
,
'GorgeousGroup3'
,
'HappyGroup'
,
'HappyGroup2'
,
'HappyGroup3'
,
'IncredibleGroup'
,
'IncredibleGroup2'
,
'IncredibleGroup3'
,
'JollyGroup'
,
'JollyGroup2'
,
'JollyGroup3'
,
'KoolGroup'
,
'KoolGroup2'
,
'KoolGroup3'
,
'LovelyGroup'
,
'LovelyGroup2'
,
'LovelyGroup3'
,
'MagnificentGroup'
,
'MagnificentGroup2'
,
'MagnificentGroup3'
,
'NiceGroup'
,
'NiceGroup2'
,
'NiceGroup3'
,
'OddGroup'
,
'OddGroup2'
,
'OddGroup3'
,
'PerfectGroup'
,
'PerfectGroup2'
,
'PerfectGroup3'
,
'QuietGroup'
,
'QuietGroup2'
,
'QuietGroup3'
,
'RestlessGroup'
,
'RestlessGroup2'
,
'RestlessGroup3'
,
'SurpriseGroup'
,
'SurpriseGroup2'
,
'SurpriseGroup3'
,
'TestingGroup'
,
'TestingGroup2'
,
'TestingGroup3'
,
'UmbrellaGroup'
,
'UmbrellaGroup2'
,
'UmbrellaGroup3'
,
'VelvetGroup'
,
'VelvetGroup2'
,
'VelvetGroup3'
,
'WaterGroup'
,
'WaterGroup2'
,
'WaterGroup3'
,
'XylophoneGroup'
,
'XylophoneGroup2'
,
'XylophoneGroup3'
,
'YellowGroup'
,
'YellowGroup2'
,
'YellowGroup3'
,
'ZebraGroup'
,
'ZebraGroup2'
,
'ZebraGroup3'
,
];
const
onChange
=
jest
.
fn
();
const
wrapper
=
shallow
<
CloudWatchLogsQueryField
>
(
<
CloudWatchLogsQueryField
history=
{
[]
}
absoluteRange=
{
{
from
:
1
,
to
:
10
}
}
syntaxLoaded=
{
false
}
syntax=
{
{}
as
any
}
exploreId=
{
ExploreId
.
left
}
datasource=
{
{
getRegions
()
{
return
Promise
.
resolve
([
{
label
:
'region1'
,
value
:
'region1'
,
text
:
'region1'
,
},
{
label
:
'region2'
,
value
:
'region2'
,
text
:
'region2'
,
},
]);
},
describeLogGroups
(
params
:
DescribeLogGroupsRequest
)
{
const
theLogGroups
=
allLogGroups
.
filter
(
logGroupName
=>
logGroupName
.
startsWith
(
params
.
logGroupNamePrefix
??
''
))
.
slice
(
0
,
Math
.
max
(
params
.
limit
??
50
,
50
));
return
Promise
.
resolve
(
theLogGroups
);
},
}
as
any
}
query=
{
{}
as
any
}
onRunQuery=
{
()
=>
{}
}
onChange=
{
onChange
}
/>
);
const
initialAvailableGroups
=
allLogGroups
.
slice
(
0
,
50
)
.
map
(
logGroupName
=>
({
value
:
logGroupName
,
label
:
logGroupName
}));
wrapper
.
setState
({
availableLogGroups
:
initialAvailableGroups
,
});
await
wrapper
.
instance
().
onLogGroupSearch
(
'Water'
,
'default'
,
{
action
:
'input-change'
});
let
nextAvailableGroups
=
(
wrapper
.
state
(
'availableLogGroups'
)
as
Array
<
SelectableValue
<
string
>>
).
map
(
logGroup
=>
logGroup
.
value
);
expect
(
nextAvailableGroups
).
toEqual
(
initialAvailableGroups
.
map
(
logGroup
=>
logGroup
.
value
).
concat
([
'WaterGroup'
,
'WaterGroup2'
,
'WaterGroup3'
])
);
await
wrapper
.
instance
().
onLogGroupSearch
(
'Velv'
,
'default'
,
{
action
:
'input-change'
});
nextAvailableGroups
=
(
wrapper
.
state
(
'availableLogGroups'
)
as
Array
<
SelectableValue
<
string
>>
).
map
(
logGroup
=>
logGroup
.
value
);
expect
(
nextAvailableGroups
).
toEqual
(
initialAvailableGroups
.
map
(
logGroup
=>
logGroup
.
value
)
.
concat
([
'WaterGroup'
,
'WaterGroup2'
,
'WaterGroup3'
,
'VelvetGroup'
,
'VelvetGroup2'
,
'VelvetGroup3'
])
);
});
});
public/app/plugins/datasource/cloudwatch/components/LogsQueryField.tsx
View file @
0e8638ec
...
...
@@ -2,6 +2,7 @@
import
React
,
{
ReactNode
}
from
'react'
;
import
intersectionBy
from
'lodash/intersectionBy'
;
import
debounce
from
'lodash/debounce'
;
import
unionBy
from
'lodash/unionBy'
;
import
{
QueryField
,
...
...
@@ -31,6 +32,7 @@ import { ExploreId } from 'app/types';
import
{
dispatch
}
from
'app/store/store'
;
import
{
changeModeAction
}
from
'app/features/explore/state/actionTypes'
;
import
{
appEvents
}
from
'app/core/core'
;
import
{
InputActionMeta
}
from
'@grafana/ui/src/components/Select/types'
;
export
interface
CloudWatchLogsQueryFieldProps
extends
ExploreQueryFieldProps
<
CloudWatchDatasource
,
CloudWatchQuery
>
{
absoluteRange
:
AbsoluteTimeRange
;
...
...
@@ -104,11 +106,12 @@ export class CloudWatchLogsQueryField extends React.PureComponent<CloudWatchLogs
];
}
fetchLogGroupOptions
=
async
(
region
:
string
)
=>
{
fetchLogGroupOptions
=
async
(
region
:
string
,
logGroupNamePrefix
?:
string
)
=>
{
try
{
const
logGroups
:
string
[]
=
await
this
.
props
.
datasource
.
describeLogGroups
({
refId
:
this
.
props
.
query
.
refId
,
region
,
logGroupNamePrefix
,
});
return
logGroups
.
map
(
logGroup
=>
({
...
...
@@ -121,6 +124,30 @@ export class CloudWatchLogsQueryField extends React.PureComponent<CloudWatchLogs
}
};
onLogGroupSearch
=
(
searchTerm
:
string
,
region
:
string
,
actionMeta
:
InputActionMeta
)
=>
{
if
(
actionMeta
.
action
!==
'input-change'
)
{
return
Promise
.
resolve
();
}
this
.
setState
({
loadingLogGroups
:
true
,
});
return
this
.
fetchLogGroupOptions
(
region
,
searchTerm
)
.
then
(
matchingLogGroups
=>
{
this
.
setState
(
state
=>
({
availableLogGroups
:
unionBy
(
state
.
availableLogGroups
,
matchingLogGroups
,
'value'
),
}));
})
.
finally
(()
=>
{
this
.
setState
({
loadingLogGroups
:
false
,
});
});
};
onLogGroupSearchDebounced
=
debounce
(
this
.
onLogGroupSearch
,
300
);
componentWillMount
=
()
=>
{
const
{
datasource
,
query
,
onChange
}
=
this
.
props
;
...
...
@@ -355,6 +382,9 @@ export class CloudWatchLogsQueryField extends React.PureComponent<CloudWatchLogs
noOptionsMessage=
"No log groups available"
isLoading=
{
loadingLogGroups
}
onOpenMenu=
{
this
.
onOpenLogGroupMenu
}
onInputChange=
{
(
value
,
actionMeta
)
=>
{
this
.
onLogGroupSearchDebounced
(
value
,
selectedRegion
.
value
??
'default'
,
actionMeta
);
}
}
/>
}
/>
...
...
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