Skip to content
Snippets Groups Projects
Commit 9f016da6 authored by Hahn Axel (hahn)'s avatar Hahn Axel (hahn)
Browse files

added support of multiple instances

parent 96a8429d
Branches
No related tags found
1 merge request!4added support of multiple instances
...@@ -21,14 +21,27 @@ Extract the archive (or use git pull). ...@@ -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 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 ```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 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. Open the file `public_html/index.html` in your webbrowser.
## Troubleshooting ## ## Troubleshooting ##
......
...@@ -24,7 +24,7 @@ const OUT_ID_MAIN='header-section'; ...@@ -24,7 +24,7 @@ const OUT_ID_MAIN='header-section';
const OUT_ID_APPS='app-section'; const OUT_ID_APPS='app-section';
const OUT_ID_TAGS='tag-section'; const OUT_ID_TAGS='tag-section';
const ID_TAGINPUT='E_TAGS'; const ID_TAGINPUT='E_TAGS';
const ID_DELTAGS='button-disable-all-tags';
// callback object after changing a tag filter // callback object after changing a tag filter
const FILTER_CALLBACK="oUbdApps.update()"; const FILTER_CALLBACK="oUbdApps.update()";
...@@ -48,8 +48,8 @@ var AM_TAGLIST={}; ...@@ -48,8 +48,8 @@ var AM_TAGLIST={};
*/ */
function _getAMApiUrl(sPath){ function _getAMApiUrl(sPath){
return AM_PRETTYURL return AM_PRETTYURL
? AM_SERVER_URL+sPath ? AM_SERVER_URL+'/api'+sPath
: AM_SERVER_URL+'/index.php?request='+sPath : AM_SERVER_URL+'/api/index.php?request='+sPath
; ;
} }
...@@ -119,6 +119,7 @@ function _2digits(i){ ...@@ -119,6 +119,7 @@ function _2digits(i){
} }
if(sLast!==sReturn){ if(sLast!==sReturn){
document.getElementById(ID_TAGINPUT).value=sReturn; document.getElementById(ID_TAGINPUT).value=sReturn;
document.getElementById(ID_DELTAGS).style.display=sReturn ? 'inline' : 'none';
eval(FILTER_CALLBACK); eval(FILTER_CALLBACK);
} }
} }
...@@ -156,7 +157,7 @@ function _renderTaglist(aData){ ...@@ -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="text" size="20" value="'+AM_TAGS+'"'+'>'
sReturn+='<input id="'+ID_TAGINPUT+'" type="hidden" size="20" value="'+AM_TAGS+'">' sReturn+='<input id="'+ID_TAGINPUT+'" type="hidden" size="20" value="'+AM_TAGS+'">'
AM_TAGLIST=_TAGLIST; AM_TAGLIST=_TAGLIST;
...@@ -187,9 +188,11 @@ function _getAllAppsStatus(aAllData){ ...@@ -187,9 +188,11 @@ function _getAllAppsStatus(aAllData){
+' (update every '+REFRESHTIME+' sec)' +' (update every '+REFRESHTIME+' sec)'
// +'</p>'; // +'</p>';
// let aAllData=JSON.parse(sData); // let aAllData=JSON.parse(sData);
var appOut='';
for (var key in aAllData){ 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; return sReturn;
} }
...@@ -262,44 +265,76 @@ function _getSingleAppStatus(aData){ ...@@ -262,44 +265,76 @@ function _getSingleAppStatus(aData){
} }
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// MAIN // init instance
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// for auth header with basic auth /**
let oHeaders=(AM_USER) * set a appmonitor instance that are defined in AM_INSTANCES
? { "Authorization": "Basic " + btoa(AM_USER + ":" + AM_PASSWORD) } * see inc_config.js
: {} *
; * @param {integer} i number of instance to activate
*/
document.getElementById(OUT_ID_MAIN).innerHTML=''+AM_ICONS['connect']+' Connected instance <a href="'+AM_SERVER_URL+'">'+AM_SERVER_URL+'</a>'; function initInstance(i){
// 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,
}
);
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 // initialize tags
oUbdTag.update(); oUbdTag=new ubd(
oUbdApps.update(); {
'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 REFRESHTIME=30; // in sec
const AM_USER=''; \ No newline at end of file
const AM_PASSWORD='';
const REFRESHTIME=30; // in sec
...@@ -15,22 +15,14 @@ ...@@ -15,22 +15,14 @@
* ====================================================================== * ======================================================================
*/ */
var ubd = function(){ /**
* Url binded to a dom id
this._sDomId=''; * @return class
this._oDomObject=false; */
this._sUrl2Fetch=false; // static value or reference of a function class ubd {
this._oHeader={};
this._sRenderfunction=false;
this._iTTL=false;
this._oTimer=false;
this._body='';
/** /**
* initialize data for a dom object * 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 * domid - id of a dom object
* url - url to an api * url - url to an api
* header - http request header data * header - http request header data
...@@ -38,25 +30,40 @@ var ubd = function(){ ...@@ -38,25 +30,40 @@ var ubd = function(){
* ttl - ttl in sec (TODO) * ttl - ttl in sec (TODO)
* @returns {undefined} * @returns {undefined}
*/ */
this.init = function(oConfig){ constructor(oConfig) {
if (oConfig){
if(oConfig['domid']){ 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']); this.setDomid(oConfig['domid']);
} }
if(oConfig['url']){ if (oConfig['url']) {
this.setUrl(oConfig['url']); this.setUrl(oConfig['url']);
} }
if(oConfig['header']){ if (oConfig['header']) {
this.setHeaders(oConfig['header']); this.setHeaders(oConfig['header']);
} }
if(oConfig['renderer']){ if (oConfig['renderer']) {
this.setRenderfunction(oConfig['renderer']); this.setRenderfunction(oConfig['renderer']);
} }
if(oConfig['ttl']){ if (oConfig['ttl']) {
this.setTtl(oConfig['ttl']); this.setTtl(oConfig['ttl']);
} }
} }
}, }
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// public SETTER for properties // public SETTER for properties
...@@ -66,141 +73,130 @@ var ubd = function(){ ...@@ -66,141 +73,130 @@ var ubd = function(){
* set domid that will by updated * set domid that will by updated
* @param {string} sDomid if of a domobject * @param {string} sDomid if of a domobject
*/ */
this.setDomid = function(sDomid){ setDomid(sDomid) {
if (document.getElementById(sDomid)){ if (document.getElementById(sDomid)) {
this._sDomId=sDomid; this._sDomId = sDomid;
this._oDomObject=document.getElementById(sDomid); this._oDomObject = document.getElementById(sDomid);
} else { } else {
this._sDomId=false; this._sDomId = false;
this._oDomObject=false; this._oDomObject = false;
console.error('ERROR: setDomid("'+sDomid+'") got an invalid string - this domid does not exist.'); 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 * set a rendering function that visualized data after a http request
* @param {string|function} oFunction reference to a function ... or false to disable rendering * @param {string|function} oFunction reference to a function ... or false to disable rendering
*/ */
this.setRenderfunction = function(oFunction){ setRenderfunction (oFunction) {
this._sRenderfunction=oFunction; this._sRenderfunction = oFunction;
}, }
/** /**
* Set time to live in seconds * Set time to live in seconds
* @param {int} iTTL * @param {int} iTTL
*/ */
this.setTtl = function(iTTL){ setTtl(iTTL) {
this._iTTL=iTTL/1; this._iTTL = iTTL / 1;
this.resetTimer(); this.resetTimer();
}, }
/** /**
* set an url to be requested * set an url to be requested
* @param {string|function} sUrl static value or reference of a function * @param {string|function} sUrl static value or reference of a function
*/ */
this.setUrl = function(sUrl){ setUrl(sUrl) {
this._sUrl2Fetch=sUrl; this._sUrl2Fetch = sUrl;
}, }
/** /**
* set header obejct for 2nd param in javascript fetch() function * set header obejct for 2nd param in javascript fetch() function
* @param {object} oHeader * @param {object} oHeader
*/ */
this.setHeaders = function(oHeader){ setHeaders(oHeader) {
this._oHeader=oHeader; this._oHeader = oHeader;
}, }
/** /**
* helper: dump current object instance to console * helper: dump current object instance to console
*/ */
this.dumpme = function(){ dumpme() {
console.log('---------- DUMP ubd'); console.log('---------- DUMP ubd');
console.log(this); console.log(this);
console.log('---------- /DUMP ubd'); console.log('---------- /DUMP ubd');
}, }
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// public ACTIONS // public ACTIONS
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
/** /**
* show rendered html content into set domid using the render function. * show rendered html content into set domid using the render function.
* If no rendering function was set then the response will be written * If no rendering function was set then the response will be written
* directly. * directly.
* You can override both by giving a parameter (a string with html) * 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. * to write that one directly. It can be used to show an error message.
* *
* TODO: * 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. * to use input or textarea.
* *
* @param {string} sHtml optional: htmlcode of an error message * @param {string} sHtml optional: htmlcode of an error message
*/ */
this.render = function(sHtml) { render(sHtml) {
let out = sHtml ? sHtml : let out = sHtml ? sHtml :
(this._sRenderfunction (this._sRenderfunction
? this._sRenderfunction(this._body) ? this._sRenderfunction(this._body)
: this._body : this._body
); );
this._oDomObject.innerHTML=out; this._oDomObject.innerHTML = out;
}, }
/** /**
* reset timer to update the content in dom id after reaching TTL * reset timer to update the content in dom id after reaching TTL
* used in setTtl * used in setTtl
*/ */
this.resetTimer = function(){ resetTimer() {
clearTimeout(this._oTimer); clearTimeout(this._oTimer);
// clearInterval(this._oTimer); // clearInterval(this._oTimer);
if(this._iTTL) { if (this._iTTL) {
let self = this; 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); // self._oTimer=window.setInterval(self.update, this._iTTL*1000);
} }
}, }
/** /**
* make http request and call the renderer * make http request and call the renderer
*/ */
this.update = async function(){ async update() {
let self = this; 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 + "]"); 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) :-/"); console.error("SKIP update - there is no url in this object instance (anymore) :-/");
this.dumpme(); this.dumpme();
return 0; return 0;
} }
try{ try {
let response = await fetch(url, this._oHeader); let response = await fetch(url, this._oHeader);
if (response.ok) { if (response.ok) {
this._body=await response.json(); this._body = await response.json();
this.render(); this.render();
} else { } else {
this.render('<div class="app result1">' this.render('<div class="app result1">'
+'ERROR '+response.status+': '+response.statusText + ' - ' + 'ERROR ' + response.status + ': ' + response.statusText + ' - '
+url + url
+'</div>'); + '</div>');
} }
} catch(e) { } catch (e) {
this.render('<div class="app result1">' this.render('<div class="app result1">'
+'UNKNOWN: no response from ' + 'UNKNOWN: no response from '
+this._sUrl2Fetch + this._sUrl2Fetch
+'</div>'); + '</div>');
console.error(e); console.error(e);
} }
this.resetTimer(); this.resetTimer();
} }
// ----------------------------------------------------------------------
// MAIN }
// ---------------------------------------------------------------------- \ No newline at end of file
if (arguments) {
this.init(arguments[0]);
} else {
this.init();
}
};
\ No newline at end of file
:root{ :root{
--color-0: #345; --color-0: #345;
--color-h1: #abc; --color-h1: #789;
--color-h2: #579; --color-h2: #579;
--color-links: #349; --color-links: #349;
...@@ -19,8 +19,8 @@ body{ ...@@ -19,8 +19,8 @@ body{
font-family: verdana,arial; 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{ 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); border-radius: 0.3em; margin: 0 0.5em 0.5em 0; padding: 0.5em;} button:hover{ background: linear-gradient(#eee, #ccc);}
button:active{ border:1px solid #fc2;} button:active{ border:1px solid #fc2;}
input{ border:1px solid #ccc; padding: 0.4em;} input{ border:1px solid #ccc; padding: 0.4em;}
...@@ -52,7 +52,15 @@ section input[type=checkbox]:checked + label { ...@@ -52,7 +52,15 @@ section input[type=checkbox]:checked + label {
section input[type=checkbox]+ label:hover { section input[type=checkbox]+ label:hover {
border-color: #89a; 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;} td{vertical-align: top;}
#main{ #main{
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment