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
9afb8b64
Unverified
Commit
9afb8b64
authored
Nov 27, 2018
by
David
Committed by
GitHub
Nov 27, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #14176 from grafana/davkal/explore-logging-level-filter
Explore: Filter logs by log level
parents
15637af1
ae5ec441
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
74 additions
and
31 deletions
+74
-31
public/app/core/logs_model.ts
+28
-9
public/app/features/explore/Graph.tsx
+13
-9
public/app/features/explore/Logs.tsx
+14
-5
public/app/plugins/datasource/logging/result_transformer.test.ts
+10
-4
public/app/plugins/datasource/logging/result_transformer.ts
+3
-3
public/sass/pages/_explore.scss
+6
-1
No files found.
public/app/core/logs_model.ts
View file @
9afb8b64
...
@@ -3,25 +3,26 @@ import { TimeSeries } from 'app/core/core';
...
@@ -3,25 +3,26 @@ import { TimeSeries } from 'app/core/core';
import
colors
from
'app/core/utils/colors'
;
import
colors
from
'app/core/utils/colors'
;
export
enum
LogLevel
{
export
enum
LogLevel
{
crit
=
'crit'
,
crit
=
'critical'
,
warn
=
'warn'
,
critical
=
'critical'
,
warn
=
'warning'
,
warning
=
'warning'
,
err
=
'error'
,
err
=
'error'
,
error
=
'error'
,
error
=
'error'
,
info
=
'info'
,
info
=
'info'
,
debug
=
'debug'
,
debug
=
'debug'
,
trace
=
'trace'
,
trace
=
'trace'
,
none
=
'none
'
,
unkown
=
'unkown
'
,
}
}
export
const
LogLevelColor
=
{
export
const
LogLevelColor
=
{
[
LogLevel
.
crit
]:
colors
[
7
],
[
LogLevel
.
critical
]:
colors
[
7
],
[
LogLevel
.
warn
]:
colors
[
1
],
[
LogLevel
.
warning
]:
colors
[
1
],
[
LogLevel
.
err
]:
colors
[
4
],
[
LogLevel
.
error
]:
colors
[
4
],
[
LogLevel
.
error
]:
colors
[
4
],
[
LogLevel
.
info
]:
colors
[
0
],
[
LogLevel
.
info
]:
colors
[
0
],
[
LogLevel
.
debug
]:
colors
[
3
],
[
LogLevel
.
debug
]:
colors
[
5
],
[
LogLevel
.
trace
]:
colors
[
3
],
[
LogLevel
.
trace
]:
colors
[
2
],
[
LogLevel
.
none
]:
'#eee
'
,
[
LogLevel
.
unkown
]:
'#ddd
'
,
};
};
export
interface
LogSearchMatch
{
export
interface
LogSearchMatch
{
...
@@ -119,6 +120,24 @@ export function dedupLogRows(logs: LogsModel, strategy: LogsDedupStrategy): Logs
...
@@ -119,6 +120,24 @@ export function dedupLogRows(logs: LogsModel, strategy: LogsDedupStrategy): Logs
};
};
}
}
export
function
filterLogLevels
(
logs
:
LogsModel
,
hiddenLogLevels
:
Set
<
LogLevel
>
):
LogsModel
{
if
(
hiddenLogLevels
.
size
===
0
)
{
return
logs
;
}
const
filteredRows
=
logs
.
rows
.
reduce
((
result
:
LogRow
[],
row
:
LogRow
,
index
,
list
)
=>
{
if
(
!
hiddenLogLevels
.
has
(
row
.
logLevel
))
{
result
.
push
(
row
);
}
return
result
;
},
[]);
return
{
...
logs
,
rows
:
filteredRows
,
};
}
export
function
makeSeriesForLogs
(
rows
:
LogRow
[],
intervalMs
:
number
):
TimeSeries
[]
{
export
function
makeSeriesForLogs
(
rows
:
LogRow
[],
intervalMs
:
number
):
TimeSeries
[]
{
// Graph time series by log level
// Graph time series by log level
const
seriesByLevel
=
{};
const
seriesByLevel
=
{};
...
...
public/app/features/explore/Graph.tsx
View file @
9afb8b64
...
@@ -83,6 +83,7 @@ interface GraphProps {
...
@@ -83,6 +83,7 @@ interface GraphProps {
size
?:
{
width
:
number
;
height
:
number
};
size
?:
{
width
:
number
;
height
:
number
};
userOptions
?:
any
;
userOptions
?:
any
;
onChangeTime
?:
(
range
:
RawTimeRange
)
=>
void
;
onChangeTime
?:
(
range
:
RawTimeRange
)
=>
void
;
onToggleSeries
?:
(
alias
:
string
,
hiddenSeries
:
Set
<
string
>
)
=>
void
;
}
}
interface
GraphState
{
interface
GraphState
{
...
@@ -178,27 +179,30 @@ export class Graph extends PureComponent<GraphProps, GraphState> {
...
@@ -178,27 +179,30 @@ export class Graph extends PureComponent<GraphProps, GraphState> {
onToggleSeries
=
(
series
:
TimeSeries
,
exclusive
:
boolean
)
=>
{
onToggleSeries
=
(
series
:
TimeSeries
,
exclusive
:
boolean
)
=>
{
this
.
setState
((
state
,
props
)
=>
{
this
.
setState
((
state
,
props
)
=>
{
const
{
data
}
=
props
;
const
{
data
,
onToggleSeries
}
=
props
;
const
{
hiddenSeries
}
=
state
;
const
{
hiddenSeries
}
=
state
;
const
hidden
=
hiddenSeries
.
has
(
series
.
alias
);
// Deduplicate series as visibility tracks the alias property
// Deduplicate series as visibility tracks the alias property
const
oneSeriesVisible
=
hiddenSeries
.
size
===
new
Set
(
data
.
map
(
d
=>
d
.
alias
)).
size
-
1
;
const
oneSeriesVisible
=
hiddenSeries
.
size
===
new
Set
(
data
.
map
(
d
=>
d
.
alias
)).
size
-
1
;
let
nextHiddenSeries
=
new
Set
();
if
(
exclusive
)
{
if
(
exclusive
)
{
return
{
if
(
hiddenSeries
.
has
(
series
.
alias
)
||
!
oneSeriesVisible
)
{
hiddenSeries
:
nextHiddenSeries
=
new
Set
(
data
.
filter
(
d
=>
d
.
alias
!==
series
.
alias
).
map
(
d
=>
d
.
alias
));
!
hidden
&&
oneSeriesVisible
?
new
Set
()
:
new
Set
(
data
.
filter
(
d
=>
d
.
alias
!==
series
.
alias
).
map
(
d
=>
d
.
alias
)),
};
}
}
}
else
{
// Prune hidden series no longer part of those available from the most recent query
// Prune hidden series no longer part of those available from the most recent query
const
availableSeries
=
new
Set
(
data
.
map
(
d
=>
d
.
alias
));
const
availableSeries
=
new
Set
(
data
.
map
(
d
=>
d
.
alias
));
const
nextHiddenSeries
=
intersect
(
new
Set
(
hiddenSeries
),
availableSeries
);
nextHiddenSeries
=
intersect
(
new
Set
(
hiddenSeries
),
availableSeries
);
if
(
nextHiddenSeries
.
has
(
series
.
alias
))
{
if
(
nextHiddenSeries
.
has
(
series
.
alias
))
{
nextHiddenSeries
.
delete
(
series
.
alias
);
nextHiddenSeries
.
delete
(
series
.
alias
);
}
else
{
}
else
{
nextHiddenSeries
.
add
(
series
.
alias
);
nextHiddenSeries
.
add
(
series
.
alias
);
}
}
}
if
(
onToggleSeries
)
{
onToggleSeries
(
series
.
alias
,
nextHiddenSeries
);
}
return
{
return
{
hiddenSeries
:
nextHiddenSeries
,
hiddenSeries
:
nextHiddenSeries
,
};
};
...
...
public/app/features/explore/Logs.tsx
View file @
9afb8b64
...
@@ -2,7 +2,7 @@ import React, { Fragment, PureComponent } from 'react';
...
@@ -2,7 +2,7 @@ import React, { Fragment, PureComponent } from 'react';
import
Highlighter
from
'react-highlight-words'
;
import
Highlighter
from
'react-highlight-words'
;
import
{
RawTimeRange
}
from
'app/types/series'
;
import
{
RawTimeRange
}
from
'app/types/series'
;
import
{
LogsDedupStrategy
,
LogsModel
,
dedupLogRows
}
from
'app/core/logs_model'
;
import
{
LogsDedupStrategy
,
LogsModel
,
dedupLogRows
,
filterLogLevels
,
LogLevel
}
from
'app/core/logs_model'
;
import
{
findHighlightChunksInText
}
from
'app/core/utils/text'
;
import
{
findHighlightChunksInText
}
from
'app/core/utils/text'
;
import
{
Switch
}
from
'app/core/components/Switch/Switch'
;
import
{
Switch
}
from
'app/core/components/Switch/Switch'
;
...
@@ -33,6 +33,7 @@ interface LogsProps {
...
@@ -33,6 +33,7 @@ interface LogsProps {
interface
LogsState
{
interface
LogsState
{
dedup
:
LogsDedupStrategy
;
dedup
:
LogsDedupStrategy
;
hiddenLogLevels
:
Set
<
LogLevel
>
;
showLabels
:
boolean
;
showLabels
:
boolean
;
showLocalTime
:
boolean
;
showLocalTime
:
boolean
;
showUtc
:
boolean
;
showUtc
:
boolean
;
...
@@ -41,6 +42,7 @@ interface LogsState {
...
@@ -41,6 +42,7 @@ interface LogsState {
export
default
class
Logs
extends
PureComponent
<
LogsProps
,
LogsState
>
{
export
default
class
Logs
extends
PureComponent
<
LogsProps
,
LogsState
>
{
state
=
{
state
=
{
dedup
:
LogsDedupStrategy
.
none
,
dedup
:
LogsDedupStrategy
.
none
,
hiddenLogLevels
:
new
Set
(),
showLabels
:
true
,
showLabels
:
true
,
showLocalTime
:
true
,
showLocalTime
:
true
,
showUtc
:
false
,
showUtc
:
false
,
...
@@ -76,11 +78,17 @@ export default class Logs extends PureComponent<LogsProps, LogsState> {
...
@@ -76,11 +78,17 @@ export default class Logs extends PureComponent<LogsProps, LogsState> {
});
});
};
};
onToggleLogLevel
=
(
rawLevel
:
string
,
hiddenRawLevels
:
Set
<
string
>
)
=>
{
const
hiddenLogLevels
:
Set
<
LogLevel
>
=
new
Set
(
Array
.
from
(
hiddenRawLevels
).
map
(
level
=>
LogLevel
[
level
]));
this
.
setState
({
hiddenLogLevels
});
};
render
()
{
render
()
{
const
{
className
=
''
,
data
,
loading
=
false
,
position
,
range
}
=
this
.
props
;
const
{
className
=
''
,
data
,
loading
=
false
,
position
,
range
}
=
this
.
props
;
const
{
dedup
,
showLabels
,
showLocalTime
,
showUtc
}
=
this
.
state
;
const
{
dedup
,
hiddenLogLevels
,
showLabels
,
showLocalTime
,
showUtc
}
=
this
.
state
;
const
hasData
=
data
&&
data
.
rows
&&
data
.
rows
.
length
>
0
;
const
hasData
=
data
&&
data
.
rows
&&
data
.
rows
.
length
>
0
;
const
dedupedData
=
dedupLogRows
(
data
,
dedup
);
const
filteredData
=
filterLogLevels
(
data
,
hiddenLogLevels
);
const
dedupedData
=
dedupLogRows
(
filteredData
,
dedup
);
const
dedupCount
=
dedupedData
.
rows
.
reduce
((
sum
,
row
)
=>
sum
+
row
.
duplicates
,
0
);
const
dedupCount
=
dedupedData
.
rows
.
reduce
((
sum
,
row
)
=>
sum
+
row
.
duplicates
,
0
);
const
meta
=
[...
data
.
meta
];
const
meta
=
[...
data
.
meta
];
if
(
dedup
!==
LogsDedupStrategy
.
none
)
{
if
(
dedup
!==
LogsDedupStrategy
.
none
)
{
...
@@ -113,6 +121,7 @@ export default class Logs extends PureComponent<LogsProps, LogsState> {
...
@@ -113,6 +121,7 @@ export default class Logs extends PureComponent<LogsProps, LogsState> {
range=
{
range
}
range=
{
range
}
id=
{
`explore-logs-graph-${position}`
}
id=
{
`explore-logs-graph-${position}`
}
onChangeTime=
{
this
.
props
.
onChangeTime
}
onChangeTime=
{
this
.
props
.
onChangeTime
}
onToggleSeries=
{
this
.
onToggleLogLevel
}
userOptions=
{
graphOptions
}
userOptions=
{
graphOptions
}
/>
/>
</
div
>
</
div
>
...
@@ -163,11 +172,11 @@ export default class Logs extends PureComponent<LogsProps, LogsState> {
...
@@ -163,11 +172,11 @@ export default class Logs extends PureComponent<LogsProps, LogsState> {
<
div
className=
"logs-entries"
style=
{
logEntriesStyle
}
>
<
div
className=
"logs-entries"
style=
{
logEntriesStyle
}
>
{
hasData
&&
{
hasData
&&
dedupedData
.
rows
.
map
(
row
=>
(
dedupedData
.
rows
.
map
(
row
=>
(
<
Fragment
key=
{
row
.
key
}
>
<
Fragment
key=
{
row
.
key
+
row
.
duplicates
}
>
<
div
className=
{
row
.
logLevel
?
`logs-row-level logs-row-level-${row.logLevel}`
:
''
}
>
<
div
className=
{
row
.
logLevel
?
`logs-row-level logs-row-level-${row.logLevel}`
:
''
}
>
{
row
.
duplicates
>
0
&&
(
{
row
.
duplicates
>
0
&&
(
<
div
className=
"logs-row-level__duplicates"
title=
{
`${row.duplicates} duplicates`
}
>
<
div
className=
"logs-row-level__duplicates"
title=
{
`${row.duplicates} duplicates`
}
>
{
Array
.
apply
(
null
,
{
length
:
row
.
duplicates
}).
map
(
index
=>
(
{
Array
.
apply
(
null
,
{
length
:
row
.
duplicates
}).
map
(
(
bogus
,
index
)
=>
(
<
div
className=
"logs-row-level__duplicate"
key=
{
`${index}`
}
/>
<
div
className=
"logs-row-level__duplicate"
key=
{
`${index}`
}
/>
))
}
))
}
</
div
>
</
div
>
...
...
public/app/plugins/datasource/logging/result_transformer.test.ts
View file @
9afb8b64
...
@@ -11,11 +11,17 @@ import {
...
@@ -11,11 +11,17 @@ import {
describe
(
'getLoglevel()'
,
()
=>
{
describe
(
'getLoglevel()'
,
()
=>
{
it
(
'returns no log level on empty line'
,
()
=>
{
it
(
'returns no log level on empty line'
,
()
=>
{
expect
(
getLogLevel
(
''
)).
toBe
(
LogLevel
.
none
);
expect
(
getLogLevel
(
''
)).
toBe
(
LogLevel
.
unkown
);
});
});
it
(
'returns no log level on when level is part of a word'
,
()
=>
{
it
(
'returns no log level on when level is part of a word'
,
()
=>
{
expect
(
getLogLevel
(
'this is a warning'
)).
toBe
(
LogLevel
.
none
);
expect
(
getLogLevel
(
'this is information'
)).
toBe
(
LogLevel
.
unkown
);
});
it
(
'returns same log level for long and short version'
,
()
=>
{
expect
(
getLogLevel
(
'[Warn]'
)).
toBe
(
LogLevel
.
warning
);
expect
(
getLogLevel
(
'[Warning]'
)).
toBe
(
LogLevel
.
warning
);
expect
(
getLogLevel
(
'[Warn]'
)).
toBe
(
'warning'
);
});
});
it
(
'returns log level on line contains a log level'
,
()
=>
{
it
(
'returns log level on line contains a log level'
,
()
=>
{
...
@@ -102,7 +108,7 @@ describe('mergeStreamsToLogs()', () => {
...
@@ -102,7 +108,7 @@ describe('mergeStreamsToLogs()', () => {
entry
:
'WARN boooo'
,
entry
:
'WARN boooo'
,
labels
:
'{foo="bar"}'
,
labels
:
'{foo="bar"}'
,
key
:
'EK1970-01-01T00:00:00Z{foo="bar"}'
,
key
:
'EK1970-01-01T00:00:00Z{foo="bar"}'
,
logLevel
:
'warn'
,
logLevel
:
'warn
ing
'
,
uniqueLabels
:
''
,
uniqueLabels
:
''
,
},
},
]);
]);
...
@@ -141,7 +147,7 @@ describe('mergeStreamsToLogs()', () => {
...
@@ -141,7 +147,7 @@ describe('mergeStreamsToLogs()', () => {
{
{
entry
:
'WARN boooo'
,
entry
:
'WARN boooo'
,
labels
:
'{foo="bar", baz="1"}'
,
labels
:
'{foo="bar", baz="1"}'
,
logLevel
:
'warn'
,
logLevel
:
'warn
ing
'
,
uniqueLabels
:
'{baz="1"}'
,
uniqueLabels
:
'{baz="1"}'
,
},
},
{
{
...
...
public/app/plugins/datasource/logging/result_transformer.ts
View file @
9afb8b64
...
@@ -14,13 +14,13 @@ import { DEFAULT_LIMIT } from './datasource';
...
@@ -14,13 +14,13 @@ import { DEFAULT_LIMIT } from './datasource';
/**
/**
* Returns the log level of a log line.
* Returns the log level of a log line.
* Parse the line for level words. If no level is found, it returns `LogLevel.
none
`.
* Parse the line for level words. If no level is found, it returns `LogLevel.
unknown
`.
*
*
* Example: `getLogLevel('WARN 1999-12-31 this is great') // LogLevel.warn`
* Example: `getLogLevel('WARN 1999-12-31 this is great') // LogLevel.warn`
*/
*/
export
function
getLogLevel
(
line
:
string
):
LogLevel
{
export
function
getLogLevel
(
line
:
string
):
LogLevel
{
if
(
!
line
)
{
if
(
!
line
)
{
return
LogLevel
.
none
;
return
LogLevel
.
unkown
;
}
}
let
level
:
LogLevel
;
let
level
:
LogLevel
;
Object
.
keys
(
LogLevel
).
forEach
(
key
=>
{
Object
.
keys
(
LogLevel
).
forEach
(
key
=>
{
...
@@ -32,7 +32,7 @@ export function getLogLevel(line: string): LogLevel {
...
@@ -32,7 +32,7 @@ export function getLogLevel(line: string): LogLevel {
}
}
});
});
if
(
!
level
)
{
if
(
!
level
)
{
level
=
LogLevel
.
none
;
level
=
LogLevel
.
unkown
;
}
}
return
level
;
return
level
;
}
}
...
...
public/sass/pages/_explore.scss
View file @
9afb8b64
...
@@ -305,6 +305,7 @@
...
@@ -305,6 +305,7 @@
opacity
:
0
.8
;
opacity
:
0
.8
;
}
}
.logs-row-level-critical
,
.logs-row-level-crit
{
.logs-row-level-crit
{
background-color
:
#705da0
;
background-color
:
#705da0
;
}
}
...
@@ -314,6 +315,7 @@
...
@@ -314,6 +315,7 @@
background-color
:
#e24d42
;
background-color
:
#e24d42
;
}
}
.logs-row-level-warning
,
.logs-row-level-warn
{
.logs-row-level-warn
{
background-color
:
#eab839
;
background-color
:
#eab839
;
}
}
...
@@ -322,11 +324,14 @@
...
@@ -322,11 +324,14 @@
background-color
:
#7eb26d
;
background-color
:
#7eb26d
;
}
}
.logs-row-level-trace
,
.logs-row-level-debug
{
.logs-row-level-debug
{
background-color
:
#1f78c1
;
background-color
:
#1f78c1
;
}
}
.logs-row-level-trace
{
background-color
:
#6ed0e0
;
}
.logs-row-level__duplicates
{
.logs-row-level__duplicates
{
position
:
absolute
;
position
:
absolute
;
width
:
9px
;
width
:
9px
;
...
...
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