ASP.NET Core provides us a rich Logging APIs which have a set of logger providers including: ConsoleLoggerPtoviderAzureAppServicesDiagnosticsLoggerProviderEventLogLoggerProvider and much more.

This let C# developers happy than before, because you need to implement them loggers yourself in the past, however a lot of us writing JavaScript code in almost web applications which is little hard, but find the client-side exceptions & errors are even harder.

There are many client-side loggers that you can name it, which are fit our needs, but today I wanna talk about the client-side logging from different angle. Me and you as developers suffer a lot from unexpected javascript error that happen occasionally, sometimes the reason is silly such missing a curly braces or broke a link .. etc.

With that I was thinking last few days that it would be nice to integrate the client-side & server-side logs, so all the logs will be logged from the ASP.NET Core logger providers that we like and love instead of managing two different logger providers for both client-side & server-side.

Logging JavaScript Events

Basically the idea is very simple, I need to inject the client-side logging APIs script into our view, after that I need the JavaScriptLoggingMiddleware to listening to the upcoming script logs and forward them to ASP.NET Core logger providers.

With that we're ready to show some code, but before that I need to mention that I didn't introduce a new logging APIs, but I could, so the javascript console object is enough for logging. In both cases we need to intercept the console logs as the following:

(function () {
var trace = console.trace;
var debug = console.debug;
var info = console.info;
var warn = console.warn;
var error = console.error; console.trace = function (message) {
log(logLevel.Trace, message);
trace.call(this, arguments);
}; console.debug = function (message) {
log(logLevel.Debug, message);
debug.call(this, arguments);
}; console.info = function (message) {
log(logLevel.Information, message);
info.call(this, arguments);
}; console.warn = function (message) {
log(logLevel.Warning, message);
warn.call(this, arguments);
}; console.error = function (message) {
log(logLevel.Error, message);
error.call(this, arguments);
};
})();

The log is a method that I created to post the actual logs to the server, which will handled by the JavaScriptLoggingMiddleware that shown below.

At this point I was wondering whether to store jsLogger script into the disk and render it using a tag helper or not!! after awhile I inspired by Application Insights and decided to store it into a resx file and retrieve them later using JavaScriptLoggingSnippet.

public class JavaScriptLoggingMiddleware
{
private readonly ILogger _logger;
private readonly RequestDelegate _next; public JavaScriptLoggingMiddleware(ILoggerFactory loggerFactory, RequestDelegate next)
{
_logger = loggerFactory.CreateLogger<JavaScriptLoggingMiddleware>();
_next = next;
} public async Task Invoke(HttpContext context)
{
if (context.Request.Path == "/log" && context.Request.Method == "POST" && context.Request.HasFormContentType)
{
var form = await context.Request.ReadFormAsync();
var level = Convert.ToInt32(form["level"].First());
var message = form["message"].First(); switch ((LogLevel)level)
{
case LogLevel.Trace:
_logger.LogTrace(message);
break;
case LogLevel.Debug:
_logger.LogDebug(message);
break;
case LogLevel.Information:
_logger.LogInformation(message);
break;
case LogLevel.Warning:
_logger.LogWarning(message);
break;
case LogLevel.Error:
_logger.LogError(message);
break;
default:
return;
}
}
else
{
await _next(context);
}
}
}

If you look closely to the code above, you will notice that the middleware listening for specific url, when it hit I need to map the client-side log levels with the server-side once, after that I log them normally.

I can finally log JavaScript Exceptions!

Last but not least, sometimes we come up to a situation that we need to catch the global javascript exception that may occur for whatever reason could be. window.onerror is a good place to catch such exception.

I added a JavaScriptLoggingOptions which is shown below to make things configurable in the way that you want.

public class JavaScriptLoggingOptions
{
public bool HandleGlobalExceptions { get; set; }
}

By adding this simple property, the JavaScriptLoggingSnippet is now able to choose the proper script to render in the view.

public class JavaScriptLoggingSnippet
{
private readonly JavaScriptLoggingOptions _loggingOptions; private static readonly HtmlString JavaScriptLoggingScript = new HtmlString(Resources.Script); private static readonly HtmlString JavaScriptLoggingGlobalExceptionHandlingScript = new HtmlString(Resources.GlobalExceptionHandlingScript); public JavaScriptLoggingSnippet(IOptions<JavaScriptLoggingOptions> loggingOptions)
{
_loggingOptions = loggingOptions.Value;
} public HtmlString Script =>
_loggingOptions.HandleGlobalExceptions ? FullScript : JavaScriptLoggingScript; private static HtmlString FullScript => JavaScriptLoggingScript.Concat(HtmlString.NewLine,
JavaScriptLoggingGlobalExceptionHandlingScript);
}

What it takes to make everything happen?

We need few steps to make this happen:

First we need to configure the JavaScriptLogging service in the ConfigureServices method

services.AddJavaScriptLogging(options =>
{
options.HandleGlobalExceptions = true;
});

After that adding the JavaScriptLoggingMiddleware to the Configure method

app.UseJavaScriptLogging();

Finally add the following line into your view or layout page to render the jsLogger script.

@Html.Raw(JavaScriptLoggingSnippet.Script)

You can download the source code for this post from my jsLogger repository on GitHub.

集成Javascript Logging on MVC or Core的更多相关文章

  1. 国产化之路-统信UOS + Nginx + Asp.Net MVC + EF Core 3.1 + 达梦DM8实现简单增删改查操作

    专题目录 国产化之路-统信UOS操作系统安装 国产化之路-国产操作系统安装.net core 3.1 sdk 国产化之路-安装WEB服务器 国产化之路-安装达梦DM8数据库 国产化之路-统信UOS + ...

  2. 【干货理解】理解javascript中实现MVC的原理

    理解javascript中的MVC MVC模式是软件工程中一种软件架构模式,一般把软件模式分为三部分,模型(Model)+视图(View)+控制器(Controller); 模型:模型用于封装与应用程 ...

  3. javascript widget ui mvc

    MVC只是javascript的一个UI模式 JavaScript UI----UI, Template, MVC(View)----Backbone, Angular RequireJS------ ...

  4. 开源题材征集 + MVC&EF Core 完整教程小结

    到目前为止,我们的MVC+EF Core 完整教程的理论部分就全部结束了,共20篇,覆盖了核心的主要知识点. 下一阶段是实战部分,我们将会把这些知识点串联起来,用10篇(天)来完成一个开源项目. 现向 ...

  5. FineUIPro/Mvc/Core/JS v4.2.0 发布了(老牌ASP.NET控件库,WebForms,ASP.NET MVC,Core,JavaScript)!

    还记得 10 年前那个稍微青涩的 ExtAspNet 吗,如今她已脱胎换骨,变成了如下 4 款产品: FineUIPro:基于jQuery的经典款ASP.NET WebForms控件,之前的FineU ...

  6. 30行代码实现Javascript中的MVC

    从09年左右开始,MVC逐渐在前端领域大放异彩,并终于在刚刚过去的2015年随着React Native的推出而迎来大爆发:AngularJS.EmberJS.Backbone.ReactJS.Rio ...

  7. JavaScript富应用MVC MVVM框架

    对框架的挑选 Ember.js.Backbone.js.Knockout.js.Spine.js.Batman.js , Angular.js 1. 轻量级的应用选择哪一个会比较好?2. 那一个比较简 ...

  8. 改造继续之eclipse集成tomcat开发spring mvc项目配置一览

    在上一篇的环境配置中,你还只能基于maven开发一个javase的项目,本篇来看如果开发一个web项目,所以还得配置一下tomcat和spring mvc. 一:Tomcat安装 在.net web开 ...

  9. ASP.NET Core MVC+EF Core从开发到部署

    笔记本电脑装了双系统(Windows 10和Ubuntu16.04)快半年了,平时有时间就喜欢切换到Ubuntu系统下耍耍Linux,熟悉熟悉Linux命令.Shell脚本以及Linux下的各种应用的 ...

随机推荐

  1. layer 查看图片

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  2. [MicroPython]TPYBoard v102炫彩跑马灯WS2812B

    一.实验目的 了解ws2812b的工作原理 学习ws2812b的驱动方法 二.实验器材 TPYBoard v102 1块 ws2812b RGB-Ring-8 1个 micro USB数据线 1条 杜 ...

  3. 一本通 1212:LETTERS

    题目描述 给出一个roe×col的大写字母矩阵,一开始的位置为左上角,你可以向上下左右四个方向移动,并且不能移向曾经经过的字母.问最多可以经过几个字母. 输入 第一行,输入字母矩阵行数R和列数S,1≤ ...

  4. SkylineGlobe TerraExplorer Pro 7.0 Web 控件版 第一行示例代码

    SkylineGlobe TerraExplorer Pro 7.0 是原生的64位应用程序,在Web端用插件方式开发的第一行示例代码如下: 常规代码,需要IE64位: <!DOCTYPE ht ...

  5. Kano模型告诉你“是不是只要企业努力的提高产品或服务质量,顾客满意度就一定会提高吗?”

    在 PO在敏捷需求下要遵守哪6条重要原则?   中讲到探索和交付两大阶段的6个原则 其中在原则[做有价值的需求]中讲了两个方法:BSA分析和产品Backlog 其中BSA分析是我在产品规划阶段常使用的 ...

  6. Hibernate各种基本注解及一对一(多)关系映射采坑笔记

    hibernate提供两种方式配置关系映射,一种XMl配置,一种注解.SpringBoot已经自带了hibernate注解方式,我也是特别喜欢使用注解,特此记下常用的知识点. 1.基本注解 @Tabl ...

  7. Tomcat完美配置多个HOST主机,域名,SSL

    这里是Tomcat9版本,其它版本基本一致! 1.配置多个主机域名 1.打开conf文件夹下的server.xml 复制官方提供的HOST配置,修改为你的域名,appBase路径(相对路径) 2.新建 ...

  8. Java调度池的实现原理

    下图是关于ScheduledFutureTask的继承体系结构图.

  9. Day10 Python基础之特殊函数(八)

    一些特殊函数 1.递归函数(recursion) 递归函数的定义:在函数内部,可以调用其他函数.如果一个函数在内部调用自身本身,这个函数就是递归函数. 递归函数的优点:是定义简单,逻辑清晰.理论上,所 ...

  10. CodeForces Round #550 Div.3

    http://codeforces.com/contest/1144 A. Diverse Strings A string is called diverse if it contains cons ...