mirror of
https://git.teknik.io/Teknikode/Teknik.git
synced 2023-08-02 14:16:22 +02:00
Moved visitor history to status page from transparency page.
This commit is contained in:
parent
2c972f1a83
commit
904f3c167f
@ -46,6 +46,9 @@ namespace Teknik
|
||||
bundles.Add(new CdnScriptBundle("~/bundles/markdown", config.CdnHost).Include(
|
||||
"~/Scripts/PageDown/Markdown.Converter.js",
|
||||
"~/Scripts/PageDown/Markdown.Sanitizer.js"));
|
||||
|
||||
bundles.Add(new CdnScriptBundle("~/bundles/signalr", config.CdnHost).Include(
|
||||
"~/Scripts/jquery.signalR-{version}.js"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ using Teknik.Attributes;
|
||||
using Teknik.Controllers;
|
||||
using Teknik.Filters;
|
||||
using Teknik.Models;
|
||||
using Teknik.Piwik;
|
||||
using Teknik.Utilities;
|
||||
|
||||
namespace Teknik.Areas.Status.Controllers
|
||||
@ -29,99 +30,48 @@ namespace Teknik.Areas.Status.Controllers
|
||||
StatusViewModel model = new StatusViewModel();
|
||||
|
||||
// Load initial status info
|
||||
Upload.Models.Upload upload = db.Uploads.OrderByDescending(u => u.UploadId).FirstOrDefault();
|
||||
model.UploadCount = (upload != null) ? upload.UploadId : 0;
|
||||
model.UploadSize = (upload != null) ? db.Uploads.Sum(u => (long)u.ContentLength) : 0;
|
||||
|
||||
Paste.Models.Paste paste = db.Pastes.OrderByDescending(p => p.PasteId).FirstOrDefault();
|
||||
model.PasteCount = (paste != null) ? paste.PasteId : 0;
|
||||
|
||||
Users.Models.User user = db.Users.OrderByDescending(u => u.UserId).FirstOrDefault();
|
||||
model.UserCount = (user != null) ? user.UserId : 0;
|
||||
|
||||
Shortener.Models.ShortenedUrl url = db.ShortenedUrls.OrderByDescending(s => s.ShortenedUrlId).FirstOrDefault();
|
||||
model.ShortenedUrlCount = (url != null) ? url.ShortenedUrlId : 0;
|
||||
|
||||
Vault.Models.Vault vault = db.Vaults.OrderByDescending(v => v.VaultId).FirstOrDefault();
|
||||
model.VaultCount = (url != null) ? vault.VaultId : 0;
|
||||
|
||||
return View(model);
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
public ActionResult GetUsage()
|
||||
public ActionResult GetVisitorData()
|
||||
{
|
||||
try
|
||||
// Get the data from the Piwik
|
||||
if (!string.IsNullOrEmpty(Config.PiwikConfig.API))
|
||||
{
|
||||
float totalCPUValue = 0;
|
||||
float webCPUValue = 0;
|
||||
float dbCPUValue = 0;
|
||||
List<VisitorData> dataList = Reporting.GetVisitSummaryByDays(Config, 31);
|
||||
|
||||
float totalMem = 0;
|
||||
float totalAvailMemValue = 0;
|
||||
float totalUsedMemValue = 0;
|
||||
float webMemValue = 0;
|
||||
float dbMemValue = 0;
|
||||
List<object> uniqueData = new List<object>();
|
||||
List<object> totalData = new List<object>();
|
||||
|
||||
float bytesSent = 0;
|
||||
float bytesReceived = 0;
|
||||
|
||||
// CPU
|
||||
using (PerformanceCounter totalCPU = new PerformanceCounter("Processor", "% Processor Time", "_Total", true))
|
||||
using (PerformanceCounter webCPU = new PerformanceCounter("Process", "% Processor Time", Process.GetCurrentProcess().ProcessName, true))
|
||||
using (PerformanceCounter dbCPU = new PerformanceCounter("Process", "% Processor Time", Config.StatusConfig.DatabaseProcessName, true))
|
||||
// Memory
|
||||
using (PerformanceCounter totalAvailMem = new PerformanceCounter("Memory", "Available Bytes", true))
|
||||
using (PerformanceCounter webMem = new PerformanceCounter("Process", "Private Bytes", Process.GetCurrentProcess().ProcessName, true))
|
||||
using (PerformanceCounter dbMem = new PerformanceCounter("Process", "Private Bytes", Config.StatusConfig.DatabaseProcessName, true))
|
||||
// Network
|
||||
using (PerformanceCounter sentPerf = new PerformanceCounter("Network Interface", "Bytes Sent/sec", Config.StatusConfig.NetworkInterface, true))
|
||||
using (PerformanceCounter receivedPerf = new PerformanceCounter("Network Interface", "Bytes Received/sec", Config.StatusConfig.NetworkInterface, true))
|
||||
foreach (VisitorData data in dataList.OrderBy(d => d.Date))
|
||||
{
|
||||
// CPU Sample
|
||||
totalCPU.NextValue();
|
||||
if (Config.StatusConfig.ShowWebStatus)
|
||||
{
|
||||
webCPU.NextValue();
|
||||
}
|
||||
if (Config.StatusConfig.ShowDatabaseStatus)
|
||||
{
|
||||
dbCPU.NextValue();
|
||||
}
|
||||
|
||||
// Network Sample
|
||||
sentPerf.NextValue();
|
||||
receivedPerf.NextValue();
|
||||
|
||||
// Wait the sample time
|
||||
Thread.Sleep(1000);
|
||||
|
||||
// CPU Values
|
||||
totalCPUValue = totalCPU.NextValue();
|
||||
if (Config.StatusConfig.ShowWebStatus)
|
||||
{
|
||||
webCPUValue = webCPU.NextValue();
|
||||
}
|
||||
if (Config.StatusConfig.ShowDatabaseStatus)
|
||||
{
|
||||
dbCPUValue = dbCPU.NextValue();
|
||||
}
|
||||
|
||||
// Memory Values
|
||||
totalMem = Config.StatusConfig.TotalMemory;
|
||||
totalAvailMemValue = totalAvailMem.NextValue();
|
||||
totalUsedMemValue = totalMem - totalAvailMemValue;
|
||||
if (Config.StatusConfig.ShowWebStatus)
|
||||
{
|
||||
webMemValue = webMem.NextValue();
|
||||
}
|
||||
if (Config.StatusConfig.ShowDatabaseStatus)
|
||||
{
|
||||
dbMemValue = dbMem.NextValue();
|
||||
}
|
||||
|
||||
// Network Values
|
||||
bytesSent = sentPerf.NextValue();
|
||||
bytesReceived = receivedPerf.NextValue();
|
||||
|
||||
// Return usage info
|
||||
return Json(new { result = new {
|
||||
cpu = new { total = totalCPUValue, web = webCPUValue, db = dbCPUValue },
|
||||
memory = new { total = totalMem, totalAvail = totalAvailMemValue, totalUsed = totalUsedMemValue, webUsed = webMemValue, dbUsed = dbMemValue },
|
||||
network = new { sent = bytesSent, received = bytesReceived }
|
||||
} }, JsonRequestBehavior.AllowGet);
|
||||
object uniqueDay = new { x = Convert.ToInt64((data.Date.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds), y = data.UniqueVisitors };
|
||||
uniqueData.Add(uniqueDay);
|
||||
object totalDay = new { x = Convert.ToInt64((data.Date.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds), y = data.Visits };
|
||||
totalData.Add(totalDay);
|
||||
}
|
||||
|
||||
return Json(new { result = new { uniqueVisitors = uniqueData.ToArray(), totalVisitors = totalData.ToArray() } }, JsonRequestBehavior.AllowGet);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Json(new { error = new { message = ex.GetFullMessage(true) } }, JsonRequestBehavior.AllowGet);
|
||||
}
|
||||
return Json(new { error = new { message = "Piwik not configured" } }, JsonRequestBehavior.AllowGet);
|
||||
}
|
||||
}
|
||||
}
|
@ -3,6 +3,9 @@ var memUsageChart;
|
||||
var networkUsageChart;
|
||||
|
||||
$(document).ready(function () {
|
||||
/* ----------------------------------------
|
||||
CPU Usage
|
||||
-----------------------------------------*/
|
||||
cpuUsageChart = new Highcharts.chart({
|
||||
chart: {
|
||||
useUTC: false,
|
||||
@ -51,6 +54,9 @@ $(document).ready(function () {
|
||||
]
|
||||
});
|
||||
|
||||
/* ----------------------------------------
|
||||
Memory usage
|
||||
-----------------------------------------*/
|
||||
memUsageChart = new Highcharts.chart({
|
||||
chart: {
|
||||
useUTC: false,
|
||||
@ -108,6 +114,9 @@ $(document).ready(function () {
|
||||
]
|
||||
});
|
||||
|
||||
/* ----------------------------------------
|
||||
Network Usage
|
||||
-----------------------------------------*/
|
||||
networkUsageChart = new Highcharts.chart({
|
||||
chart: {
|
||||
useUTC: false,
|
||||
@ -159,58 +168,110 @@ $(document).ready(function () {
|
||||
]
|
||||
});
|
||||
|
||||
// Fire Off the request data
|
||||
requestData();
|
||||
});
|
||||
|
||||
function requestData() {
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: getUsageURL,
|
||||
success: function (response) {
|
||||
if (response.result) {
|
||||
// Tick Time
|
||||
var x = (new Date()).getTime();
|
||||
|
||||
// CPU Usage
|
||||
cpuUsageChart.series[0].addPoint([x, response.result.cpu.total], false, cpuUsageChart.series[0].data.length > 20);
|
||||
if (showWebCPU) {
|
||||
cpuUsageChart.series[1].addPoint([x, response.result.cpu.web], false, cpuUsageChart.series[1].data.length > 20);
|
||||
}
|
||||
if (showDatabaseCPU) {
|
||||
cpuUsageChart.series[2].addPoint([x, response.result.cpu.db], false, cpuUsageChart.series[2].data.length > 20);
|
||||
}
|
||||
|
||||
// Database Usage
|
||||
memUsageChart.series[0].addPoint([x, response.result.memory.totalUsed], false, memUsageChart.series[0].data.length > 20);
|
||||
if (showWebCPU) {
|
||||
memUsageChart.series[1].addPoint([x, response.result.memory.webUsed], false, memUsageChart.series[1].data.length > 20);
|
||||
}
|
||||
if (showDatabaseCPU) {
|
||||
memUsageChart.series[2].addPoint([x, response.result.memory.dbUsed], false, memUsageChart.series[2].data.length > 20);
|
||||
}
|
||||
|
||||
// Network Usage
|
||||
networkUsageChart.series[0].addPoint([x, response.result.network.sent], false, networkUsageChart.series[0].data.length > 20);
|
||||
networkUsageChart.series[1].addPoint([x, response.result.network.received], false, networkUsageChart.series[1].data.length > 20);
|
||||
|
||||
// Redraw the charts
|
||||
cpuUsageChart.redraw();
|
||||
memUsageChart.redraw();
|
||||
networkUsageChart.redraw();
|
||||
|
||||
// call it again right away
|
||||
setTimeout(requestData, 100);
|
||||
}
|
||||
else {
|
||||
var err = response;
|
||||
if (response.error) {
|
||||
err = response.error.message;
|
||||
}
|
||||
$("#top_msg").css('display', 'inline', 'important');
|
||||
$("#top_msg").html('<div class="alert alert-danger alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>' + err + '</div>');
|
||||
/* ----------------------------------------
|
||||
Visitor History
|
||||
-----------------------------------------*/
|
||||
visitChart = new Highcharts.chart({
|
||||
chart: {
|
||||
renderTo: 'visitor-chart'
|
||||
},
|
||||
title: {
|
||||
text: 'Daily Visitors'
|
||||
},
|
||||
xAxis: {
|
||||
type: 'datetime',
|
||||
dateTimeLabelFormats: { // don't display the dummy year
|
||||
month: '%e. %b',
|
||||
year: '%b'
|
||||
},
|
||||
title: {
|
||||
text: 'Date'
|
||||
}
|
||||
},
|
||||
cache: false
|
||||
yAxis: {
|
||||
title: {
|
||||
text: 'Visitors'
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
shared: true,
|
||||
crosshairs: true,
|
||||
headerFormat: '<span style="font-size: 10px">{point.key:%B %e, %Y}</span><br/>',
|
||||
pointFormat: '<span style="color:{point.color}">\u25CF</span> {series.name}: <b>{point.y}</b><br/>'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: 'All Visitors',
|
||||
data: []
|
||||
},
|
||||
{
|
||||
name: 'Unique Visitors',
|
||||
data: []
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------
|
||||
Websocket for updating realtime stats
|
||||
-----------------------------------------*/
|
||||
var ticker = $.connection.serverUsage;
|
||||
|
||||
ticker.client.updateServerUsage = function (serverUsage) {
|
||||
// Tick Time
|
||||
var x = (new Date()).getTime();
|
||||
|
||||
// CPU Usage
|
||||
cpuUsageChart.series[0].addPoint([x, serverUsage.cpu.total], false, cpuUsageChart.series[0].data.length > 20);
|
||||
if (showWebCPU) {
|
||||
cpuUsageChart.series[1].addPoint([x, serverUsage.cpu.website], false, cpuUsageChart.series[1].data.length > 20);
|
||||
}
|
||||
if (showDatabaseCPU) {
|
||||
cpuUsageChart.series[2].addPoint([x, serverUsage.cpu.database], false, cpuUsageChart.series[2].data.length > 20);
|
||||
}
|
||||
|
||||
// Database Usage
|
||||
memUsageChart.series[0].addPoint([x, serverUsage.memory.used], false, memUsageChart.series[0].data.length > 20);
|
||||
if (showWebCPU) {
|
||||
memUsageChart.series[1].addPoint([x, serverUsage.memory.websiteUsed], false, memUsageChart.series[1].data.length > 20);
|
||||
}
|
||||
if (showDatabaseCPU) {
|
||||
memUsageChart.series[2].addPoint([x, serverUsage.memory.databaseUsed], false, memUsageChart.series[2].data.length > 20);
|
||||
}
|
||||
|
||||
// Network Usage
|
||||
networkUsageChart.series[0].addPoint([x, serverUsage.network.sent], false, networkUsageChart.series[0].data.length > 20);
|
||||
networkUsageChart.series[1].addPoint([x, serverUsage.network.received], false, networkUsageChart.series[1].data.length > 20);
|
||||
|
||||
// Redraw the charts
|
||||
cpuUsageChart.redraw();
|
||||
memUsageChart.redraw();
|
||||
networkUsageChart.redraw();
|
||||
}
|
||||
|
||||
$.connection.hub.start();
|
||||
|
||||
/* ----------------------------------------
|
||||
Load the data for Visitor History
|
||||
-----------------------------------------*/
|
||||
if (showVisitorStats) {
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: getVisitorDataURL,
|
||||
success: function (response) {
|
||||
if (response.result) {
|
||||
visitChart.series[0].setData(response.result.totalVisitors);
|
||||
visitChart.series[1].setData(response.result.uniqueVisitors);
|
||||
}
|
||||
else {
|
||||
var err = response;
|
||||
if (response.error) {
|
||||
err = response.error.message;
|
||||
}
|
||||
$("#top_msg").css('display', 'inline', 'important');
|
||||
$("#top_msg").html('<div class="alert alert-danger alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>' + err + '</div>');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
@ -2,11 +2,33 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Teknik.Models;
|
||||
using Teknik.ViewModels;
|
||||
|
||||
namespace Teknik.Areas.Status.ViewModels
|
||||
{
|
||||
public class StatusViewModel : ViewModelBase
|
||||
{
|
||||
public int UploadCount { get; set; }
|
||||
|
||||
public long UploadSize { get; set; }
|
||||
|
||||
public int PasteCount { get; set; }
|
||||
|
||||
public int UserCount { get; set; }
|
||||
|
||||
public int ShortenedUrlCount { get; set; }
|
||||
|
||||
public int VaultCount { get; set; }
|
||||
|
||||
public StatusViewModel()
|
||||
{
|
||||
UploadCount = 0;
|
||||
UploadSize = 0;
|
||||
PasteCount = 0;
|
||||
UserCount = 0;
|
||||
ShortenedUrlCount = 0;
|
||||
VaultCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,16 +1,20 @@
|
||||
@model Teknik.Areas.Status.ViewModels.StatusViewModel
|
||||
|
||||
@using Teknik.Utilities
|
||||
@using Newtonsoft.Json
|
||||
|
||||
@Scripts.Render("~/bundles/signalr")
|
||||
@Scripts.Render("~/signalr/hubs")
|
||||
@Scripts.Render("~/bundles/status")
|
||||
|
||||
<script type="text/javascript">
|
||||
var getVisitorDataURL = '@Url.SubRouteUrl("status", "Status.Action", new { action = "GetVisitorData" })';
|
||||
var showWebCPU = @Model.Config.StatusConfig.ShowWebStatus.ToString().ToLower();
|
||||
var showDatabaseCPU = @Model.Config.StatusConfig.ShowDatabaseStatus.ToString().ToLower();
|
||||
var showNetworkUsage = @Model.Config.StatusConfig.ShowNetworkStatus.ToString().ToLower();
|
||||
var showVisitorStats = @Model.Config.PiwikConfig.Enabled.ToString().ToLower();
|
||||
var totalMemory = @Model.Config.StatusConfig.TotalMemory;
|
||||
var tickInterval = totalMemory / 5;
|
||||
var getUsageURL = '@Url.SubRouteUrl("status", "Status.Action", new { action = "GetUsage" })';
|
||||
</script>
|
||||
|
||||
<div class="container">
|
||||
@ -18,7 +22,7 @@
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-sm-10 col-sm-offset-1">
|
||||
<h2 class="text-center"><b>Server Status</b></h2>
|
||||
<h2 class="text-center"><b>Realtime Usage</b></h2>
|
||||
<hr>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
@ -37,6 +41,47 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-10 col-sm-offset-1">
|
||||
<br />
|
||||
<h2 class="text-center"><b>Statistics</b></h2>
|
||||
<hr>
|
||||
@if (Model.Config.PiwikConfig.Enabled)
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<div id="visitor-chart"></div>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
}
|
||||
<div class="row">
|
||||
<div class="col-sm-3 text-center">
|
||||
<h3>Uploads</h3>
|
||||
<p>Total Count: @Model.UploadCount</p>
|
||||
<p>Total Size: @StringHelper.GetBytesReadable(Model.UploadSize)</p>
|
||||
</div>
|
||||
<div class="col-sm-3 text-center">
|
||||
<h3>Pastes</h3>
|
||||
<p>Total Count: @Model.PasteCount</p>
|
||||
</div>
|
||||
<div class="col-sm-3 text-center">
|
||||
<h3>Shortened Urls</h3>
|
||||
<p>Total Count: @Model.ShortenedUrlCount</p>
|
||||
</div>
|
||||
<div class="col-sm-3 text-center">
|
||||
<h3>Vaults</h3>
|
||||
<p>Total Count: @Model.ShortenedUrlCount</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-12 text-center">
|
||||
<h3>Users</h3>
|
||||
<p>Number of Users: @Model.UserCount</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -9,19 +9,7 @@ using Teknik.ViewModels;
|
||||
namespace Teknik.Areas.Transparency.ViewModels
|
||||
{
|
||||
public class TransparencyViewModel : ViewModelBase
|
||||
{
|
||||
public int UploadCount { get; set; }
|
||||
|
||||
public long UploadSize { get; set; }
|
||||
|
||||
public int PasteCount { get; set; }
|
||||
|
||||
public int UserCount { get; set; }
|
||||
|
||||
public int ShortenedUrlCount { get; set; }
|
||||
|
||||
public int VaultCount { get; set; }
|
||||
|
||||
{
|
||||
public string Canary { get; set; }
|
||||
|
||||
public Dictionary<string, double> TotalBills { get; set; }
|
||||
|
@ -18,51 +18,11 @@
|
||||
<h2 class="text-center"><b>Behind the Scenes</b></h2>
|
||||
<hr>
|
||||
<p>
|
||||
Here you can view all of Teknik's financial information, takedown requests and the actions we took, as well as some general statistics for the site's services.
|
||||
Here you can view all of Teknik's financial information, takedown requests and the actions we took.
|
||||
</p>
|
||||
<p>
|
||||
If you would like to request additional information about Teknik, please feel free to contact us through our <a href="@Url.SubRouteUrl("contact", "Contact.Index")" target="_blank">Contact Form</a> or by emailing us at <a href="mailto:@Model.Config.SupportEmail">@Model.Config.SupportEmail</a>.
|
||||
</p>
|
||||
<p>
|
||||
Want to make a donation? Visit our <a href="@Url.SubRouteUrl("about", "About.Index")" target="_blank">About Page</a> and choose a donation method at the bottom.
|
||||
</p>
|
||||
<br />
|
||||
<h2 class="text-center"><b>Statistics</b></h2>
|
||||
<hr>
|
||||
@if (Model.Config.PiwikConfig.Enabled)
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<div id="visitor-chart"></div>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
}
|
||||
<div class="row">
|
||||
<div class="col-sm-3 text-center">
|
||||
<h3>Uploads</h3>
|
||||
<p>Total Count: @Model.UploadCount</p>
|
||||
<p>Total Size: @StringHelper.GetBytesReadable(Model.UploadSize)</p>
|
||||
</div>
|
||||
<div class="col-sm-3 text-center">
|
||||
<h3>Pastes</h3>
|
||||
<p>Total Count: @Model.PasteCount</p>
|
||||
</div>
|
||||
<div class="col-sm-3 text-center">
|
||||
<h3>Shortened Urls</h3>
|
||||
<p>Total Count: @Model.ShortenedUrlCount</p>
|
||||
</div>
|
||||
<div class="col-sm-3 text-center">
|
||||
<h3>Vaults</h3>
|
||||
<p>Total Count: @Model.ShortenedUrlCount</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-12 text-center">
|
||||
<h3>Users</h3>
|
||||
<p>Number of Users: @Model.UserCount</p>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<h2 class="text-center"><b>Transactions</b></h2>
|
||||
<hr>
|
||||
|
98
Teknik/Hubs/ServerUsageHub.cs
Normal file
98
Teknik/Hubs/ServerUsageHub.cs
Normal file
@ -0,0 +1,98 @@
|
||||
using Microsoft.AspNet.SignalR;
|
||||
using Microsoft.AspNet.SignalR.Hubs;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using Teknik.Configuration;
|
||||
using Teknik.SignalR;
|
||||
|
||||
namespace Teknik.Hubs
|
||||
{
|
||||
[HubName("serverUsage")]
|
||||
public class ServerUsageHub : Hub
|
||||
{
|
||||
private readonly ServerUsageTicker _serverUsageTicker;
|
||||
|
||||
public ServerUsageHub() : this(ServerUsageTicker.Instance) { }
|
||||
|
||||
public ServerUsageHub(ServerUsageTicker serverUsageTicker)
|
||||
{
|
||||
_serverUsageTicker = serverUsageTicker;
|
||||
}
|
||||
|
||||
public class ServerUsage
|
||||
{
|
||||
[JsonProperty("cpu")]
|
||||
public CPUUsage CPU { get; set; }
|
||||
[JsonProperty("memory")]
|
||||
public MemoryUsage Memory { get; set; }
|
||||
[JsonProperty("network")]
|
||||
public NetworkUsage Network { get; set; }
|
||||
|
||||
public ServerUsage()
|
||||
{
|
||||
CPU = new CPUUsage();
|
||||
Memory = new MemoryUsage();
|
||||
Network = new NetworkUsage();
|
||||
}
|
||||
}
|
||||
|
||||
public class CPUUsage
|
||||
{
|
||||
[JsonProperty("total")]
|
||||
public float Total { get; set; }
|
||||
[JsonProperty("website")]
|
||||
public float Website { get; set; }
|
||||
[JsonProperty("database")]
|
||||
public float Database { get; set; }
|
||||
|
||||
public CPUUsage()
|
||||
{
|
||||
Total = 0;
|
||||
Website = 0;
|
||||
Database = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public class MemoryUsage
|
||||
{
|
||||
[JsonProperty("total")]
|
||||
public float Total { get; set; }
|
||||
[JsonProperty("available")]
|
||||
public float Available { get; set; }
|
||||
[JsonProperty("used")]
|
||||
public float Used { get; set; }
|
||||
[JsonProperty("websiteUsed")]
|
||||
public float WebsiteUsed { get; set; }
|
||||
[JsonProperty("databaseUsed")]
|
||||
public float DatabaseUsed { get; set; }
|
||||
|
||||
public MemoryUsage()
|
||||
{
|
||||
Total = 0;
|
||||
Available = 0;
|
||||
Used = 0;
|
||||
WebsiteUsed = 0;
|
||||
DatabaseUsed = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public class NetworkUsage
|
||||
{
|
||||
[JsonProperty("sent")]
|
||||
public float Sent { get; set; }
|
||||
[JsonProperty("received")]
|
||||
public float Received { get; set; }
|
||||
|
||||
public NetworkUsage()
|
||||
{
|
||||
Sent = 0;
|
||||
Received = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
24
Teknik/Models/DataPoint.cs
Normal file
24
Teknik/Models/DataPoint.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
|
||||
namespace Teknik.Models
|
||||
{
|
||||
public class DataPoint
|
||||
{
|
||||
public long X { get; set; }
|
||||
|
||||
public long Y { get; set; }
|
||||
|
||||
public DataPoint() : this(0, 0)
|
||||
{
|
||||
}
|
||||
|
||||
public DataPoint(long x, long y)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
2955
Teknik/Scripts/jquery.signalR-2.2.1.js
Normal file
2955
Teknik/Scripts/jquery.signalR-2.2.1.js
Normal file
File diff suppressed because it is too large
Load Diff
9
Teknik/Scripts/jquery.signalR-2.2.1.min.js
vendored
Normal file
9
Teknik/Scripts/jquery.signalR-2.2.1.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
179
Teknik/SignalR/ServerUsageTicker.cs
Normal file
179
Teknik/SignalR/ServerUsageTicker.cs
Normal file
@ -0,0 +1,179 @@
|
||||
using Microsoft.AspNet.SignalR;
|
||||
using Microsoft.AspNet.SignalR.Hubs;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Timers;
|
||||
using System.Web;
|
||||
using Teknik.Configuration;
|
||||
using Teknik.Hubs;
|
||||
using static Teknik.Hubs.ServerUsageHub;
|
||||
|
||||
namespace Teknik.SignalR
|
||||
{
|
||||
public class ServerUsageTicker
|
||||
{
|
||||
// Singleton instance
|
||||
private readonly static Lazy<ServerUsageTicker> _instance = new Lazy<ServerUsageTicker>(() => new ServerUsageTicker(GlobalHost.ConnectionManager.GetHubContext<ServerUsageHub>().Clients));
|
||||
|
||||
private readonly ServerUsage _serverUsage = new ServerUsage();
|
||||
|
||||
private readonly object _updateServerUsageLock = new object();
|
||||
|
||||
private readonly double _updateInterval = 100;
|
||||
|
||||
private readonly System.Timers.Timer _timer;
|
||||
private volatile bool _updatingServerUpdates = false;
|
||||
|
||||
public ServerUsageTicker(IHubConnectionContext<dynamic> clients)
|
||||
{
|
||||
Clients = clients;
|
||||
|
||||
_timer = new System.Timers.Timer(_updateInterval);
|
||||
_timer.Elapsed += UpdateServerUsage;
|
||||
_timer.AutoReset = false;
|
||||
_timer.Enabled = true;
|
||||
}
|
||||
|
||||
public static ServerUsageTicker Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
return _instance.Value;
|
||||
}
|
||||
}
|
||||
|
||||
private IHubConnectionContext<dynamic> Clients
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
private void UpdateServerUsage(object source, ElapsedEventArgs e)
|
||||
{
|
||||
lock (_updateServerUsageLock)
|
||||
{
|
||||
if (!_updatingServerUpdates)
|
||||
{
|
||||
_updatingServerUpdates = true;
|
||||
|
||||
// Update Server Usage
|
||||
if (TryUpdateServerUsage())
|
||||
{
|
||||
BroadcastServerUsage(_serverUsage);
|
||||
}
|
||||
|
||||
_updatingServerUpdates = false;
|
||||
|
||||
// Restart the timer
|
||||
_timer.Enabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void BroadcastServerUsage(ServerUsage serverUsage)
|
||||
{
|
||||
Clients.All.updateServerUsage(serverUsage);
|
||||
}
|
||||
|
||||
private bool TryUpdateServerUsage()
|
||||
{
|
||||
try
|
||||
{
|
||||
Config config = Config.Load();
|
||||
|
||||
// CPU
|
||||
PerformanceCounter totalCPU = new PerformanceCounter();
|
||||
PerformanceCounter webCPU = new PerformanceCounter();
|
||||
PerformanceCounter dbCPU = new PerformanceCounter();
|
||||
// Memory
|
||||
PerformanceCounter totalAvailMem = new PerformanceCounter();
|
||||
PerformanceCounter webMem = new PerformanceCounter();
|
||||
PerformanceCounter dbMem = new PerformanceCounter();
|
||||
// Network
|
||||
PerformanceCounter sentPerf = new PerformanceCounter();
|
||||
PerformanceCounter receivedPerf = new PerformanceCounter();
|
||||
|
||||
string processName = Process.GetCurrentProcess().ProcessName;
|
||||
|
||||
// CPU
|
||||
totalCPU = new PerformanceCounter("Processor", "% Processor Time", "_Total", true);
|
||||
webCPU = new PerformanceCounter("Process", "% Processor Time", processName, true);
|
||||
if (config.StatusConfig.ShowDatabaseStatus)
|
||||
{
|
||||
dbCPU = new PerformanceCounter("Process", "% Processor Time", config.StatusConfig.DatabaseProcessName, true);
|
||||
}
|
||||
// Memory
|
||||
totalAvailMem = new PerformanceCounter("Memory", "Available Bytes", true);
|
||||
webMem = new PerformanceCounter("Process", "Private Bytes", processName, true);
|
||||
if (config.StatusConfig.ShowDatabaseStatus)
|
||||
{
|
||||
dbMem = new PerformanceCounter("Process", "Private Bytes", config.StatusConfig.DatabaseProcessName, true);
|
||||
}
|
||||
// Network
|
||||
if (config.StatusConfig.ShowNetworkStatus)
|
||||
{
|
||||
sentPerf = new PerformanceCounter("Network Interface", "Bytes Sent/sec", config.StatusConfig.NetworkInterface, true);
|
||||
receivedPerf = new PerformanceCounter("Network Interface", "Bytes Received/sec", config.StatusConfig.NetworkInterface, true);
|
||||
}
|
||||
|
||||
// CPU Sample
|
||||
totalCPU.NextValue();
|
||||
if (config.StatusConfig.ShowWebStatus)
|
||||
{
|
||||
webCPU.NextValue();
|
||||
}
|
||||
if (config.StatusConfig.ShowDatabaseStatus)
|
||||
{
|
||||
dbCPU.NextValue();
|
||||
}
|
||||
|
||||
// Network Sample
|
||||
sentPerf.NextValue();
|
||||
receivedPerf.NextValue();
|
||||
|
||||
// Wait the sample time
|
||||
Thread.Sleep(1000);
|
||||
|
||||
// CPU Values
|
||||
_serverUsage.CPU.Total = totalCPU.NextValue();
|
||||
if (config.StatusConfig.ShowWebStatus)
|
||||
{
|
||||
_serverUsage.CPU.Website = webCPU.NextValue();
|
||||
}
|
||||
if (config.StatusConfig.ShowDatabaseStatus)
|
||||
{
|
||||
_serverUsage.CPU.Database = dbCPU.NextValue();
|
||||
}
|
||||
|
||||
// Memory Values
|
||||
_serverUsage.Memory.Total = config.StatusConfig.TotalMemory;
|
||||
_serverUsage.Memory.Available = totalAvailMem.NextValue();
|
||||
_serverUsage.Memory.Used = _serverUsage.Memory.Total - _serverUsage.Memory.Available;
|
||||
if (config.StatusConfig.ShowWebStatus)
|
||||
{
|
||||
_serverUsage.Memory.WebsiteUsed = webMem.NextValue();
|
||||
}
|
||||
if (config.StatusConfig.ShowDatabaseStatus)
|
||||
{
|
||||
_serverUsage.Memory.DatabaseUsed = dbMem.NextValue();
|
||||
}
|
||||
|
||||
// Network Values
|
||||
if (config.StatusConfig.ShowNetworkStatus)
|
||||
{
|
||||
_serverUsage.Network.Sent = sentPerf.NextValue();
|
||||
_serverUsage.Network.Received = receivedPerf.NextValue();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Logger.WriteEntry(ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
18
Teknik/Startup.cs
Normal file
18
Teknik/Startup.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Owin;
|
||||
using Owin;
|
||||
|
||||
[assembly: OwinStartup(typeof(Teknik.Startup))]
|
||||
|
||||
namespace Teknik
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
public void Configuration(IAppBuilder app)
|
||||
{
|
||||
// For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=316888
|
||||
app.MapSignalR();
|
||||
}
|
||||
}
|
||||
}
|
@ -73,11 +73,31 @@
|
||||
<HintPath>..\packages\Microsoft.AspNet.Identity.EntityFramework.2.2.1\lib\net45\Microsoft.AspNet.Identity.EntityFramework.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.AspNet.SignalR.Core, Version=2.2.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.AspNet.SignalR.Core.2.2.1\lib\net45\Microsoft.AspNet.SignalR.Core.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.AspNet.SignalR.SystemWeb, Version=2.2.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.AspNet.SignalR.SystemWeb.2.2.1\lib\net45\Microsoft.AspNet.SignalR.SystemWeb.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Azure.KeyVault.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Azure.KeyVault.Core.2.0.4\lib\net45\Microsoft.Azure.KeyVault.Core.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="Microsoft.Owin, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Owin.2.1.0\lib\net45\Microsoft.Owin.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Owin.Host.SystemWeb, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Owin.Host.SystemWeb.2.1.0\lib\net45\Microsoft.Owin.Host.SystemWeb.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Owin.Security, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Owin.Security.2.1.0\lib\net45\Microsoft.Owin.Security.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualBasic" />
|
||||
<Reference Include="MySql.Data, Version=6.9.9.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\MySql.Data.6.9.9\lib\net45\MySql.Data.dll</HintPath>
|
||||
@ -91,6 +111,10 @@
|
||||
<HintPath>..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Piwik.Tracker, Version=2.16.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Piwik.Tracker.2.16.0.0\lib\net40\Piwik.Tracker.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
@ -253,6 +277,8 @@
|
||||
<Compile Include="Areas\Vault\ViewModels\VaultItemViewModel.cs" />
|
||||
<Compile Include="Attributes\TeknikAuthorizeAttribute.cs" />
|
||||
<Compile Include="Filters\CORSActionFilter.cs" />
|
||||
<Compile Include="Hubs\ServerUsageHub.cs" />
|
||||
<Compile Include="Models\DataPoint.cs" />
|
||||
<Compile Include="Models\TransferTypes.cs" />
|
||||
<Compile Include="Areas\User\Models\UploadSettings.cs" />
|
||||
<Compile Include="Areas\User\Models\UserSettings.cs" />
|
||||
@ -319,6 +345,8 @@
|
||||
<Compile Include="Areas\User\ViewModels\LoginViewModel.cs" />
|
||||
<Compile Include="Areas\User\ViewModels\RegisterViewModel.cs" />
|
||||
<Compile Include="Modules\PerformanceMonitorModule.cs" />
|
||||
<Compile Include="SignalR\ServerUsageTicker.cs" />
|
||||
<Compile Include="Startup.cs" />
|
||||
<Compile Include="ViewModels\ViewModelBase.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="App_Start\SubdomainRoute.cs" />
|
||||
@ -619,6 +647,8 @@
|
||||
<Content Include="Scripts\jquery.blockUI.js" />
|
||||
<Content Include="Scripts\jquery.fileupload.js" />
|
||||
<Content Include="Scripts\jquery.iframe-transport.js" />
|
||||
<Content Include="Scripts\jquery.signalR-2.2.1.js" />
|
||||
<Content Include="Scripts\jquery.signalR-2.2.1.min.js" />
|
||||
<Content Include="Scripts\jquery.tocify.min.js" />
|
||||
<None Include="Scripts\jquery.validate-vsdoc.js" />
|
||||
<Content Include="Scripts\jquery.validate.js" />
|
||||
|
@ -18,15 +18,23 @@
|
||||
<package id="Microsoft.AspNet.Identity.EntityFramework" version="2.2.1" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.AspNet.Mvc" version="5.2.3" targetFramework="net46" userInstalled="true" />
|
||||
<package id="Microsoft.AspNet.Razor" version="3.2.3" targetFramework="net46" userInstalled="true" />
|
||||
<package id="Microsoft.AspNet.SignalR" version="2.2.1" targetFramework="net462" />
|
||||
<package id="Microsoft.AspNet.SignalR.Core" version="2.2.1" targetFramework="net462" />
|
||||
<package id="Microsoft.AspNet.SignalR.JS" version="2.2.1" targetFramework="net462" />
|
||||
<package id="Microsoft.AspNet.SignalR.SystemWeb" version="2.2.1" targetFramework="net462" />
|
||||
<package id="Microsoft.AspNet.Web.Optimization" version="1.1.3" targetFramework="net46" userInstalled="true" />
|
||||
<package id="Microsoft.AspNet.WebPages" version="3.2.3" targetFramework="net46" userInstalled="true" />
|
||||
<package id="Microsoft.Azure.KeyVault.Core" version="2.0.4" targetFramework="net462" />
|
||||
<package id="Microsoft.jQuery.Unobtrusive.Validation" version="3.2.3" targetFramework="net46" userInstalled="true" />
|
||||
<package id="Microsoft.Owin" version="2.1.0" targetFramework="net462" />
|
||||
<package id="Microsoft.Owin.Host.SystemWeb" version="2.1.0" targetFramework="net462" />
|
||||
<package id="Microsoft.Owin.Security" version="2.1.0" targetFramework="net462" />
|
||||
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net46" userInstalled="true" />
|
||||
<package id="Modernizr" version="2.8.3" targetFramework="net452" userInstalled="true" />
|
||||
<package id="MySql.Data" version="6.9.9" targetFramework="net452" />
|
||||
<package id="nClam" version="2.0.6.0" targetFramework="net462" />
|
||||
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Owin" version="1.0" targetFramework="net462" />
|
||||
<package id="Piwik.Tracker" version="2.16.0.0" targetFramework="net452" />
|
||||
<package id="QRCoder" version="1.2.3" targetFramework="net462" />
|
||||
<package id="Respond" version="1.4.2" targetFramework="net452" userInstalled="true" />
|
||||
|
Loading…
Reference in New Issue
Block a user