artdaq_node_server  v1_00_08
 All Classes Namespaces Files Variables Pages
artdaq-daqmon_module.js
1 var Emitter = require('events').EventEmitter;
2 var daqmon = new Emitter();
3 var net = require('net');
4 
5 var config = {
6  durationToStore: 300 // 5 Minutes
7 }
8 
9 var database = {
10  data: {
11  nodes: [
12  { name: "EventBuilders", width: 1, lastUpdate: Date.now(), repvalue: 0, unit: "Fragments/s" },
13  { name: "Data_Logger", width: 1, lastUpdate: Date.now(), repvalue: 0, unit: "Fragments/s" },
14  { name: "Online_Monitor", width: 1, lastUpdate: Date.now(), repvalue: 0, unit: "Fragments/s" }
15  ],
16  links: [
17  { source: "Data_Logger", target: "Online_Monitor", value: 1 }
18  ],
19  metrics: {},
20  avgFragRate: -1.0,
21  fragRateCount: 0
22  }
23 };
24 var locked = false;
25 
26 function checkMetrics() {
27  var now = Date.now();
28  var then = now - config.durationToStore * 1000;
29  for (var h in database.metrics) {
30  if (database.metrics.hasOwnProperty(h)) {
31  var metrics = database.metrics[h];
32  for (var m in metrics) {
33  if (metrics.hasOwnProperty(m)) {
34  var metric = metrics[m];
35  for (var i in metric) {
36  if (metric.hasOwnProperty(i)) {
37  if (metric[i].date < then) {
38  delete database.metrics[h][m][i];
39  } else {
40  break;
41  }
42  }
43  }
44  }
45  }
46  }
47  }
48 }
49 
50 function IndexOfSink(sinkName) {
51  for (var i = 0; i < database.data.links.length; i++) {
52  if (database.data.links[i].target === sinkName) { return i; }
53  }
54  return -1;
55 }
56 
57 function IndexOfLink(sourceName) {
58  for (var i = 0; i < database.data.links.length; i++) {
59  if (database.data.links[i].source === sourceName) { return i; }
60  }
61  return -1;
62 }
63 
64 function IndexOfNode(nodeName) {
65  for (var i = 0; i < database.data.nodes.length; i++) {
66  if (database.data.nodes[i].name === nodeName) { return i; }
67  }
68  return -1;
69 }
70 
71 function startGraphiteListener() {
72  var server = net.createServer(function (socket) {
73  socket.name = socket.remoteAddress + ":" + socket.remotePort;
74  console.log("Received Graphite Client connection from " + socket.name);
75 
76  socket.on('data', function (data) {
77  locked = true;
78  //console.log("Received metric data: " + data);
79  var strdata = "" + data;
80  var mm = strdata.split("\n");
81  for (var m in mm) {
82  if (mm.hasOwnProperty(m)) {
83  var arr = mm[m].trim().split(" ", 3);
84  if (arr[0] !== undefined && arr[1] !== undefined && arr[2] !== undefined) {
85  var dotNot = arr[0].split('.');
86  var appName = dotNot.shift();
87  var value = parseFloat(arr[1]);
88  if (dotNot.length > 0 && dotNot[0].search(/^[0-9]*$/) >= 0) {
89  appName += "." + dotNot.shift();
90  }
91  var metricName = "" + dotNot.join('.');
92  console.log("Application: " + appName + ", Metric: " + metricName + ": " + arr[1] + " at " + arr[2]);
93  if (database.data.metrics[appName] === undefined) {
94  database.data.metrics[appName] = {};
95  }
96  if (database.data.metrics[appName][metricName] === undefined) {
97  database.data.metrics[appName][metricName] = [];
98  }
99  database.data.metrics[appName][metricName].push({ value: arr[1], date: new Date(arr[2] * 1000) });
100  var br = appName.search("BoardReader") >= 0;
101  var eb = appName.search("EventBuilder") >= 0;
102  var nodeIndex = IndexOfNode(appName);
103  if (nodeIndex < 0) {
104  database.data.nodes.push({ name: appName, width: 1, lastUpdate: Date.now(), repvalue: 0, unit: "Fragments/s" });
105  if (br) {
106  database.data.links.push({ source: appName, target: "EventBuilders", value: 1 });
107  }
108  else if (eb) {
109  database.data.links.push({ source: "EventBuilders", target: appName, value: 1 });
110  database.data.links.push({ source: appName, target: "Data_Logger", value: 1 });
111  }
112  nodeIndex = IndexOfNode(appName);
113  }
114 
115  //console.log("NodeIndex is " + nodeIndex);
116  database.data.nodes[nodeIndex].lastUpdate = Date.now();
117 
118  //console.log("Metric name is: " + metricName);
119  if (metricName.search("Data_Rate") >= 0) {
120  //console.log("Data_Rate Metric Found!!!");
121  var link = IndexOfLink(appName);
122  //console.log("Index of link is: " + link);
123  if (link >= 0) {
124  //console.log("Setting value to: " + value);
125  database.data.links[link].value = value;
126  }
127  if (eb) {
128  var sink = IndexOfSink(appName);
129  if (sink >= 0) {
130  database.data.links[sink].value = value;
131  }
132  }
133  }
134  if (metricName.search("Fragment_Rate") >= 0) {
135  //console.log("Fragment_Rate Metric Found!!!");
136  if (nodeIndex >= 0) {
137  if (!eb) {
138  if (database.data.avgFragRate === -1) {
139  database.data.avgFragRate = value;
140  database.data.fragRateCount = 1;
141  } else {
142  database.data.avgFragRate = (database.data.avgFragRate * database.data.fragRateCount + value) / (database.data.fragRateCount + 1);
143  database.data.fragRateCount += 1;
144  }
145  database.data.nodes[nodeIndex].width = value / database.data.avgFragRate;
146  database.data.nodes[nodeIndex].repvalue = value;
147  }
148  }
149  }
150  if (metricName.search("Incomplete_Event_Count") >= 0) {
151  if (nodeIndex >= 0) {
152  database.data.nodes[nodeIndex].width = value / database.data.avgFragRate;
153  database.data.nodes[nodeIndex].repvalue = value;
154  database.data.nodes[nodeIndex].unit = "Incomplete Events";
155  }
156  }
157  }
158  }
159  }
160  locked = false;
161  checkMetrics();
162  daqmon.emit('message', { name: "artdaq-daqmon", target: "data", data: database.data });
163  });
164 
165  socket.on('end', function () {
166  console.log("Graphite Client Disconnected: " + socket.name);
167  });
168  });
169 
170  server.on("error", function (err) {
171  console.log("artdaq-daqmon listen server error:\n" + err.stack);
172  server.close();
173  });
174 
175  console.log("Binding Server to port 2003 (Graphite Listen)");
176  server.listen(2003);
177 }
178 
179 daqmon.Update = function (workerData) {
180  if (!locked) {
181  //console.log("Updating database: " + JSON.stringify(workerData));
182  database = workerData;
183  }
184 }
185 
186 daqmon.GET_Json = function (workerData) {
187  //console.log(JSON.stringify(workerData));
188  return JSON.stringify(workerData.data);
189 }
190 
191 daqmon.MasterInitFunction = function (workerData) {
192 
193  workerData["artdaq-daqmon"] = database;
194 }
195 
196 daqmon.WorkerInitFunction = function (workerData) {
197  startGraphiteListener();
198  return null;
199 }
200 
201 module.exports = function (module_holder) {
202  module_holder["artdaq-daqmon"] = daqmon;
203 };