增加功能:增加在线用户统计功能

This commit is contained in:
Argo-Windows 2019-02-28 16:44:50 +08:00
parent 5ea8022d3c
commit a4520041c9
7 changed files with 232 additions and 0 deletions

View File

@ -0,0 +1,23 @@
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
namespace Bootstrap.Admin.Controllers.Api
{
/// <summary>
///
/// </summary>
[Route("api/[controller]")]
[ApiController]
public class OnlineUsersController : ControllerBase
{
/// <summary>
///
/// </summary>
/// <returns></returns>
[HttpPost()]
public IEnumerable<OnlineUser> Post([FromServices]IOnlineUsers onlineUSers)
{
return onlineUSers.OnlineUsers;
}
}
}

View File

@ -0,0 +1,32 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
namespace Bootstrap.Admin
{
/// <summary>
///
/// </summary>
internal class DefaultOnlineUsers : IOnlineUsers
{
private ConcurrentDictionary<string, OnlineUser> _onlineUsers = new ConcurrentDictionary<string, OnlineUser>();
/// <summary>
///
/// </summary>
/// <returns></returns>
public IEnumerable<OnlineUser> OnlineUsers
{
get { return _onlineUsers.Values; }
}
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <param name="addValueFactory"></param>
/// <param name="updateValueFactory"></param>
/// <returns></returns>
public OnlineUser AddOrUpdate(string key, Func<string, OnlineUser> addValueFactory, Func<string, OnlineUser, OnlineUser> updateValueFactory) => _onlineUsers.AddOrUpdate(key, addValueFactory, updateValueFactory);
}
}

View File

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
namespace Bootstrap.Admin
{
/// <summary>
///
/// </summary>
public interface IOnlineUsers
{
/// <summary>
///
/// </summary>
IEnumerable<OnlineUser> OnlineUsers { get; }
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <param name="addValueFactory"></param>
/// <param name="updateValueFactory"></param>
/// <returns></returns>
OnlineUser AddOrUpdate(string key, Func<string, OnlineUser> addValueFactory, Func<string, OnlineUser, OnlineUser> updateValueFactory);
}
}

View File

@ -0,0 +1,80 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
namespace Bootstrap.Admin
{
/// <summary>
///
/// </summary>
public class OnlineUser
{
private ConcurrentQueue<KeyValuePair<DateTime, string>> _requestUrls;
/// <summary>
///
/// </summary>
/// <param name="ip"></param>
/// <param name="userName"></param>
/// <param name="method"></param>
public OnlineUser(string ip, string userName, string method)
{
Ip = ip;
UserName = userName;
Method = method;
FirstAccessTime = DateTime.Now;
LastAccessTime = DateTime.Now;
_requestUrls = new ConcurrentQueue<KeyValuePair<DateTime, string>>();
}
/// <summary>
///
/// </summary>
public string UserName { get; }
/// <summary>
///
/// </summary>
public DateTime FirstAccessTime { get; }
/// <summary>
///
/// </summary>
public DateTime LastAccessTime { get; set; }
/// <summary>
///
/// </summary>
public string Method { get; set; }
/// <summary>
///
/// </summary>
public string Ip { get; set; }
/// <summary>
///
/// </summary>
public IEnumerable<KeyValuePair<DateTime, string>> RequestUrls
{
get
{
return _requestUrls.ToArray();
}
}
/// <summary>
///
/// </summary>
/// <param name="url"></param>
public void AddRequestUrl(string url)
{
_requestUrls.Enqueue(new KeyValuePair<DateTime, string>(DateTime.Now, url));
if (_requestUrls.Count > 10)
{
_requestUrls.TryDequeue(out _);
}
}
}
}

View File

@ -0,0 +1,48 @@
using Bootstrap.Admin;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Linq;
using System.Threading.Tasks;
namespace Microsoft.AspNetCore.Builder
{
/// <summary>
///
/// </summary>
public static class OnlineUsersMiddlewareExtensions
{
/// <summary>
///
/// </summary>
/// <param name="builder"></param>
/// <returns></returns>
public static IApplicationBuilder UseOnlineUsers(this IApplicationBuilder builder) => builder.UseWhen(context => context.Filter(), app => app.Use(async (context, next) =>
{
await Task.Run(() =>
{
var onlineUsers = context.RequestServices.GetService<IOnlineUsers>();
var clientIp = context.Connection.RemoteIpAddress.ToString();
onlineUsers.AddOrUpdate(clientIp, key =>
{
var ou = new OnlineUser(key, context.User.Identity.Name, context.Request.Method);
ou.AddRequestUrl(context.Request.Path);
return ou;
}, (key, v) =>
{
v.LastAccessTime = DateTime.Now;
v.Method = context.Request.Method;
v.AddRequestUrl(context.Request.Path);
return v;
});
});
await next();
}));
private static bool Filter(this HttpContext context)
{
var url = context.Request.Path;
return !new string[] { "/api", "/NotiHub", "/swagger" }.Any(r => url.StartsWithSegments(r, StringComparison.OrdinalIgnoreCase));
}
}
}

View File

@ -0,0 +1,22 @@
using Bootstrap.Admin;
using Microsoft.Extensions.DependencyInjection.Extensions;
namespace Microsoft.Extensions.DependencyInjection
{
/// <summary>
///
/// </summary>
public static class OnlineUsersServicesCollectionExtensions
{
/// <summary>
///
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
public static IServiceCollection AddOnlineUsers(this IServiceCollection services)
{
services.TryAddSingleton<IOnlineUsers, DefaultOnlineUsers>();
return services;
}
}
}

View File

@ -60,6 +60,7 @@ namespace Bootstrap.Admin
services.AddConfigurationManager(Configuration);
services.AddCacheManager(Configuration);
services.AddDbAdapter();
services.AddOnlineUsers();
var dataProtectionBuilder = services.AddDataProtection(op => op.ApplicationDiscriminator = Configuration["ApplicationDiscriminator"])
.SetApplicationName(Configuration["ApplicationName"])
.PersistKeysToFileSystem(new DirectoryInfo(Configuration["KeyPath"]));
@ -125,6 +126,7 @@ namespace Bootstrap.Admin
app.UseStaticFiles();
app.UseAuthentication();
app.UseBootstrapAdminAuthorization(RoleHelper.RetrieveRolesByUserName, RoleHelper.RetrieveRolesByUrl, AppHelper.RetrievesByUserName);
app.UseOnlineUsers();
app.UseCacheManagerCorsHandler();
app.UseSignalR(routes => { routes.MapHub<SignalRHub>("/NotiHub"); });
app.UseMvc(routes =>