Classification flow
This is a flow that implements a classification algorithm. This algorithm compares the distance between the three centroids given from the K-means clustering flow and the values inside function object. So like the the flow mentioned above it's possible to run this flow ether as a node red flow or as a Openwhisk function.

Example input
{
"function": {
"owendpoint": "cluster.url",
"actionname": "Inference_3fff08e8-3617-4eb4-b118-4229f30514e3.json",
"cpu": 0.28138695097583194,
"branchname": "Inference",
"flow": "Inference",
"memory": 74014720,
"networkReceived": 131.45833333333331,
"networkTransmitted": 279.4666666666667,
"fsReads": 70729728,
"fsWrites": 28672
},
"cluster": {
"cpu": [
{
"category": "low",
"value": 0.005801420285783651
},
{
"category": "medium",
"value": 0.029655391993717292
},
{
"category": "high",
"value": 0.1852146552507543
}
],
"memory": [
{
"category": "low",
"value": 22821091.555555556
},
{
"category": "medium",
"value": 27701589.333333332
},
{
"category": "high",
"value": 47930026.666666664
}
],
"fsWrites": [
{
"category": "low",
"value": 20480
},
{
"category": "medium",
"value": 285696
},
{
"category": "high",
"value": 454656
}
],
"networkTransmitted": [
{
"category": "low",
"value": 196.98828026984765
},
{
"category": "medium",
"value": 359.94572729706005
},
{
"category": "high",
"value": 495.8401658633009
}
],
"fsReads": [
{
"category": "low",
"value": 12274688
},
{
"category": "medium",
"value": 1494016
},
{
"category": "high",
"value": 49229824
}
],
"networkReceived": [
{
"category": "low",
"value": 173.3337710628692
},
{
"category": "medium",
"value": 663.1380479260863
},
{
"category": "high",
"value": 983.7239894223181
}
]
}
}
In the function object Prometheus performance metrics get inserted and the cluster contains the output of the clustering function
Example output
{
"cpu": "high",
"flow": "Inference",
"fsReads": "high",
"fsWrites": "low",
"memory": "high",
"networkReceived": "low",
"networkTransmitted": "medium"
}
[{"id":"20575d97a6b029d7","type":"tab","label":"Flow 1","disabled":false,"info":"","env":[]},{"id":"db88a51f04879dd0","type":"http in","z":"20575d97a6b029d7","name":"","url":"/run","method":"post","upload":false,"swaggerDoc":"","x":100,"y":400,"wires":[["8fce9a86ec9aee23"]]},{"id":"87227bab870fcdc0","type":"http response","z":"20575d97a6b029d7","name":"","statusCode":"","headers":{},"x":830,"y":400,"wires":[]},{"id":"5d4443c1cb191e7e","type":"http in","z":"20575d97a6b029d7","name":"","url":"/init","method":"post","upload":false,"swaggerDoc":"","x":420,"y":600,"wires":[["55f7187cce540cbf"]]},{"id":"55f7187cce540cbf","type":"http response","z":"20575d97a6b029d7","name":"","statusCode":"","headers":{},"x":590,"y":600,"wires":[]},{"id":"7508518ce4778dba","type":"function","z":"20575d97a6b029d7","name":"ADD ERROR INFO","func":"var payload=msg.payload;\nmsg.payload={};\n\nmsg.payload.error=msg.error;\nmsg.payload.error.payload=payload;\nmsg.statusCode=400;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":630,"y":520,"wires":[["87227bab870fcdc0"]]},{"id":"c50f213dd0a4c70f","type":"function","z":"20575d97a6b029d7","name":"Classifier","func":"const actionName = msg.input.value.actionName;\nconst branchName = msg.input.value.branchName;\nconst location = msg.input.value.location;\nconst flowC = msg.input.value.flow;\n\nfunction compare (resourceType, value){\n if(value==null) return null;\n let clusterFromDatabase = msg.payload[resourceType]\n // { category: 'low', value: 1 },\n // { category: 'medium', value: 2 },\n // { category: 'high', value: 3 }\n\n console.log(msg.payload.cpu)\n let category;\n let diff;\n let min = 10000000000;\n console.log(clusterFromDatabase)\n for (let k = 0; k < clusterFromDatabase.length; k++) {\n diff = Math.abs(clusterFromDatabase[k].value - value);\n if (diff < min) {\n category = clusterFromDatabase[k].category;\n min = diff;\n }\n console.log(clusterFromDatabase[k].category);\n }\n return category; \n}\nvar newPayload = {\n \"actionName\": actionName,\n \"branchName\": branchName,\n \"flow\": flowC,\n \"cpu\": compare(\"cpu\", msg.input.value.cpu),\n \"memory\": compare(\"memory\", msg.input.value.memory),\n \"networkReceived\": compare(\"networkReceived\", msg.input.value.networkReceived),\n \"networkTransmitted\": compare(\"networkTransmitted\", msg.input.value.networkTransmitted),\n \"fsReads\": compare(\"fsReads\", msg.input.value.fsReads),\n \"fsWrites\": compare(\"fsWrites\", msg.input.value.fsWrites),\n \"location\": location\n}\nmsg.payload = newPayload\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":640,"y":400,"wires":[["87227bab870fcdc0","6c526db6eb65acea"]]},{"id":"8fce9a86ec9aee23","type":"change","z":"20575d97a6b029d7","name":"","rules":[{"t":"set","p":"input.value","pt":"msg","to":"payload.value.function","tot":"msg","dc":true},{"t":"set","p":"payload","pt":"msg","to":"payload.value.cluster","tot":"msg","dc":true}],"action":"","property":"","from":"","to":"","reg":false,"x":320,"y":400,"wires":[["46d5d747bc57e7a3"]]},{"id":"6c526db6eb65acea","type":"debug","z":"20575d97a6b029d7","name":"debug 1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":820,"y":360,"wires":[]},{"id":"46d5d747bc57e7a3","type":"function","z":"20575d97a6b029d7","name":"Null Check","func":"\nif ((msg.input.value.cpu==null)&&(msg.input.value.memory==null)&&(msg.input.value.networkReceived==null)&&(msg.input.value.networkTransmitted==null)&&(msg.input.value.fsReads==null)&&(msg.input.value.fsWrites==null)) {\n\n msg.error=\"Null values detected in all input data\";\n msg.payload='Null values detected in all input data';\n\n return [null,msg];\n} else {\n return [msg,null];\n}\n","outputs":2,"noerr":0,"initialize":"","finalize":"","libs":[],"x":490,"y":400,"wires":[["c50f213dd0a4c70f"],["7508518ce4778dba"]]},{"id":"61b1f90e3496851a","type":"catch","z":"20575d97a6b029d7","name":"","scope":null,"uncaught":false,"x":400,"y":520,"wires":[["7508518ce4778dba"]]}]