Files
butler-sos/static/configvis/index.html
2025-07-27 19:20:06 +00:00

397 lines
23 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<title>Butler SOS</title>
<link rel="stylesheet" href="jsontree.js.css" />
<script src="jsontree.js"></script>
<!-- Include Prism CSS -->
<link rel="stylesheet" href="prism.css" />
<!-- Include Prism JS -->
<script src="prism.js"></script>
<style>
#header {
display: flex;
justify-content: space-between;
align-items: center;
position: fixed;
top: 0;
width: 100%;
z-index: 1000;
background-color: #fff; /* Add a background color to ensure text is readable */
}
#headerLeft {
display: flex;
align-items: center;
width: 50%;
}
#headerRight {
display: flex;
align-items: center;
width: 50%;
text-align: right;
}
#logo,
/* #pageTitle, */
#buttons {
display: flex;
align-items: center; /* Center align the contents of logo and buttons */
}
#logo {
/* Ensure there's no right margin or padding that could push the title to the right */
margin-top: 10px;
margin-right: 0;
padding-right: 0;
}
#pageTitle h1, #pageTitle h2 {
display: block; /* Display as block element */
text-align: left; /* Align the title to the left */
margin: 0; /* Remove default margin */
padding-left: 20px; /* Add some space between the logo and the title */
font-family: Arial, sans-serif; /* Use Arial font */
}
#pageTitle h1 {
font-size: 32px; /* Adjust font size as needed */
}
#pageTitle h2 {
font-size: 20px; /* Adjust font size as needed */
}
#buttons {
justify-content: flex-end;
}
#downloadYaml {
font-size: 20px;
padding: 10px;
margin-right: 20px;
background-color: #007bff; /* Blue background */
color: white; /* White text */
border: none; /* Remove border */
cursor: pointer; /* Pointer cursor on hover */
border-radius: 5px; /* Rounded corners */
box-shadow: 0 4px #0056b3; /* Darker blue shadow for 3D effect */
transition: all 0.3s; /* Smooth transition for press effect */
}
#downloadYaml:hover {
background-color: #0056b3; /* Darker shade on hover */
cursor: pointer; /* Change cursor to pointer to indicate it's clickable */
}
#downloadYaml:active {
box-shadow: 0 2px #0056b3; /* Adjust shadow for pressed effect */
transform: translateY(4px); /* Move button down to mimic press */
}
body {
padding-top: 90px; /* Add padding to the top of the body to prevent content from being hidden behind the fixed header */
}
/* Style the tab */
.tab {
overflow: hidden;
border: 1px solid #ccc;
background-color: #f1f1f1;
}
/* Style the buttons inside the tab */
.tab button {
background-color: inherit;
float: left;
border: none;
outline: none;
cursor: pointer;
padding: 14px 16px;
transition: 0.3s;
font-size: 17px;
}
/* Change background color of buttons on hover */
.tab button:hover {
background-color: #ddd;
}
/* Create an active/current tablink class */
.tab button.active {
background-color: #ccc;
}
/* Style the tab content */
.tabcontent {
display: none;
padding: 6px 12px;
border: 1px solid #ccc;
border-top: none;
}
/* Style for preformatted text */
pre {
background-color: #f4f4f4;
border: 1px solid #ddd;
padding: 10px;
border-radius: 5px;
overflow: auto;
}
/* Make tooltips hoverable so links can be clicked */
div.jsontree-js-tooltip,
div.jsontree-js-tooltip-value {
/* Increase z-index to ensure tooltips appear above other elements */
z-index: 9999 !important;
/* Make the tooltip itself hoverable */
pointer-events: auto !important;
/* Add padding around tooltip for easier hover targeting */
padding: 12px !important;
}
/* Prevent tooltips from disappearing when hovering over them */
div.jsontree-js-tooltip:hover,
div.jsontree-js-tooltip-value:hover {
display: block !important;
visibility: visible !important;
}
/* Style links in tooltips to be more obviously clickable */
div.jsontree-js-tooltip a,
div.jsontree-js-tooltip-value a {
color: #4a9eff !important;
text-decoration: underline !important;
pointer-events: auto !important;
}
div.jsontree-js-tooltip a:hover,
div.jsontree-js-tooltip-value a:hover {
color: #66b3ff !important;
background-color: rgba(74, 158, 255, 0.1) !important;
}
</style>
</head>
<body>
<div id="header">
<div id="headerLeft">
<div id="logo">
<a href="https://butler-sos.ptarmiganlabs.com" target="_blank">
<img src="butler-sos.png" alt="Butler SOS logo" height="100px" />
</a>
</div>
<div id="pageTitle">
<h1>
Current Butler SOS configuration
</h1>
<h2>
Config file docs
<a
href="https://butler-sos.ptarmiganlabs.com/docs/reference/config_file_format/"
target="_blank"
>here</a>
</h2>
</div>
</div>
<div id="headerRight">
<div id="buttons">
<button id="downloadYaml">
<img
src="download-solid.svg"
alt="Download icon"
style="
vertical-align: middle;
margin-right: 5px;
height: 32px;
width: 32px;
"
/>
Download YAML
</button>
</div>
<!-- Tab links -->
<div class="tab">
<button class="tablinks" onclick="openTab(event, 'YAML')">YAML</button>
<button class="tablinks" onclick="openTab(event, 'JSONTree')">
JSON tree view
</button>
</div>
</div>
</div>
<!-- Tab content -->
<div id="YAML" class="tabcontent">
<h3>YAML configuration</h3>
<pre class="line-numbers"><code class="language-yaml">{{butlerConfigYaml}}</code></pre>
</div>
<div id="JSONTree" class="tabcontent">
<h3>JSON tree view</h3>
<div
id="tree-1"
data-jsontree-js="{
title: {
show: false,
showTreeControls: true,
showCopyButton: true
},
showCounts: true,
sortPropertyNames: false,
sortPropertyNamesInAlphabeticalOrder: false,
data: {{butlerSosConfigJsonEncoded}},
tooltip: {
delay: 50,
offset: 15
},
valueToolTips: {
'Butler-SOS\\logLevel': 'Log level. Possible log levels are silly, debug, verbose, info, warn, error. Case sensitive.',
'Butler-SOS\\fileLogging': 'true/false to enable/disable logging to disk file',
'Butler-SOS\\logDirectory': 'Subdirectory where log files are stored',
'Butler-SOS\\systemInfo': 'Butler SOS collects system information for monitoring and diagnostic purposes. On Windows, this may trigger security alerts in enterprise monitoring tools.',
'Butler-SOS\\systemInfo\\enable': 'Should detailed system information be collected? Set to false in security-sensitive environments.',
'Butler-SOS\\anonTelemetry': 'Can Butler SOS send anonymous data about what computer it is running on? More info: https://butler-sos.ptarmiganlabs.com/docs/about/telemetry/',
'Butler-SOS\\configVisualisation': 'Should Butler SOS start a web server that serves an obfuscated view of the Butler SOS config file?',
'Butler-SOS\\configVisualisation\\enable': 'true/false to enable/disable the web UI for config file visualisation',
'Butler-SOS\\configVisualisation\\host': 'Hostname or IP address where the web server will listen. Should be localhost in most cases.',
'Butler-SOS\\configVisualisation\\port': 'Port where the web server will listen. Change if port 3100 is already in use.',
'Butler-SOS\\configVisualisation\\obfuscate': 'Should the config file shown in the web UI be obfuscated?',
'Butler-SOS\\heartbeat': 'Heartbeats can be used to send I am alive messages to some other tool, e.g. an infrastructure monitoring tool. The remoteURL will be called at the specified frequency.',
'Butler-SOS\\heartbeat\\enable': 'Enable or disable heartbeat functionality',
'Butler-SOS\\heartbeat\\remoteURL': 'URL that will be called at the specified frequency to indicate Butler SOS is alive',
'Butler-SOS\\heartbeat\\frequency': 'How often heartbeat should be sent. Format: https://bunkat.github.io/later/parsers.html#text',
'Butler-SOS\\dockerHealthCheck': 'Docker health checks are used when running Butler SOS as a Docker container. The Docker engine will call the container health check REST endpoint to determine if the container is alive.',
'Butler-SOS\\dockerHealthCheck\\enable': 'Control whether a REST endpoint will be set up to serve Docker health check messages',
'Butler-SOS\\dockerHealthCheck\\port': 'Port the Docker health check service runs on (if enabled)',
'Butler-SOS\\uptimeMonitor': 'Monitor Butler SOS uptime and resource usage',
'Butler-SOS\\uptimeMonitor\\enable': 'Should uptime messages be written to the console and log files?',
'Butler-SOS\\uptimeMonitor\\frequency': 'How often uptime data should be collected. Format: https://bunkat.github.io/later/parsers.html#text',
'Butler-SOS\\uptimeMonitor\\logLevel': 'Starting at what log level should uptime messages be shown in console log and log files?',
'Butler-SOS\\uptimeMonitor\\storeInInfluxdb\\butlerSOSMemoryUsage': 'Should data on Butler SOS own memory use be stored in InfluxDB?',
'Butler-SOS\\uptimeMonitor\\storeInInfluxdb\\instanceTag': 'Tag that can be used to differentiate data from multiple Butler SOS instances',
'Butler-SOS\\uptimeMonitor\\storeNewRelic': 'Settings for storing uptime data in New Relic',
'Butler-SOS\\uptimeMonitor\\storeNewRelic\\enable': 'Should uptime data be sent to New Relic?',
'Butler-SOS\\uptimeMonitor\\storeNewRelic\\destinationAccount': 'List of New Relic accounts where uptime data should be sent',
'Butler-SOS\\uptimeMonitor\\storeNewRelic\\metric': 'Metric configuration for New Relic',
'Butler-SOS\\uptimeMonitor\\storeNewRelic\\metric\\dynamic': 'Dynamic metrics configuration',
'Butler-SOS\\uptimeMonitor\\storeNewRelic\\metric\\dynamic\\butlerMemoryUsage\\enable': 'Should Butler SOS memory/RAM usage be sent to New Relic?',
'Butler-SOS\\uptimeMonitor\\storeNewRelic\\metric\\dynamic\\butlerUptime\\enable': 'Should Butler SOS uptime (how long since it was started) be sent to New Relic?',
'Butler-SOS\\uptimeMonitor\\storeNewRelic\\attribute\\dynamic\\butlerVersion\\enable': 'Should the Butler SOS version be included in the data sent to New Relic?',
'Butler-SOS\\thirdPartyToolsCredentials': 'Credentials for third party systems that Butler SOS integrates with. These can also be specified via command line parameters when starting Butler SOS.',
'Butler-SOS\\thirdPartyToolsCredentials\\newRelic': 'Array of New Relic accounts/insert keys',
'Butler-SOS\\userEvents': 'Track individual users opening/closing apps and starting/stopping sessions. Requires log appender XML file(s) to be added to Sense server(s).',
'Butler-SOS\\userEvents\\enable': 'Enable or disable user event tracking',
'Butler-SOS\\userEvents\\excludeUser': 'Optional blacklist of users that should be disregarded when it comes to user events',
'Butler-SOS\\userEvents\\udpServerConfig': 'UDP server configuration for receiving user events from Sense',
'Butler-SOS\\userEvents\\udpServerConfig\\serverHost': 'Host/IP where user event server will listen for events from Sense',
'Butler-SOS\\userEvents\\udpServerConfig\\portUserActivityEvents': 'Port on which user event server will listen for events from Sense',
'Butler-SOS\\userEvents\\tags': 'Tags are added to the data before it is stored in InfluxDB',
'Butler-SOS\\userEvents\\sendToMQTT\\enable': 'Set to true if user events should be forwarded as MQTT messages',
'Butler-SOS\\userEvents\\sendToMQTT\\postTo\\everythingTopic\\enable': 'Enable sending all user events to this topic',
'Butler-SOS\\userEvents\\sendToMQTT\\postTo\\everythingTopic\\topic': 'MQTT topic name for all user events',
'Butler-SOS\\userEvents\\sendToMQTT\\postTo\\sessionStartTopic\\enable': 'Enable sending session start events to this topic',
'Butler-SOS\\userEvents\\sendToMQTT\\postTo\\sessionStartTopic\\topic': 'MQTT topic name for session start events',
'Butler-SOS\\userEvents\\sendToMQTT\\postTo\\sessionStopTopic\\enable': 'Enable sending session stop events to this topic',
'Butler-SOS\\userEvents\\sendToMQTT\\postTo\\sessionStopTopic\\topic': 'MQTT topic name for session stop events',
'Butler-SOS\\userEvents\\sendToMQTT\\postTo\\connectionOpenTopic\\enable': 'Enable sending connection open events to this topic',
'Butler-SOS\\userEvents\\sendToMQTT\\postTo\\connectionOpenTopic\\topic': 'MQTT topic name for connection open events',
'Butler-SOS\\userEvents\\sendToMQTT\\postTo\\connectionCloseTopic\\enable': 'Enable sending connection close events to this topic',
'Butler-SOS\\userEvents\\sendToMQTT\\postTo\\connectionCloseTopic\\topic': 'MQTT topic name for connection close events',
'Butler-SOS\\userEvents\\sendToInfluxdb\\enable': 'Set to true if user events should be stored in InfluxDB',
'Butler-SOS\\userEvents\\sendToNewRelic\\enable': 'Should user events be sent to New Relic?',
'Butler-SOS\\userEvents\\sendToNewRelic\\destinationAccount': 'List of New Relic accounts where user events should be sent',
'Butler-SOS\\userEvents\\sendToNewRelic\\scramble': 'Should user info (user directory and user ID) be scrambled before sent to New Relic?',
'Butler-SOS\\logEvents': 'Log events are used to capture Sense warnings, errors and fatals in real time',
'Butler-SOS\\logEvents\\udpServerConfig': 'UDP server configuration for receiving log events from Sense',
'Butler-SOS\\logEvents\\udpServerConfig\\serverHost': 'Host/IP where log event server will listen for events from Sense',
'Butler-SOS\\logEvents\\udpServerConfig\\portLogEvents': 'Port on which log event server will listen for events from Sense',
'Butler-SOS\\logEvents\\tags': 'Tags are added to the data before it is stored in InfluxDB',
'Butler-SOS\\logEvents\\source\\engine\\enable': 'Should log events from the engine service be handled?',
'Butler-SOS\\logEvents\\source\\proxy\\enable': 'Should log events from the proxy service be handled?',
'Butler-SOS\\logEvents\\source\\repository\\enable': 'Should log events from the repository service be handled?',
'Butler-SOS\\logEvents\\source\\scheduler\\enable': 'Should log events from the scheduler service be handled?',
'Butler-SOS\\logEvents\\source\\qixPerf\\enable': 'Should log events relating to QIX performance be handled?',
'Butler-SOS\\logEvents\\sendToMQTT\\enable': 'Should log events be sent as MQTT messages?',
'Butler-SOS\\logEvents\\sendToMQTT\\baseTopic': 'What topic should log events be forwarded to?',
'Butler-SOS\\logEvents\\sendToInfluxdb\\enable': 'Should log events be stored in InfluxDB?',
'Butler-SOS\\logEvents\\sendToNewRelic\\enable': 'Should log events be sent to New Relic?',
'Butler-SOS\\cert': 'Certificates to use when connecting to Sense. Get these from the Certificate Export in QMC.',
'Butler-SOS\\cert\\clientCert': 'Path to client certificate file (client.pem)',
'Butler-SOS\\cert\\clientCertKey': 'Path to client certificate key file (client_key.pem)',
'Butler-SOS\\cert\\clientCertCA': 'Path to certificate authority file (root.pem)',
'Butler-SOS\\cert\\clientCertPassphrase': 'Certificate key password, if one was specified when exporting certificates from Sense QMC',
'Butler-SOS\\mqttConfig': 'MQTT broker configuration',
'Butler-SOS\\mqttConfig\\enable': 'Enable or disable MQTT functionality',
'Butler-SOS\\mqttConfig\\brokerHost': 'IP address or hostname of MQTT broker/server',
'Butler-SOS\\mqttConfig\\brokerPort': 'Port where MQTT broker is listening (usually 1883)',
'Butler-SOS\\mqttConfig\\baseTopic': 'Default topic used if not otherwise specified elsewhere. Should end with /',
'Butler-SOS\\influxdbConfig': 'InfluxDB configuration for storing Butler SOS metrics',
'Butler-SOS\\influxdbConfig\\enable': 'Enable or disable InfluxDB integration',
'Butler-SOS\\influxdbConfig\\host': 'InfluxDB host, hostname, FQDN or IP address',
'Butler-SOS\\influxdbConfig\\port': 'Port where InfluxDB is listening (usually 8086)',
'Butler-SOS\\influxdbConfig\\version': 'Is the InfluxDB instance version 1.x or 2.x? Valid values are 1 or 2',
'Butler-SOS\\serversToMonitor': 'Configuration for Qlik Sense servers to monitor',
'Butler-SOS\\serversToMonitor\\pollingInterval': 'How often (milliseconds) should the healthcheck API be polled?',
'Butler-SOS\\serversToMonitor\\rejectUnauthorized': 'If false, Butler SOS will accept TLS certificates on the server without verifying them with the CA. If true, data will only be retrieved from the Sense server if that servers TLS cert verifies successfully against the list of CAs.',
'Butler-SOS\\serversToMonitor\\servers': 'List of Sense servers that should be queried for healthcheck data'
}
}"
style="width: 100%; max-width: 100%"
>
</div>
</div>
<script>
// Function that gets data from handlebars template butlerConfigYamlObfuscated and returns it
function getYamlFromHandlebars() {
try {
const yamlData = `{{butlerConfigYaml}}`;
return yamlData;
} catch (error) {
console.error(
'There was a problem getting YAML config data from Handlebars template:',
error
);
}
}
document.getElementById('downloadYaml').addEventListener('click', function () {
var butlerConfigYaml = getYamlFromHandlebars();
var blob = new Blob([butlerConfigYaml], { type: 'text/yaml' });
var url = URL.createObjectURL(blob);
// Create a temporary link to trigger the download
var a = document.createElement('a');
a.href = url;
a.download = 'config.yaml'; // The default file name for downloading
document.body.appendChild(a); // Append to the document
a.click(); // Simulate click to trigger download
document.body.removeChild(a); // Remove the element after download
URL.revokeObjectURL(url); // Clean up the URL object
});
function openTab(evt, tabName) {
// Declare all variables
var i, tabcontent, tablinks;
// Get all elements with class="tabcontent" and hide them
tabcontent = document.getElementsByClassName('tabcontent');
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.display = 'none';
}
// Get all elements with class="tablinks" and remove the class "active"
tablinks = document.getElementsByClassName('tablinks');
for (i = 0; i < tablinks.length; i++) {
tablinks[i].className = tablinks[i].className.replace(' active', '');
}
// Show the current tab, and add an "active" class to the button that opened the tab
document.getElementById(tabName).style.display = 'block';
evt.currentTarget.className += ' active';
}
// Optionally, auto-open the first tab when the page loads
document.addEventListener('DOMContentLoaded', function () {
document.getElementsByClassName('tablinks')[0].click();
});
</script>
</body>
</html>