Skip to content

Commit

Permalink
support names in graph_source custom variable
Browse files Browse the repository at this point in the history
  • Loading branch information
sni committed Oct 24, 2024
1 parent 09c0f7d commit f978206
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 16 deletions.
5 changes: 5 additions & 0 deletions lib/Thruk/Utils.pm
Original file line number Diff line number Diff line change
Expand Up @@ -818,6 +818,11 @@ sub get_custom_vars {
$add_action_menu = 1 unless defined $add_action_menu;

my %hash;
if($data->{'custom_variables'}) {
for my $key (keys %{$data->{'custom_variables'}}) {
$hash{$key} = $data->{'custom_variables'}->{$key};
}
}

if( defined $data
and defined $data->{$prefix.'custom_variable_names'}
Expand Down
1 change: 1 addition & 0 deletions root/thruk/javascript/thruk-3.18.js
Original file line number Diff line number Diff line change
Expand Up @@ -9949,6 +9949,7 @@ function set_histou_img(start, end, id, source, skip_hash) {
//add timerange to iconlink, so the target graph matches the preview
jQuery("#histou_graph_link").attr("href", url_prefix + "#" + histou_url + getParamFrom + getParamTo);

jQuery('#histou_graph_pane').css('display', '');
jQuery('#pnpwaitimg').css('display', 'block');

jQuery('#histou_iframe').one("load", function() {
Expand Down
29 changes: 25 additions & 4 deletions script/pnp_export.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
# pnp_export.sh <hostname> <servicedescription> <imgwidth> <imgheight> <start> <end> <pnpurl> <tempfile> [<source>]


PNP_WGET="wget -q"
PNP_GET="curl -nsS"

if [ "$OMD_ROOT" != "" ]; then
PNP_ETC=~/etc/pnp4nagios
Expand All @@ -32,17 +32,38 @@ if [ "$PNPURL" != "" ]; then
PNPURL="$PNP_URL_PREFIX$PNPURL"
fi

export REQUEST_URI="image?host=$HOST&srv=$SERVICE&view=1&source=$SOURCE&graph_width=$WIDTH&graph_height=$HEIGHT&start=$START&end=$END"
export JSON_URI="json?host=$HOST&srv=$SERVICE"

if [ "${PNPURL:0:5}" != "http:" -a "${PNPURL:0:6}" != "https:" ]; then
# export graph with local php
[ "$PNP_ETC" = "" ] && exit 0
[ "$PNP_INDEX" = "" ] && exit 0
[ -d "$PNP_ETC/." ] || exit 0
cd $PNP_ETC

# translate non-numeric source
if ! [[ $SOURCE =~ ^[0-9]+$ ]]; then
SOURCENR=$(php $PNP_INDEX "$JSON_URI" | perl -MCpanel::JSON::XS -ne '$data = decode_json($_); my @matches = grep { $data->[$_]->{"ds_name"} eq "'$SOURCE'" } 0..$#$data; print $matches[0]')
if [ "$SOURCENR" != "" ]; then
SOURCE=$SOURCENR
fi
fi

export REQUEST_URI="image?host=$HOST&srv=$SERVICE&view=1&source=$SOURCE&graph_width=$WIDTH&graph_height=$HEIGHT&start=$START&end=$END"
php $PNP_INDEX "$REQUEST_URI" > $TEMPFILE 2>/dev/null
else
# try to fetch image with wget
$PNP_WGET -O $TEMPFILE "$PNPURL/$REQUEST_URI"
# translate non-numeric source
if ! [[ $SOURCE =~ ^[0-9]+$ ]]; then
SOURCENR=$($PNP_GET "$PNPURL/$JSON_URI" | perl -MCpanel::JSON::XS -ne '$data = decode_json($_); my @matches = grep { $data->[$_]->{"ds_name"} eq "'$SOURCE'" } 0..$#$data; print $matches[0]')
if [ "$SOURCENR" != "" ]; then
SOURCE=$SOURCENR
fi
fi

export REQUEST_URI="image?host=$HOST&srv=$SERVICE&view=1&source=$SOURCE&graph_width=$WIDTH&graph_height=$HEIGHT&start=$START&end=$END"

# try to fetch image with curl
$PNP_GET "$PNPURL/$REQUEST_URI" > $TEMPFILE
fi

exit 0
54 changes: 54 additions & 0 deletions script/puppeteer.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,60 @@ if (!process.env['XDG_CACHE_HOME']) { process.env['XDG_CACHE_HOME'] = tempDir;
}
//console.debug("response:", response.url(), response.status());
})

// extract panelId parameter from url
let urlObj = new URL(url);
let panelId = urlObj.searchParams.get('panelId');
let hostname = urlObj.searchParams.get('host');
let service = urlObj.searchParams.get('service');
if(panelId && !panelId.match(/^[0-9]+$/)) {
var random = Number(Math.random() * 100000).toFixed(0);
var source_url = url.replace(/\/grafana\/(d|dashboard|dashboard-solo)\/script\/histou\.js\?/, '/histou/index.php?_='+random+'&').replace('&disablePanelTitle', '');
if(source_url.match("/histou/index.php")) {
await page.goto(source_url);

let data = await page.content();
data = data.replace(/^[\s\S]*<br>\{/, '{');
data = data.replace(/<br><\/pre>.*/, '');
data = data.replace(/\n/g, '');
eval('data = '+data+";");
data.rows.forEach(function(row, i) {
row.panels.forEach(function(panel, j) {
var title = panel.title;
title = title.replace(hostname+' ', '');
title = title.replace(service+' ', '');
title = title.replace(/^check_\S+ /, '');
if(panel.id==panelId || title == panelId) {
urlObj.searchParams.set('panelId', panel.id);
url = urlObj.toString();
}
});
});
} else {
// extract panels from plain grafana dashboard
var matches = source_url.match(/(?:d|d-solo|dashboard)\/([^\/]+)\//);
if(matches && matches[1]) {
var dashboard_id = matches[1];
var api_url = source_url.replace(/\/grafana\/.*$/, '/grafana/api/dashboards/uid/'+dashboard_id)
await page.goto(api_url);

let data = await page.content();
data = data.replace(/.*<pre>/, '');
data = data.replace(/<\/pre>.*/, '');
data = data.replace(/\n/g, '');
eval('data = '+data+";");
if(data && data["dashboard"] && data["dashboard"]["panels"]) {
data.dashboard.panels.forEach(function(panel, j) {
if(panel.id==panelId || panel.title.match(panelId)) {
urlObj.searchParams.set('panelId', panel.id);
url = urlObj.toString();
}
});
}
}
}
};

await page.goto(url);
if(url.match(/histou\.js\?/) || url.match(/\/grafana\//)) {
var errorMsg;
Expand Down
73 changes: 66 additions & 7 deletions templates/_histou_graph.tt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<script>
var histou_url = "[% histou_url %]";
var histou_frame_url = "[% histou_frame_url %]";
var histou_source = [% histou_source %];
var histou_source = "[% histou_source %]";
var random = Number(Math.random() * 100000).toFixed(0);

/* try to fetch sources */
Expand All @@ -27,8 +27,8 @@
var title = panel.title;
title = title.replace('[% escape_js(hst) %] ', '');
title = title.replace('[% escape_js(svc) %] ', '');
title = title.replace('check_thruk_agent ', '');
jQuery('#histou_source_select').append('<option value="'+panel.id+'"'+(panel.id==histou_source ? ' selected' : '')+'>'+title+'<\/option>');
title = title.replace(/^check_\S+ /, '');
jQuery('#histou_source_select').append('<option value="'+panel.id+'"'+((panel.id==histou_source || title == histou_source) ? ' selected' : '')+'>'+title+'<\/option>');
has_graphs++;
});
});
Expand All @@ -42,7 +42,7 @@
});
} else {
// extract panels from plain grafana dashboard
var matches = source_url.match(/(?:d|dashboard)\/([^\/]+)\//);
var matches = source_url.match(/(?:d|d-solo|dashboard)\/([^\/]+)\//);
if(matches && matches[1]) {
var dashboard_id = matches[1];
var api_url = source_url.replace(/\/grafana\/.*$/, '/grafana/api/dashboards/uid/'+dashboard_id)
Expand All @@ -57,7 +57,7 @@
jQuery('#histou_source_select').find('option').remove();
if(data && data["dashboard"] && data["dashboard"]["panels"]) {
jQuery(data.dashboard.panels).each(function(j, panel) {
jQuery('#histou_source_select').append('<option value="'+panel.id+'"'+(panel.id==histou_source ? ' selected' : '')+'>'+panel.title+'<\/option>');
jQuery('#histou_source_select').append('<option value="'+panel.id+'"'+((panel.id==histou_source || panel.title.match(histou_source)) ? ' selected' : '')+'>'+panel.title+'<\/option>');
has_graphs++;
});
}
Expand Down Expand Up @@ -94,7 +94,7 @@
</div>
<div class="h-[262px] relative justify-center">
<a id="histou_graph_link" href="[% url_prefix %]#[% histou_url %]" class="clickable absolute top-0 left-0 w-full h-full z-40"></a>
<div id="histou_graph_pane" class="relative w-full h-full overflow-hidden">
<div id="histou_graph_pane" style="display:none;" class="relative w-full h-full overflow-hidden">
<div id="pnpwaitimg" class="absolute top-10 left-1/2 transform -translate-x-1/2" title="waiting"><div class="spinner w-12 h-12"></div></div>
<iframe id="histou_iframe" src="[% histou_frame_url %]" class="w-full h-[270px] p-0 m-0 mx-auto"></iframe>
</div>
Expand All @@ -120,5 +120,64 @@
histou_source = values[3];
}
}
set_histou_img(histou_start, histou_end, histou_id, histou_source, true);


if(jQuery.isNumeric(histou_source)) {
set_histou_img(histou_start, histou_end, histou_id, histou_source, true);
} else {
// fetch id for source name
var source_url = histou_url.replace(/\/grafana\/(d|dashboard|dashboard-solo)\/script\/histou\.js\?/, '/histou/index.php?_='+random+'&');
jQuery('#pnpwaitimg').css('display', 'block');
if(source_url.match("/histou/index.php")) {
jQuery.ajax({
url: source_url,
type: 'POST',
xhrFields: {
withCredentials: true
},
success: function(data) {
data = data.replace(/^[\s\S]*<br>\{/, '{');
data = data.replace(/<br><\/pre>$/, '');
data = data.replace(/\n/g, '');
eval('data = '+data+";");
jQuery(data.rows).each(function(i, row) {
jQuery(row.panels).each(function(j, panel) {
var title = panel.title;
title = title.replace('[% escape_js(hst) %] ', '');
title = title.replace('[% escape_js(svc) %] ', '');
title = title.replace(/^check_\S+ /, '');
if(panel.id==histou_source || title == histou_source) {
set_histou_img(histou_start, histou_end, histou_id, panel.id);
}
});
});
},
error: ajax_xhr_error_logonly
});
} else {
// extract panels from plain grafana dashboard
var matches = source_url.match(/(?:d|d-solo|dashboard)\/([^\/]+)\//);
if(matches && matches[1]) {
var dashboard_id = matches[1];
var api_url = source_url.replace(/\/grafana\/.*$/, '/grafana/api/dashboards/uid/'+dashboard_id)
jQuery.ajax({
url: api_url,
type: 'GET',
xhrFields: {
withCredentials: true
},
success: function(data) {
if(data && data["dashboard"] && data["dashboard"]["panels"]) {
jQuery(data.dashboard.panels).each(function(j, panel) {
if(panel.id==histou_source || panel.title.match(histou_source)) {
set_histou_img(histou_start, histou_end, histou_id, panel.id);
}
});
}
},
error: ajax_xhr_error_logonly
});
}
}
}
</script>
35 changes: 30 additions & 5 deletions templates/_pnp_graph.tt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[% USE date %]
<script>
var pnp_source = [% pnp_source %];
var pnp_source = "[% pnp_source %]";
var pnp_url = "[% pnp_url %]/image?host=[% hst | uri %]&srv=[% svc | uri %]&view=1&graph_width=550";

/* try to fetch sources */
Expand All @@ -17,7 +17,7 @@
var has_graphs = false;
jQuery('#pnp_source_select').find('option').remove();
jQuery(sources).each(function(x, s) {
jQuery('#pnp_source_select').append('<option value="'+x+'"'+(x==pnp_source ? ' selected' : '')+'>'+s.ds_name+'<\/option>');
jQuery('#pnp_source_select').append('<option value="'+x+'"'+((x==pnp_source || s.ds_name == pnp_source) ? ' selected' : '')+'>'+s.ds_name+'<\/option>');
has_graphs = true;
});
/* only useful for multiple sources */
Expand Down Expand Up @@ -49,10 +49,10 @@
<span id="pnp_th5" class="tabs text-center w-[18%]" onclick="return set_png_img(-30067200, '', this.id, pnp_source)">year</span>
<span class="tabs text-center w-12" onclick="return move_png_img( 0.5)"><i class="uil uil-angle-right text-lg contents"></i></span>
</div>
<div id="pnp_graph_pane" class="relative justify-center min-h-[100px]">
<div id="pnp_graph_pane" class="relative justify-center min-h-[160px]">
<a href="[% url_prefix %]#[% pnp_url %]/graph?host=[% hst | uri %]&amp;srv=[% svc | uri %]&amp;theme=smoothness" class="w-full">
<div id="pnpwaitimg" class="absolute top-10 left-1/2 transform -translate-x-1/2" title="waiting"><div class="spinner w-12 h-12"></div></div>
<img id="pnpimg" src="[% pnp_url %]/image?host=[% hst | uri %]&srv=[% svc | uri %]&view=1&graph_width=550" alt="pnp graph" class="mx-auto">
<img id="pnpimg" style="display:none;" src="[% pnp_url %]/image?host=[% hst | uri %]&srv=[% svc | uri %]&view=1&graph_width=550" alt="pnp graph" class="mx-auto">
<div id="pnperr" style="display:none" class="textALERT text-center py-2">Could not retrieve graph data</div>
<iframe id="pnp_iframe" src="#" class="w-full h-[270px] p-0 m-0 mx-auto hidden"></iframe>
</a>
Expand All @@ -78,5 +78,30 @@
pnp_source = values[3];
}
}
set_png_img(pnp_start, pnp_end, pnp_id, pnp_source, true);

if(jQuery.isNumeric(pnp_source)) {
set_png_img(pnp_start, pnp_end, pnp_id, pnp_source, true);
} else {
// fetch id for source name
var source_url = pnp_url.replace(/\/image\?/, '/json?');
jQuery('#pnpwaitimg').css('display', 'block');
jQuery.ajax({
url: source_url,
type: 'POST',
xhrFields: {
withCredentials: true
},
success: function(data) {
if(!data.match(/^\[/)) { return; }
var sources = eval(data);
jQuery(sources).each(function(x, s) {
if(x==pnp_source || s.ds_name == pnp_source) {
set_png_img(pnp_start, pnp_end, pnp_id, x);
return false;
}
});
},
error: ajax_xhr_error_logonly
});
}
</script>

0 comments on commit f978206

Please sign in to comment.