Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • iml-open-source/appmonitor-dashboard
1 result
Select Git revision
Show changes
Commits on Source (2)
......@@ -21,14 +21,27 @@ Extract the archive (or use git pull).
We need to setup the url for the api of the IML Appmonitor instance. In `public_html/javascript` copy the dist file inc_config.js.dist to inc_config.js
Replace values in AM_SERVER_URL and AM_TAGS with your real data:
Replace values in the first object in the AM_INSTANCES array with your real data:
```js
const AM_SERVER_URL='https://appmonitor.example.com/api';
const AM_TAGS='live,myapp';
/**
* you can add multiple instances of appmonitor servers
*/
const AM_INSTANCES=[
{
'label': 'local Docker',
'url': 'http://localhost:8001',
'tags': 'monitoring',
'user': 'api',
'password': 'hello'
}
];
const REFRESHTIME=30; // in sec
```
You can multiple instances of appmonitor servers with creating an additional object here. You get a select box to switch between them.
Open the file `public_html/index.html` in your webbrowser.
## Troubleshooting ##
......
......@@ -24,7 +24,7 @@ const OUT_ID_MAIN='header-section';
const OUT_ID_APPS='app-section';
const OUT_ID_TAGS='tag-section';
const ID_TAGINPUT='E_TAGS';
const ID_DELTAGS='button-disable-all-tags';
// callback object after changing a tag filter
const FILTER_CALLBACK="oUbdApps.update()";
......@@ -48,8 +48,8 @@ var AM_TAGLIST={};
*/
function _getAMApiUrl(sPath){
return AM_PRETTYURL
? AM_SERVER_URL+sPath
: AM_SERVER_URL+'/index.php?request='+sPath
? AM_SERVER_URL+'/api'+sPath
: AM_SERVER_URL+'/api/index.php?request='+sPath
;
}
......@@ -119,6 +119,7 @@ function _2digits(i){
}
if(sLast!==sReturn){
document.getElementById(ID_TAGINPUT).value=sReturn;
document.getElementById(ID_DELTAGS).style.display=sReturn ? 'inline' : 'none';
eval(FILTER_CALLBACK);
}
}
......@@ -156,7 +157,7 @@ function _renderTaglist(aData){
: ''
);
}
sReturn+='<button onclick="cbTagToggle(true);return false;"> </button>'
sReturn+='<button id="'+ID_DELTAGS+'" onclick="cbTagToggle(true);return false;"> '+AM_ICONS['delete']+' </button>'
// sReturn+='<input id="'+ID_TAGINPUT+'" type="text" size="20" value="'+AM_TAGS+'"'+'>'
sReturn+='<input id="'+ID_TAGINPUT+'" type="hidden" size="20" value="'+AM_TAGS+'">'
AM_TAGLIST=_TAGLIST;
......@@ -187,9 +188,11 @@ function _getAllAppsStatus(aAllData){
+' (update every '+REFRESHTIME+' sec)'
// +'</p>';
// let aAllData=JSON.parse(sData);
var appOut='';
for (var key in aAllData){
sReturn+=_getSingleAppStatus(aAllData[key]);
appOut+=_getSingleAppStatus(aAllData[key]);
}
sReturn+=appOut ? appOut : '<div class="app result2">NO DATA.<br>No application matches this combination of tags.</div>';
return sReturn;
}
......@@ -262,44 +265,76 @@ function _getSingleAppStatus(aData){
}
// ----------------------------------------------------------------------
// MAIN
// init instance
// ----------------------------------------------------------------------
// for auth header with basic auth
let oHeaders=(AM_USER)
? { "Authorization": "Basic " + btoa(AM_USER + ":" + AM_PASSWORD) }
: {}
;
document.getElementById(OUT_ID_MAIN).innerHTML=''+AM_ICONS['connect']+' Connected instance <a href="'+AM_SERVER_URL+'">'+AM_SERVER_URL+'</a>';
// initialize tags
var oUbdTag=new ubd(
{
'domid': OUT_ID_TAGS,
'url': _getUrlForTags(),
'header': { "headers": oHeaders },
'renderer': _renderTaglist,
'ttl': 0,
}
);
// initialize visible apps
var oUbdApps=new ubd(
{
'domid': OUT_ID_APPS,
'url': _getUrlWithTags, // remark: this is a function
'header': { "headers": oHeaders },
'renderer': _getAllAppsStatus,
'ttl': REFRESHTIME,
}
);
/**
* set a appmonitor instance that are defined in AM_INSTANCES
* see inc_config.js
*
* @param {integer} i number of instance to activate
*/
function initInstance(i){
AM_SERVER_URL=AM_INSTANCES[i]['url'];
AM_TAGS=AM_INSTANCES[i]['tags'];
AM_USER=AM_INSTANCES[i]['user'];
AM_PASSWORD=AM_INSTANCES[i]['password'];
// for auth header with basic auth
let oHeaders=(AM_USER)
? { "Authorization": "Basic " + btoa(AM_USER + ":" + AM_PASSWORD) }
: {}
;
// fill in initial values ... and update based on given ttl
oUbdTag.update();
oUbdApps.update();
// initialize tags
oUbdTag=new ubd(
{
'domid': OUT_ID_TAGS,
'url': _getUrlForTags(),
'header': { "headers": oHeaders },
'renderer': _renderTaglist,
'ttl': 0,
}
);
// initialize visible apps
oUbdApps=new ubd(
{
'domid': OUT_ID_APPS,
'url': _getUrlWithTags, // remark: this is a function
'header': { "headers": oHeaders },
'renderer': _getAllAppsStatus,
'ttl': REFRESHTIME,
}
);
let sInstances='';
for (var j=0; j<AM_INSTANCES.length; j++){
sInstances+='<option value="'+j+'" '
+(i==j ? 'selected ' : '')
+ '>'+AM_INSTANCES[j]['label']+'</option>';
}
sInstances=sInstances
? AM_ICONS['connect']+' Connected instance '
+ '<select onchange="initInstance(this.value); return false;">'+sInstances+'</select> '
+ ' <a href="'+AM_SERVER_URL+'">'+AM_SERVER_URL+'</a>'
: '';
document.getElementById(OUT_ID_MAIN).innerHTML= sInstances;
// fill in initial values ... and update based on given ttl
window.setTimeout("oUbdTag.update();", 50);
window.setTimeout("oUbdApps.update();", 400);
}
// ----------------------------------------------------------------------
// MAIN
// ----------------------------------------------------------------------
initInstance(0);
// ----------------------------------------------------------------------
\ No newline at end of file
const AM_SERVER_URL='https://appmonitor.example.com/api';
const AM_TAGS='live,myapp';
/**
* you can add multiple instances of appmonitor servers
*/
const AM_INSTANCES=[
{
'label': 'local Docker',
'url': 'http://localhost:8001',
'tags': 'monitoring',
'user': 'api',
'password': 'hello'
}
];
// optional: BASIC AUTH
const AM_USER='';
const AM_PASSWORD='';
const REFRESHTIME=30; // in sec
const REFRESHTIME=30; // in sec
\ No newline at end of file
......@@ -15,22 +15,14 @@
* ======================================================================
*/
var ubd = function(){
this._sDomId='';
this._oDomObject=false;
this._sUrl2Fetch=false; // static value or reference of a function
this._oHeader={};
this._sRenderfunction=false;
this._iTTL=false;
this._oTimer=false;
this._body='';
/**
* Url binded to a dom id
* @return class
*/
class ubd {
/**
* initialize data for a dom object
* @parm {object} oConfig optional config object with those subkeys:
* @param {object} oConfig optional config object with those subkeys:
* domid - id of a dom object
* url - url to an api
* header - http request header data
......@@ -38,25 +30,40 @@ var ubd = function(){
* ttl - ttl in sec (TODO)
* @returns {undefined}
*/
this.init = function(oConfig){
if (oConfig){
if(oConfig['domid']){
constructor(oConfig) {
this._sDomId = '';
this._oDomObject = false;
this._sUrl2Fetch = false; // static value or reference of a function
this._oHeader = {};
this._sRenderfunction = false;
this._iTTL = false;
this._oTimer = false;
this._body = '';
oConfig = arguments ? arguments[0] : false;
if (oConfig) {
if (oConfig['domid']) {
this.setDomid(oConfig['domid']);
}
if(oConfig['url']){
if (oConfig['url']) {
this.setUrl(oConfig['url']);
}
if(oConfig['header']){
if (oConfig['header']) {
this.setHeaders(oConfig['header']);
}
if(oConfig['renderer']){
if (oConfig['renderer']) {
this.setRenderfunction(oConfig['renderer']);
}
if(oConfig['ttl']){
if (oConfig['ttl']) {
this.setTtl(oConfig['ttl']);
}
}
},
}
// ----------------------------------------------------------------------
// public SETTER for properties
......@@ -66,141 +73,130 @@ var ubd = function(){
* set domid that will by updated
* @param {string} sDomid if of a domobject
*/
this.setDomid = function(sDomid){
if (document.getElementById(sDomid)){
this._sDomId=sDomid;
this._oDomObject=document.getElementById(sDomid);
} else {
this._sDomId=false;
this._oDomObject=false;
console.error('ERROR: setDomid("'+sDomid+'") got an invalid string - this domid does not exist.');
}
},
setDomid(sDomid) {
if (document.getElementById(sDomid)) {
this._sDomId = sDomid;
this._oDomObject = document.getElementById(sDomid);
} else {
this._sDomId = false;
this._oDomObject = false;
console.error('ERROR: setDomid("' + sDomid + '") got an invalid string - this domid does not exist.');
}
}
/**
* set a rendering function that visualized data after a http request
* @param {string|function} oFunction reference to a function ... or false to disable rendering
*/
this.setRenderfunction = function(oFunction){
this._sRenderfunction=oFunction;
},
setRenderfunction (oFunction) {
this._sRenderfunction = oFunction;
}
/**
* Set time to live in seconds
* @param {int} iTTL
* @param {int} iTTL
*/
this.setTtl = function(iTTL){
this._iTTL=iTTL/1;
setTtl(iTTL) {
this._iTTL = iTTL / 1;
this.resetTimer();
},
}
/**
* set an url to be requested
* @param {string|function} sUrl static value or reference of a function
*/
this.setUrl = function(sUrl){
this._sUrl2Fetch=sUrl;
},
setUrl(sUrl) {
this._sUrl2Fetch = sUrl;
}
/**
* set header obejct for 2nd param in javascript fetch() function
* @param {object} oHeader
* @param {object} oHeader
*/
this.setHeaders = function(oHeader){
this._oHeader=oHeader;
},
setHeaders(oHeader) {
this._oHeader = oHeader;
}
/**
* helper: dump current object instance to console
*/
this.dumpme = function(){
dumpme() {
console.log('---------- DUMP ubd');
console.log(this);
console.log('---------- /DUMP ubd');
},
}
// ----------------------------------------------------------------------
// public ACTIONS
// ----------------------------------------------------------------------
/**
* show rendered html content into set domid using the render function.
* If no rendering function was set then the response will be written
* directly.
* You can override both by giving a parameter (a string with html)
* to write that one directly. It can be used to show an error message.
*
*
* TODO:
* other output places than innerHTML by detecting the tag e.g.
* other output places than innerHTML by detecting the tag e.g.
* to use input or textarea.
*
*
* @param {string} sHtml optional: htmlcode of an error message
*/
this.render = function(sHtml) {
let out = sHtml ? sHtml :
(this._sRenderfunction
render(sHtml) {
let out = sHtml ? sHtml :
(this._sRenderfunction
? this._sRenderfunction(this._body)
: this._body
);
this._oDomObject.innerHTML=out;
},
this._oDomObject.innerHTML = out;
}
/**
* reset timer to update the content in dom id after reaching TTL
* used in setTtl
*/
this.resetTimer = function(){
resetTimer() {
clearTimeout(this._oTimer);
// clearInterval(this._oTimer);
if(this._iTTL) {
if (this._iTTL) {
let self = this;
self._oTimer=window.setTimeout( function(){ self.update() }, this._iTTL*1000);
self._oTimer = window.setTimeout(function () { self.update(); }, this._iTTL * 1000);
// self._oTimer=window.setInterval(self.update, this._iTTL*1000);
}
},
}
/**
* make http request and call the renderer
*/
this.update = async function(){
async update() {
let self = this;
let url=( typeof this._sUrl2Fetch == "function" ) ? this._sUrl2Fetch() : this._sUrl2Fetch;
let url = (typeof this._sUrl2Fetch == "function") ? this._sUrl2Fetch() : this._sUrl2Fetch;
console.log("update from url [" + url + "]");
if (url == undefined){
if (url == undefined) {
console.error("SKIP update - there is no url in this object instance (anymore) :-/");
this.dumpme();
return 0;
}
try{
try {
let response = await fetch(url, this._oHeader);
if (response.ok) {
this._body=await response.json();
this._body = await response.json();
this.render();
} else {
this.render('<div class="app result1">'
+'ERROR '+response.status+': '+response.statusText + ' - '
+url
+'</div>');
}
} catch(e) {
+ 'ERROR ' + response.status + ': ' + response.statusText + ' - '
+ url
+ '</div>');
}
} catch (e) {
this.render('<div class="app result1">'
+'UNKNOWN: no response from '
+this._sUrl2Fetch
+'</div>');
+ 'UNKNOWN: no response from '
+ this._sUrl2Fetch
+ '</div>');
console.error(e);
}
this.resetTimer();
}
// ----------------------------------------------------------------------
// MAIN
// ----------------------------------------------------------------------
if (arguments) {
this.init(arguments[0]);
} else {
this.init();
}
};
\ No newline at end of file
}
\ No newline at end of file
:root{
--color-0: #345;
--color-h1: #abc;
--color-h1: #789;
--color-h2: #579;
--color-links: #349;
......@@ -19,8 +19,8 @@ body{
font-family: verdana,arial;
}
button{ border: 1px solid rgba(0,0,0,0.1); background: linear-gradient(#f8f8f8, #ddd); border-radius: 0.3em; margin: 0 0.5em 0.5em 0; padding: 0.5em;}
button:hover{ background: linear-gradient(#eee, #ccc); border-radius: 0.3em; margin: 0 0.5em 0.5em 0; padding: 0.5em;}
button{ border: 1px solid rgba(0,0,0,0.1); background: linear-gradient(#f8f8f8, #ddd); border-radius: 0.3em; margin: 0 0.5em 0; padding: 0.5em;}
button:hover{ background: linear-gradient(#eee, #ccc);}
button:active{ border:1px solid #fc2;}
input{ border:1px solid #ccc; padding: 0.4em;}
......@@ -52,7 +52,15 @@ section input[type=checkbox]:checked + label {
section input[type=checkbox]+ label:hover {
border-color: #89a;
}
select{
background: #fff;
border: 2px solid #f8f8f8;
color: var(--color-0);
font-size: 110%;
}
select:hover{
background: #fec;
}
td{vertical-align: top;}
#main{
......