metrics.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. import { Meteor } from 'meteor/meteor';
  2. import Users from '../users';
  3. function acceptedIpAddress(ipAddress) {
  4. const trustedIpAddress = process.env.WEKAN_METRICS_ACCEPTED_IP_ADDRESS;
  5. return (
  6. trustedIpAddress !== undefined &&
  7. trustedIpAddress.split(',').includes(ipAddress)
  8. );
  9. }
  10. const getBoardIdWithMostActivities = (dateWithXdaysAgo, nbLimit) => {
  11. return Promise.await(
  12. Activities.rawCollection()
  13. .aggregate([
  14. {
  15. $match: {
  16. modifiedAt: { $gte: dateWithXdaysAgo },
  17. },
  18. },
  19. { $group: { _id: '$boardId', count: { $sum: 1 } } },
  20. { $sort: { count: -1 } },
  21. ])
  22. .limit(nbLimit)
  23. .toArray(),
  24. );
  25. };
  26. const getBoards = (boardIds) => {
  27. return Boards.find({ _id: { $in: boardIds } }).fetch();
  28. };
  29. Meteor.startup(() => {
  30. WebApp.connectHandlers.use('/metrics', (req, res, next) => {
  31. try {
  32. const ipAddress =
  33. req.headers['x-forwarded-for'] || req.socket.remoteAddress;
  34. // if(process.env.TRUST_PROXY_FORXARD)
  35. // {
  36. // const ipAddress = req.headers['x-forwarded-for'] || req.socket.remoteAddress
  37. // }else{
  38. // const ipAddress = req.socket.remoteAddress
  39. // }
  40. // List of trusted ip adress will be found in environment variable "WEKAN_METRICS_ACCEPTED_IP_ADDRESS" (separeted with commas)
  41. if (acceptedIpAddress(ipAddress)) {
  42. let metricsRes = '';
  43. let resCount = 0;
  44. //connected users
  45. metricsRes += '# Number of connected users\n';
  46. // Get number of connected user by using meteor socketJs
  47. const allOpenedSockets = Meteor.server.stream_server.open_sockets;
  48. let connectedUserIds = [];
  49. allOpenedSockets.forEach(
  50. (socket) =>
  51. socket._meteorSession.userId !== null &&
  52. connectedUserIds.push(socket._meteorSession.userId),
  53. );
  54. resCount = connectedUserIds.length; // KPI 1
  55. metricsRes += 'wekan_connectedUsers ' + resCount + '\n';
  56. //registered users
  57. metricsRes += '# Number of registered users\n';
  58. // Get number of registered user
  59. resCount = Users.find({}).count(); // KPI 2
  60. metricsRes += 'wekan_registeredUsers ' + resCount + '\n';
  61. resCount = 0;
  62. //board numbers
  63. metricsRes += '# Number of registered boards\n';
  64. // Get number of registered boards
  65. resCount = Boards.find({ archived: false, type: 'board' }).count(); // KPI 3
  66. metricsRes += 'wekan_registeredboards ' + resCount + '\n';
  67. resCount = 0;
  68. //board numbers by registered users
  69. metricsRes += '# Number of registered boards by registered users\n';
  70. // Get number of registered boards by registered users
  71. resCount =
  72. Boards.find({ archived: false, type: 'board' }).count() /
  73. Users.find({}).count(); // KPI 4
  74. metricsRes +=
  75. 'wekan_registeredboardsBysRegisteredUsers ' + resCount + '\n';
  76. resCount = 0;
  77. //board numbers with only one member
  78. metricsRes += '# Number of registered boards\n';
  79. // Get board numbers with only one member
  80. resCount = Boards.find({
  81. archived: false,
  82. type: 'board',
  83. members: { $size: 1 },
  84. }).count(); // KPI 5
  85. metricsRes +=
  86. 'wekan_registeredboardsWithOnlyOneMember ' + resCount + '\n';
  87. resCount = 0;
  88. // KPI 6 : - store last login date
  89. // KPI 6 = count where date of last connection > x days
  90. // Cutting in label since 5 days / 10 days / 20 days / 30 days
  91. //Number of users with last connection dated 5 days ago
  92. metricsRes +=
  93. '# Number of users with last connection dated 5 days ago\n';
  94. // Get number of users with last connection dated 5 days ago
  95. let xdays = 5;
  96. let dateWithXdaysAgo = new Date(
  97. new Date() - xdays * 24 * 60 * 60 * 1000,
  98. );
  99. resCount = Users.find({
  100. lastConnectionDate: { $gte: dateWithXdaysAgo },
  101. }).count(); // KPI 5
  102. metricsRes +=
  103. 'wekan_usersWithLastConnectionDated5DaysAgo ' + resCount + '\n';
  104. resCount = 0;
  105. metricsRes +=
  106. '# Number of users with last connection dated 10 days ago\n';
  107. // Get number of users with last connection dated 10 days ago
  108. xdays = 10;
  109. dateWithXdaysAgo = new Date(new Date() - xdays * 24 * 60 * 60 * 1000);
  110. resCount = Users.find({
  111. lastConnectionDate: { $gte: dateWithXdaysAgo },
  112. }).count(); // KPI 5
  113. metricsRes +=
  114. 'wekan_usersWithLastConnectionDated10DaysAgo ' + resCount + '\n';
  115. resCount = 0;
  116. metricsRes +=
  117. '# Number of users with last connection dated 20 days ago\n';
  118. // Get number of users with last connection dated 20 days ago
  119. xdays = 20;
  120. dateWithXdaysAgo = new Date(new Date() - xdays * 24 * 60 * 60 * 1000);
  121. resCount = Users.find({
  122. lastConnectionDate: { $gte: dateWithXdaysAgo },
  123. }).count(); // KPI 5
  124. metricsRes +=
  125. 'wekan_usersWithLastConnectionDated20DaysAgo ' + resCount + '\n';
  126. resCount = 0;
  127. metricsRes +=
  128. '# Number of users with last connection dated 30 days ago\n';
  129. // Get number of users with last connection dated 20 days ago
  130. xdays = 30;
  131. dateWithXdaysAgo = new Date(new Date() - xdays * 24 * 60 * 60 * 1000);
  132. resCount = Users.find({
  133. lastConnectionDate: { $gte: dateWithXdaysAgo },
  134. }).count(); // KPI 5
  135. metricsRes +=
  136. 'wekan_usersWithLastConnectionDated30DaysAgo ' + resCount + '\n';
  137. resCount = 0;
  138. // TO DO:
  139. // connection average: ((disconnection date - last connection date) + (last average)) / 2
  140. // KPI 7 : sum of connection average / number of users (ignore users with 0 average)
  141. metricsRes +=
  142. '# Top 10 boards with most activities dated 30 days ago\n';
  143. //Get top 10 table with most activities in current month
  144. const boardIdWithMostActivities = getBoardIdWithMostActivities(
  145. dateWithXdaysAgo,
  146. xdays,
  147. );
  148. const boardWithMostActivities = boardIdWithMostActivities.map(
  149. (board) => board._id,
  150. );
  151. getBoards(boardWithMostActivities).forEach((board, index) => {
  152. metricsRes +=
  153. `wekan_top10BoardsWithMostActivities{n="${board.title}"} ${
  154. index + 1
  155. }` + '\n';
  156. });
  157. res.writeHead(200); // HTTP status
  158. res.end(metricsRes);
  159. } else {
  160. res.writeHead(401); // HTTP status
  161. res.end(
  162. 'IpAddress: ' +
  163. ipAddress +
  164. ' is not authorized to perform this action !!\n',
  165. );
  166. }
  167. } catch (e) {
  168. res.writeHead(500); // HTTP status
  169. res.end(e.toString());
  170. }
  171. });
  172. });