Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Open sidebar
gstlal-visualisation
ligo-scald
Commits
ea40ce87
Commit
ea40ce87
authored
Aug 12, 2019
by
Patrick Godwin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add ability to serve multiple dashboard pages, overhaul config file layout
parent
2419730c
Pipeline
#74694
passed with stages
in 1 minute and 41 seconds
Changes
5
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
94 additions
and
50 deletions
+94
-50
ligo/scald/serve.py
ligo/scald/serve.py
+42
-33
ligo/scald/utils.py
ligo/scald/utils.py
+7
-7
static/scald.js
static/scald.js
+2
-0
templates/navbar.html
templates/navbar.html
+16
-1
templates/scripts.js
templates/scripts.js
+27
-9
No files found.
ligo/scald/serve.py
View file @
ea40ce87
...
...
@@ -72,54 +72,62 @@ def static(file_):
@
app
.
route
(
"/"
)
def
index
():
@
app
.
route
(
"/<page>"
)
def
dashboard
(
page
=
'index'
):
"""Route to serve a dashboard.
"""
config
=
dict
(
app
.
config
)
static_dir
=
'../'
if
config
[
'use_cgi'
]
else
''
if
page
!=
'index'
:
static_dir
+=
'../'
if
'type'
in
bottle
.
request
.
query
:
config
[
'
dashboard'
][
'type'
]
=
bottle
.
request
.
query
[
'type'
]
config
[
'
pages'
][
page
][
'type'
]
=
bottle
.
request
.
query
[
'type'
]
else
:
config
[
'
dashboard'
][
'type'
]
=
'online'
if
config
[
'
dashboard'
][
'type'
]
==
'online'
:
config
[
'
pages'
][
page
][
'type'
]
=
'online'
if
config
[
'
pages'
][
page
][
'type'
]
==
'online'
:
if
'lookback'
in
bottle
.
request
.
query
:
config
[
'dashboard'
][
'lookback'
]
=
int
(
bottle
.
request
.
query
[
'lookback'
])
elif
'duration'
in
config
[
'dashboard'
]:
### backwards compatibility
config
[
'dashboard'
][
'lookback'
]
=
config
[
'dashboard'
][
'duration'
]
config
[
'pages'
][
page
][
'lookback'
]
=
int
(
bottle
.
request
.
query
[
'lookback'
])
if
'delay'
in
bottle
.
request
.
query
:
config
[
'dashboard'
][
'delay'
]
=
int
(
bottle
.
request
.
query
[
'delay'
])
elif
'gps'
in
config
[
'dashboard'
]
and
config
[
'dashboard'
][
'gps'
]
<
0
:
### backwards compatibility
config
[
'dashboard'
][
'delay'
]
=
-
config
[
'dashboard'
][
'gps'
]
config
[
'pages'
][
page
][
'delay'
]
=
int
(
bottle
.
request
.
query
[
'delay'
])
else
:
config
[
'
dashboard'
][
'start'
]
=
int
(
bottle
.
request
.
query
[
'start'
])
config
[
'
dashboard'
][
'end'
]
=
int
(
bottle
.
request
.
query
[
'end'
])
config
[
'
pages'
][
page
][
'start'
]
=
int
(
bottle
.
request
.
query
[
'start'
])
config
[
'
pages'
][
page
][
'end'
]
=
int
(
bottle
.
request
.
query
[
'end'
])
### find out whether query is for realtime or historical data
if
config
[
'
dashboard'
][
'type'
]
==
'online'
:
stop
=
int
(
aggregator
.
now
()
-
config
[
'
dashboard'
][
'delay'
])
start
=
stop
-
config
[
'
dashboard'
][
'lookback'
]
if
config
[
'
pages'
][
page
][
'type'
]
==
'online'
:
stop
=
int
(
aggregator
.
now
()
-
config
[
'
pages'
][
page
][
'delay'
])
start
=
stop
-
config
[
'
pages'
][
page
][
'lookback'
]
refresh
=
2000
else
:
start
=
config
[
'
dashboard'
][
'start'
]
stop
=
config
[
'dashboard'
][
'end'
]
start
=
config
[
'
pages'
][
page
][
'start'
]
stop
=
config
[
'dashboard'
][
page
][
'end'
]
refresh
=
-
1
### fill in plot section for page with plot/schema info
plots
=
config
[
'pages'
][
page
][
'plots'
]
for
plot
in
plots
:
plot_name
=
plot
[
'plot'
]
plot
.
update
(
config
[
'plots'
][
plot_name
])
plot
[
'schema'
]
=
config
[
'schemas'
][
plot
[
'schema'
]]
### generate html
yield
bottle
.
template
(
'dashboard.html'
,
static_dir
=
static_dir
,
script_name
=
config
[
'script_name'
],
plots
=
config
[
'plots'
],
plot_defaults
=
config
[
'plotly'
]
if
'plotly'
in
config
else
{},
plots
=
plots
,
start
=
start
,
stop
=
stop
,
refresh
=
refresh
,
lookback
=
config
[
'dashboard'
][
'lookback'
],
delay
=
config
[
'dashboard'
][
'delay'
],
query_type
=
config
[
'dashboard'
][
'type'
],
dashboard_config
=
config
[
'dashboard'
],
lookback
=
config
[
'pages'
][
page
][
'lookback'
],
delay
=
config
[
'pages'
][
page
][
'delay'
],
query_type
=
config
[
'pages'
][
page
][
'type'
],
dashboard_config
=
config
[
'navbar'
],
page_config
=
config
[
'pages'
],
current_page
=
page
,
)
...
...
@@ -309,9 +317,9 @@ def serve_latest(measurement, start, end):
"""
query
=
parse_query
(
bottle
.
request
.
query
)
tag
=
app
.
config
[
'
measurement
s'
][
measurement
][
'tag'
]
default_value
=
app
.
config
[
'
measurement
s'
][
measurement
][
'default'
]
transform
=
app
.
config
[
'
measurement
s'
][
measurement
][
'transform'
]
tag
=
app
.
config
[
'
schema
s'
][
measurement
][
'tag'
]
default_value
=
app
.
config
[
'
schema
s'
][
measurement
][
'default'
]
transform
=
app
.
config
[
'
schema
s'
][
measurement
][
'transform'
]
y
=
[]
### query for timeseries
...
...
@@ -391,14 +399,15 @@ def serve_nagios(check):
dt
=
utils
.
duration_to_dt
(
duration
)
### data settings
measurement
=
nagios_config
[
'measurement'
]
column
=
nagios_config
[
'column'
]
tags
=
nagios_config
[
'tags'
]
if
'tags'
in
nagios_config
else
[]
aggregate
=
nagios_config
[
'aggregate'
]
schema
=
app
.
config
[
'schemas'
][
check
]
measurement
=
schema
[
'measurement'
]
column
=
schema
[
'column'
]
tags
=
schema
[
'tags'
]
if
'tags'
in
schema
else
[]
aggregate
=
schema
[
'aggregate'
]
### alert settings
alert_type
=
nagios_config
[
'alert_type'
]
alert_tags
=
utils
.
extract_alert_tags
(
nagios_config
[
'alert_settings'
]
)
alert_tags
=
utils
.
extract_alert_tags
(
schema
)
### alert tracking
alert_values
=
[]
...
...
@@ -428,13 +437,13 @@ def serve_nagios(check):
if
bad_status
:
if
alert_type
==
'heartbeat'
:
text_status
=
"{num_tags} {alert_tag} more than {lookback} seconds behind"
.
format
(
alert_tag
=
nagios_config
[
'alert_settings'
][
'tag_
type
'
],
alert_tag
=
nagios_config
[
'alert_settings'
][
'tag_
key
'
],
num_tags
=
bad_status
,
lookback
=
duration
,
)
elif
alert_type
==
'threshold'
:
text_status
=
"{num_tags} {alert_tag} above {column} threshold = {threshold} {units} from gps times: {start} - {end}"
.
format
(
alert_tag
=
nagios_config
[
'alert_settings'
][
'tag_
type
'
],
alert_tag
=
nagios_config
[
'alert_settings'
][
'tag_
key
'
],
threshold
=
nagios_config
[
'alert_settings'
][
'threshold'
],
units
=
nagios_config
[
'alert_settings'
][
'threshold_units'
],
num_tags
=
bad_status
,
...
...
@@ -448,7 +457,7 @@ def serve_nagios(check):
text_status
=
"OK: Max delay: {delay} seconds"
.
format
(
delay
=
max
(
alert_values
))
elif
alert_type
==
'threshold'
:
text_status
=
"OK: No {alert_tag}s above {column} threshold = {threshold} {units} from gps times: {start} - {end}"
.
format
(
alert_tag
=
nagios_config
[
'alert_settings'
][
'tag_
type
'
],
alert_tag
=
nagios_config
[
'alert_settings'
][
'tag_
key
'
],
threshold
=
nagios_config
[
'alert_settings'
][
'threshold'
],
units
=
nagios_config
[
'alert_settings'
][
'threshold_units'
],
column
=
measurement
,
...
...
ligo/scald/utils.py
View file @
ea40ce87
...
...
@@ -209,16 +209,16 @@ def status_to_nagios_response(text_status, bad_status):
}
def
extract_alert_tags
(
alert_settings
):
if
'tags'
in
alert_settings
:
return
alert_settings
[
'tags'
]
def
extract_alert_tags
(
schema
):
if
'tags'
in
schema
:
return
schema
[
'tags'
]
else
:
tag_type
=
alert_settings
[
'tag_
type
'
]
alert_tag_format
=
alert_settings
[
'tag_format'
]
tag_type
=
schema
[
'tag_
key
'
]
alert_tag_format
=
schema
[
'tag_format'
]
if
'digit'
in
alert_tag_format
:
num_digits
=
int
(
alert_tag_format
[
0
])
num_tags
=
int
(
alert_settings
[
'num_tags'
])
tag_start
=
int
(
alert_settings
[
'tag_start'
])
if
'tag_start'
in
alert_settings
else
0
num_tags
=
int
(
schema
[
'num_tags'
])
tag_start
=
int
(
schema
[
'tag_start'
])
if
'tag_start'
in
schema
else
0
return
[(
tag_type
,
str
(
tag_num
).
zfill
(
num_digits
))
for
tag_num
in
range
(
tag_start
,
tag_start
+
num_tags
)]
else
:
raise
ValueError
(
'{} tag format not recognized'
.
format
(
alert_tag_format
))
...
...
static/scald.js
View file @
ea40ce87
...
...
@@ -707,6 +707,7 @@ class MultiSchema extends _TimePlot{
this
.
stream
=
new
Stream2D
(
this
.
measurement
,
this
.
schema
,
this
.
segment
,
this
.
data_options
,
this
.
refresh_interval
,
this
.
update
,
this
.
delay
);
delete
this
.
url_params
;
delete
this
.
schema
.
dt
;
delete
this
.
schema
.
measurement
;
this
.
script_name
=
script_name
;
for
(
var
key
in
this
.
schema
)
{
// Set a custom base URL for each schema measurement
...
...
@@ -788,6 +789,7 @@ class MultiAxis extends _TimePlot{
this
.
stream
=
new
Stream2D
(
this
.
measurement
,
this
.
schema
,
this
.
segment
,
this
.
data_options
,
this
.
refresh_interval
,
this
.
update
,
this
.
delay
);
delete
this
.
url_params
;
delete
this
.
schema
.
dt
;
delete
this
.
schema
.
measurement
;
var
axis
=
1
;
for
(
var
key
in
this
.
schema
)
{
// Create the info for each yaxis supplied
...
...
templates/navbar.html
View file @
ea40ce87
...
...
@@ -14,6 +14,21 @@
<b-collapse
is-nav
id=
"nav_collapse"
>
<ul
class=
"navbar-nav mr-auto"
>
<!-- add pages -->
% if 'pages' in dashboard_config:
% if current_page != 'index':
% script_name = '../' + script_name
% end
% for page in pages:
% if page == 'index':
% url = script_name if script_name[-1] != '/' else script_name[:-1]
% else:
% url = script_name + page
% end
<li><a
class=
"nav-link mt-0"
href=
"{{ url }}"
>
{{ page_config[page]['title'] }}
</a></li>
% end
% end
<!-- add tabs -->
% for tab in tabs:
<li><a
class=
"nav-link mt-0"
href=
"{{ tab['url'] }}"
>
{{ tab['name'] }}
</a></li>
...
...
@@ -44,7 +59,7 @@
class =
"m-lg-2"
name=
"livecharts{{ plot['title'].replace(' ', '_').lower() }}"
href=
"#"
:checked=
{{
'
true
'
if
plot
['
v
alue
'
] =
=
'
checked
'
else
'
false
'
}}
:checked=
{{
'
true
'
if
plot
['
v
isible
']
else
'
false
'
}}
@
click=
"addItem(plots[{{ i }}])"
>
{{ plot['title'] }}
...
...
templates/scripts.js
View file @
ea40ce87
%
import
json
%
if
current_page
!=
'
index
'
:
%
script_name
=
'
../
'
+
script_name
%
end
<
script
>
document
.
body
.
onkeydown
=
function
(
e
)
{
if
(
e
.
keyCode
==
32
)
{
...
...
@@ -219,7 +223,7 @@
grid
.
type
=
plot
.
type
;
grid
.
i
=
idx
;
grid
.
divname
=
'
plot
'
+
idx
;
if
(
plot
.
v
alue
===
'
checked
'
)
{
if
(
plot
.
v
isible
)
{
if
(
!
(
'
y
'
in
grid
))
{
grid
.
y
=
this
.
ySpace
;
};
...
...
@@ -243,19 +247,33 @@
var
options
=
(
'
options
'
in
plot
)
?
plot
.
options
:
{};
var
segment
=
{
"
start
"
:
{{
start
}},
"
stop
"
:
{{
stop
}}
};
if
(
'
layout
'
in
this
.
plotDefaults
)
{
plotLayout
=
update_config_object
(
plotLayout
,
this
.
plotDefaults
[
'
layout
'
]);
}
if
(
'
data_options
'
in
this
.
plotDefaults
)
{
dataOptions
=
update_config_object
(
dataOptions
,
this
.
plotDefaults
[
'
data_options
'
]);
}
if
(
'
options
'
in
this
.
plotDefaults
)
{
options
=
update_config_object
(
options
,
this
.
plotDefaults
[
'
options
'
]);
if
(
'
default
'
in
this
.
plotDefaults
)
{
if
(
'
layout
'
in
this
.
plotDefaults
.
default
)
{
plotLayout
=
update_config_object
(
plotLayout
,
this
.
plotDefaults
[
'
default
'
][
'
layout
'
]);
}
if
(
'
data_options
'
in
this
.
plotDefaults
.
default
)
{
dataOptions
=
update_config_object
(
dataOptions
,
this
.
plotDefaults
[
'
default
'
][
'
data_options
'
]);
}
if
(
'
options
'
in
this
.
plotDefaults
.
default
)
{
options
=
update_config_object
(
options
,
this
.
plotDefaults
[
'
default
'
][
'
options
'
]);
}
}
if
(
plot
.
type
in
this
.
plotDefaults
)
{
if
(
'
layout
'
in
this
.
plotDefaults
[
plot
.
type
])
{
plotLayout
=
update_config_object
(
plotLayout
,
this
.
plotDefaults
[
plot
.
type
][
'
layout
'
]);
}
if
(
'
data_options
'
in
this
.
plotDefaults
[
plot
.
type
])
{
dataOptions
=
update_config_object
(
dataOptions
,
this
.
plotDefaults
[
plot
.
type
][
'
data_options
'
]);
}
if
(
'
options
'
in
this
.
plotDefaults
[
plot
.
type
])
{
options
=
update_config_object
(
options
,
this
.
plotDefaults
[
plot
.
type
][
'
options
'
]);
}
}
if
(
'
schema
'
in
plot
)
{
plot
.
schema
=
update_config_object
(
plot
.
schema
,
plot
.
settings
);
}
// create the plot
var
thisplot
=
new
(
plotFactory
.
get
(
plot
.
type
))(
grid
.
divname
,
// div name for the plot
plot
.
title
,
// plot title stored for regeneration
plot
.
measurement
,
// name of measurement to query
plot
.
schema
.
measurement
,
// name of measurement to query
plot
.
schema
,
// schema for retrieving data
'
{{ script_name }}
'
,
// script name (hack to deal with cgi/apache)
segment
,
// initial data segment
...
...
@@ -268,7 +286,7 @@
);
// populate plot and push
if
(
plot
.
v
alue
===
'
checked
'
)
{
if
(
plot
.
v
isible
)
{
thisplot
.
populate
();
}
this
.
plots
.
push
(
thisplot
);
...
...
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