stats.html 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. <script src="./script/useragent.js"></script>
  2. <div class="standardContainer">
  3. <div class="ui basic segment">
  4. <h2>Statistical Analysis</h2>
  5. <p>Statistic of your server in every aspects</p>
  6. </div>
  7. <div class="ui divider"></div>
  8. <div class="ui basic segment">
  9. <!-- Client Geolocation Analysis-->
  10. <h3>Visitors Countries</h3>
  11. <p>Distributions of visitors by country code. Access origin are estimated using open source GeoIP database and might not be accurate.</p>
  12. <div style="min-height: 400px;">
  13. <canvas id="stats_visitors"></canvas>
  14. </div>
  15. <div class="ui divider"></div>
  16. <!-- Client IP Analysis -->
  17. <div class="ui stackable grid">
  18. <div class="eight wide column">
  19. <h3>Request Client IP Versions</h3>
  20. <p>The version of Internet Protocol that the client is using. If the request client is pass through a DNS proxy like CloudFlare,
  21. the CloudFlare proxy server address will be filtered and only the first value in the RemoteAddress field will be analysised.</p>
  22. <div>
  23. <canvas id="stats_ipver"></canvas>
  24. </div>
  25. </div>
  26. <div class="eight wide column">
  27. <h3>Request Origin Counts</h3>
  28. <p>Top 25 request origin sorted by request count</p>
  29. <div style="height: 500px; overflow-y: auto;">
  30. <table class="ui unstackable striped celled table">
  31. <thead>
  32. <tr>
  33. <th>Request Origin</th>
  34. <th>No of Requests</th>
  35. </tr></thead>
  36. <tbody id="stats_requestCountlist">
  37. </tbody>
  38. </table>
  39. </div>
  40. </div>
  41. </div>
  42. <div class="ui divider"></div>
  43. <!-- Client Device Analysis -->
  44. <div class="ui stackable grid">
  45. <div class="eight wide column">
  46. <h3>Client Devices</h3>
  47. <p>Device type analysis by its request interactions.The number of iteration count does not means the number unique device, as no cookie is used to track the devices identify.</p>
  48. <div>
  49. <canvas id="stats_device"></canvas>
  50. </div>
  51. </div>
  52. <div class="eight wide column">
  53. <h3>Client OS</h3>
  54. <p>The OS where your client is using. Estimated using the UserAgent header sent by the client browser while requesting a resources from one of your host.</p>
  55. <div>
  56. <canvas id="stats_OS"></canvas>
  57. </div>
  58. </div>
  59. </div>
  60. </div>
  61. <button class="ui icon right floated basic button" onclick="initStatisticSummery();"><i class="green refresh icon"></i> Refresh</button>
  62. <br><br>
  63. </div>
  64. <script>
  65. function initStatisticSummery(){
  66. $.getJSON("./example.json", function(data){
  67. //Render visitor data
  68. renderVisitorChart(data.RequestOrigin);
  69. //Render IP versions
  70. renderIPVersionChart(data.RequestClientIp);
  71. //Render user agent analysis
  72. renderUserAgentCharts(data.UserAgent);
  73. });
  74. }
  75. initStatisticSummery();
  76. function renderUserAgentCharts(userAgentsEntries){
  77. let userAgents = Object.keys(userAgentsEntries);
  78. let mobileUser = 0;
  79. let desktopUser = 0;
  80. let osTypes = {};
  81. //Statistics collector
  82. userAgents.forEach(function(thisUA){
  83. var uaInfo = parseUserAgent(thisUA);
  84. if (uaInfo.isMobile){
  85. mobileUser+=userAgentsEntries[thisUA];
  86. }else{
  87. desktopUser+=userAgentsEntries[thisUA];
  88. }
  89. let currentNo = osTypes[uaInfo.os];
  90. if (currentNo == undefined){
  91. osTypes[uaInfo.os] = userAgentsEntries[thisUA];
  92. }else{
  93. osTypes[uaInfo.os] = currentNo + userAgentsEntries[thisUA]
  94. }
  95. });
  96. //Create the device chart
  97. let deviceTypeChart = new Chart(document.getElementById("stats_device"), {
  98. type: 'pie',
  99. data: {
  100. labels: ['Desktop', 'Mobile'],
  101. datasets: [{
  102. data: [desktopUser, mobileUser],
  103. backgroundColor: ['#e56b5e', '#6eb9c1'],
  104. hoverBackgroundColor: ['#e56b5e', '#6eb9c1']
  105. }]
  106. },
  107. options: {
  108. responsive: true,
  109. maintainAspectRatio: false,
  110. }
  111. });
  112. //Create the OS chart
  113. let OSnames = [];
  114. let OSCounts = [];
  115. let OSColors = [];
  116. for (const [key, value] of Object.entries(osTypes)) {
  117. OSnames.push(key);
  118. OSCounts.push(value);
  119. OSColors.push(getOSColorCode(key));
  120. }
  121. let osTypeChart = new Chart(document.getElementById("stats_OS"), {
  122. type: 'pie',
  123. data: {
  124. labels: OSnames,
  125. datasets: [{
  126. data: OSCounts,
  127. backgroundColor: OSColors,
  128. hoverBackgroundColor: OSColors
  129. }]
  130. },
  131. options: {
  132. responsive: true,
  133. maintainAspectRatio: false,
  134. }
  135. });
  136. console.log(osTypes);
  137. }
  138. //Generate the IPversion pie chart
  139. function renderIPVersionChart(RequestClientIp){
  140. let ipv4Count = Object.keys(RequestClientIp).filter(ip => ip.includes('.')).length;
  141. let ipv6Count = Object.keys(RequestClientIp).filter(ip => ip.includes(':')).length;
  142. let totalCount = ipv4Count + ipv6Count;
  143. let ipv4Percent = ((ipv4Count / totalCount) * 100).toFixed(2);
  144. let ipv6Percent = ((ipv6Count / totalCount) * 100).toFixed(2);
  145. // Create the chart data object
  146. let chartData = {
  147. labels: ['IPv4', 'IPv6'],
  148. datasets: [{
  149. data: [ipv4Percent, ipv6Percent],
  150. backgroundColor: ['#9295f0', '#bff092'],
  151. hoverBackgroundColor: ['#9295f0', '#bff092']
  152. }]
  153. };
  154. // Create the chart options object
  155. let ipvChartOption = {
  156. responsive: true,
  157. maintainAspectRatio: false,
  158. };
  159. // Create the pie chart
  160. let ipTypeChart = new Chart(document.getElementById("stats_ipver"), {
  161. type: 'pie',
  162. data: chartData,
  163. options: ipvChartOption
  164. });
  165. //Populate the request count table
  166. let requestCounts = Object.entries(RequestClientIp);
  167. // Sort the array by the value (count)
  168. requestCounts.sort((a, b) => b[1] - a[1]);
  169. // Select the table body and empty it
  170. let tableBody = $('#stats_requestCountlist');
  171. tableBody.empty();
  172. // Loop through the sorted array and add the top 25 requested IPs to the table
  173. for (let i = 0; i < 25 && i < requestCounts.length; i++) {
  174. let [ip, count] = requestCounts[i];
  175. let row = $('<tr>').appendTo(tableBody);
  176. $('<td style="word-break: break-all;">').text(ip).appendTo(row);
  177. $('<td>').text(count).appendTo(row);
  178. }
  179. }
  180. //Generate a fixed color code from string hash
  181. function generateColorFromHash(stringToHash){
  182. let hash = 0;
  183. for (let i = 0; i < stringToHash.length; i++) {
  184. hash = stringToHash.charCodeAt(i) + ((hash << 5) - hash);
  185. }
  186. const hue = hash % 300;
  187. const saturation = Math.floor(Math.random() * 20) + 70;
  188. const lightness = Math.floor(Math.random() * 20) + 60;
  189. return `hsl(${hue}, ${saturation}%, ${lightness}%)`;
  190. }
  191. //Generate the visitor country pie chart
  192. function renderVisitorChart(visitorData){
  193. // Extract the labels and data from the visitor data object
  194. let labels = [];
  195. let data = Object.values(visitorData);
  196. Object.keys(visitorData).forEach(function(cc){
  197. if (cc == ""){
  198. labels.push("Local / Unknown")
  199. }else{
  200. labels.push(`${getCountryName(cc)} [${cc.toUpperCase()}]` );
  201. }
  202. });
  203. // Define the colors to be used in the pie chart
  204. let colors = [];
  205. labels.forEach(function(cc){
  206. colors.push(generateColorFromHash(cc));
  207. });
  208. // Create the chart data object
  209. let CCchartData = {
  210. labels: labels,
  211. datasets: [{
  212. data: data,
  213. backgroundColor: colors
  214. }]
  215. };
  216. // Create the chart options object
  217. let CCchartOptions = {
  218. responsive: true,
  219. maintainAspectRatio: false,
  220. };
  221. // Create the pie chart
  222. const visitorsChart = new Chart(document.getElementById("stats_visitors"), {
  223. type: 'pie',
  224. data: CCchartData,
  225. options: CCchartOptions
  226. });
  227. }
  228. </script>