A node-red proxy for rewriting HCL Domino STATPUB for Prometheus scraping
Inspired by this idea on the Domino Product Idea Portal I wanted to find a workaround.
In this workaround we will have a HCL Domino server post statistics to a URL on a Node-Red instance every minute. We will transform the data so it matches a Prometheus metrics scrape file. The data will be stored in a local file. Whenever Prometheus scrapes for new data, the cached data will be loaded from the local file. This will allow Prometheus to store the Domino statistics in its time series database. You can then use these statistics in a Grafana dashboard.


[{"id":"768e450440ab2925","type":"http in","z":"a9dd5084d410833d","name":"/input","url":"/input","method":"post","upload":false,"swaggerDoc":"","x":70,"y":100,"wires":[["3acc17685efa8c40","0cb81ed176f50e89","0073b494804b6d87"]]},{"id":"3acc17685efa8c40","type":"debug","z":"a9dd5084d410833d","name":"Data coming in from POST request","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":480,"y":100,"wires":[]},{"id":"0cb81ed176f50e89","type":"http response","z":"a9dd5084d410833d","name":"","statusCode":"200","headers":{},"x":280,"y":140,"wires":[]},{"id":"1f13aa3fd3bb9424","type":"catch","z":"a9dd5084d410833d","name":"","scope":null,"uncaught":false,"x":80,"y":40,"wires":[["1e117308e198c883"]]},{"id":"1e117308e198c883","type":"debug","z":"a9dd5084d410833d","name":"Error","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":390,"y":40,"wires":[]},{"id":"e2be8f5ee7363b3b","type":"split","z":"a9dd5084d410833d","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":130,"y":260,"wires":[["9ff1b126427f0ff1","3a5422b552b63a67"]]},{"id":"9ff1b126427f0ff1","type":"debug","z":"a9dd5084d410833d","name":"splits file into messages per line","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":470,"y":260,"wires":[]},{"id":"3a5422b552b63a67","type":"function","z":"a9dd5084d410833d","name":"","func":"var oldstring = msg.payload.strValue;\nvar newstring;\n// replace dot with underscore\nnewstring = oldstring.replace(/\\./g,'_');\n// remove all slashes\nnewstring = newstring.replace(/\\//g,'');\n// replace bracket open with underscore\nnewstring = newstring.replace(/\\(/g,'_');\n// replace brakcet close with underscore\nnewstring = newstring.replace(/\\)/g,'_');\n// replace minus with underscore\nnewstring = newstring.replace(/\\-/g,'_');\n// replace # with underscore\nnewstring = newstring.replace(/\\#/g,'_');\n// replace [ with underscore\nnewstring = newstring.replace(/\\[/g,'_');\n// replace ] with underscore\nnewstring = newstring.replace(/\\]/g,'_');\n// replace = with underscore\nnewstring = newstring.replace(/\\=/g,'_');\nmsg.payload.strValue = newstring;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":160,"y":300,"wires":[["10b3b4ae98afcc42","32fbadc3160e51f8"]]},{"id":"10b3b4ae98afcc42","type":"debug","z":"a9dd5084d410833d","name":"transform the key name","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":450,"y":300,"wires":[]},{"id":"32fbadc3160e51f8","type":"join","z":"a9dd5084d410833d","name":"","mode":"auto","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":true,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":170,"y":340,"wires":[["8001057a5e1e8481","e972eb2d59d1f5ed"]]},{"id":"8001057a5e1e8481","type":"debug","z":"a9dd5084d410833d","name":"re-join data into array","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":440,"y":340,"wires":[]},{"id":"0073b494804b6d87","type":"json","z":"a9dd5084d410833d","name":"Make it a JavaScript-Object","property":"payload","action":"obj","pretty":false,"x":160,"y":180,"wires":[["043f65695f368944","cf7567c52e33db70"]]},{"id":"043f65695f368944","type":"debug","z":"a9dd5084d410833d","name":"Show me the JSON","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":430,"y":180,"wires":[]},{"id":"cf7567c52e33db70","type":"change","z":"a9dd5084d410833d","name":"Move metrics to payload","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.metrics","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":170,"y":220,"wires":[["77bad860f9e3b5a4","e2be8f5ee7363b3b"]]},{"id":"77bad860f9e3b5a4","type":"debug","z":"a9dd5084d410833d","name":"Show me the metrics JSON","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":460,"y":220,"wires":[]},{"id":"e972eb2d59d1f5ed","type":"csv","z":"a9dd5084d410833d","name":"","sep":" ","hdrin":"","hdrout":"none","multi":"one","ret":"\\n","temp":"","skip":"0","strings":true,"include_empty_strings":"","include_null_values":"","x":130,"y":400,"wires":[["57906ce643dc8b52","77c8fccfea81d151"]]},{"id":"57906ce643dc8b52","type":"debug","z":"a9dd5084d410833d","name":"convert to CSV","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":420,"y":400,"wires":[]},{"id":"77c8fccfea81d151","type":"file","z":"a9dd5084d410833d","name":"","filename":"/tmp/metrics_url.csv","appendNewline":true,"createDir":false,"overwriteFile":"true","encoding":"none","x":200,"y":440,"wires":[["f83f467469337c35"]]},{"id":"f83f467469337c35","type":"debug","z":"a9dd5084d410833d","name":"export to file","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":410,"y":440,"wires":[]},{"id":"61e98968f03daab9","type":"http in","z":"a9dd5084d410833d","name":"/metrics","url":"/metrics","method":"get","upload":false,"swaggerDoc":"","x":100,"y":500,"wires":[["2fb1c354.d04e3c","1551bb5dbc4dedf8"]]},{"id":"2fb1c354.d04e3c","type":"file in","z":"a9dd5084d410833d","name":"","filename":"/tmp/metrics_url.csv","format":"","allProps":false,"x":180,"y":540,"wires":[["88974243.7768c","61525ba86a556f86"]]},{"id":"88974243.7768c","type":"http response","z":"a9dd5084d410833d","name":"","x":150,"y":580,"wires":[]},{"id":"1551bb5dbc4dedf8","type":"debug","z":"a9dd5084d410833d","name":"Prometheus scraping our URL","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":470,"y":500,"wires":[]},{"id":"61525ba86a556f86","type":"debug","z":"a9dd5084d410833d","name":"Content of CSV file","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":430,"y":540,"wires":[]},{"id":"bcb5b54d743a4cc2","type":"comment","z":"a9dd5084d410833d","name":"notes.ini","info":"# Change next line using the URL of your Node-Red installation\nSTATPUB_URI=http://node-red.traefik-proxy:1880/input\nSTATPUB_ENABLE=1\nSTATPUB_HEADERS=Content-type: application/json\nSTATPUB_DATA_HEAD={\"agent_payload_version\": 1.0, \"plugin_textkey\": \"at.brandlehner.chris.dominostats\", \"plugin_category_name\": \"Domino Statistics\", \"metrics\": [$Newline$\nSTATPUB_METRIC_FORMAT={\"strValue\": \"$Name$\", \"numValue\": $Value$}\nSTATPUB_DELTA_METRIC_FORMAT={\"strValue\": \"Rate.$Name$\", \"numValue\": $Value$}","x":100,"y":620,"wires":[]}]