使用 JSNLog 在 JavaScript 中插入日志记录器






4.93/5 (9投票s)
展示了如何使用 JSNLog 在 JavaScript 中插入日志记录器。JSNLog 是一个 JavaScript 日志记录库,可以很好地与您的 .Net 站点集成。
展示了如何使用 JSNLog 在 JavaScript 中插入日志记录器。JSNLog 是一个 JavaScript 日志记录库,可以很好地与 .Net 集成。它允许您在 web.config 中配置日志记录器。它还可以让您在不进行任何编码的情况下,从客户端接收日志消息并将其存储在服务器端。
本系列内容
- JavaScript 日志记录的原理和方法
- 在 JavaScript 中插入日志记录器
- 在 web.config 中配置您的日志记录器
本文内容
JL 命名空间
- JL 方法 - 创建日志记录器
- setOptions 方法 - 配置 JSNLog 库
Logger 对象
JL 命名空间
允许您创建日志记录器并配置 JSNLog 库本身。
JL 方法
创建和检索日志记录器
定义
JL(loggerName?: string): Logger
参数
- loggerName
- 日志记录器的名称,或为空表示根日志记录器。
返回值
具有给定名称的日志记录器,或者在未给出名称时为根日志记录器。如果日志记录器不存在,则会创建它。
备注
在您的服务器端日志中,根日志记录器称为 ClientRoot。
示例
这会返回名为“a.b”的日志记录器。
var logger = JL('a.b');
这会返回根日志记录器。
var rootlogger = JL();
setOptions 方法
设置库范围的选项
定义
setOptions(options: any): void
参数
- options
- 一个包含选项的 JSON 对象。请参阅下面的“备注”部分。
返回值
本身。
备注
JSON 对象可以包含以下字段
字段 | 类型 | 默认值 | 描述 |
---|---|---|---|
enabled optional |
bool | true | 如果为 false,则禁用所有日志记录器。 |
maxMessages optional |
number | 无最大值 | 限制发送到服务器的消息总数。请参阅下面的备注。 |
requestId optional |
字符串 | (空) | 与所有日志消息一起发送到服务器,以便更容易识别给定请求的所有日志消息。通过 <jsnlog> 元素 的 serverSideMessageFormat 属性中的 %requestId 占位符报告。 |
maxMessages 和缓冲
您可以使用 maxMessages 来限制发送到服务器的消息数量。当您通过调用 setOptions 设置 maxMessages 时,计数器会设置为 maxMessages。每次将消息发送到服务器时,该计数器都会减去发送的消息数量。当计数器降至零或以下时,将不再发送更多消息。
但是,这会受到 批量和缓冲 的影响。
考虑一个情况,maxMessages 设置为 5,并且已经发送了 2 条消息 - 因此消息计数器现在是 3。如果缓冲区中存储了 8 条消息,并且这些消息现在被发送,那么它们将被全部发送。这意味着服务器将总共收到 2 + 8 = 10 条消息。之后,将不再发送更多消息,因为发送的消息数量(10)超过了 maxMessages(5)。
这意味着 maxMessages 不是发送到服务器的消息数量的精确限制。另一方面,缓冲的消息会一起在一个请求中发送到服务器,从而最大程度地减少带宽。并且缓冲的消息通常有助于解决异常,因此接收它们是有价值的。
示例
这将 requestId 设置为与所有日志消息一起发送到服务器。
JL.setOptions({ "requestId": "35F7416D-86F1-47FA-A9EC-547FFF510086" });
Logger 对象
trace 方法
创建严重级别为 TRACE 的日志项
定义
trace<text>(logObject: any): Logger</text>
参数
- logObject
- 要记录的字符串或对象,或者返回要记录的字符串或对象的函数(详细信息)。
返回值
Logger 本身。
示例
这会创建一个严重级别为 TRACE 的日志消息“log message”。
JL().trace<text>("log message");</text>
debug 方法
创建严重级别为 DEBUG 的日志项
定义
debug<text>(logObject: any): Logger</text>
参数
- logObject
- 要记录的字符串或对象,或者返回要记录的字符串或对象的函数(详细信息)。
返回值
Logger 本身。
示例
这会创建一个严重级别为 DEBUG 的日志消息“log message”。
JL().debug<text>("log message");</text>
info 方法
创建严重级别为 INFO 的日志项
定义
info<text>(logObject: any): Logger</text>
参数
- logObject
- 要记录的字符串或对象,或者返回要记录的字符串或对象的函数(详细信息)。
返回值
Logger 本身。
示例
这会创建一个严重级别为 INFO 的日志消息“log message”。
JL().info<text>("log message");</text>
warn 方法
创建严重级别为 WARN 的日志项
定义
warn<text>(logObject: any): Logger</text>
参数
- logObject
- 要记录的字符串或对象,或者返回要记录的字符串或对象的函数(详细信息)。
返回值
Logger 本身。
示例
这会创建一个严重级别为 WARN 的日志消息“log message”。
JL().warn<text>("log message");</text>
error 方法
创建严重级别为 ERROR 的日志项
定义
error<text>(logObject: any): Logger</text>
参数
- logObject
- 要记录的字符串或对象,或者返回要记录的字符串或对象的函数(详细信息)。
返回值
Logger 本身。
示例
这会创建一个严重级别为 ERROR 的日志消息“log message”。
JL().error<text>("log message");</text>
fatal 方法
创建严重级别为 FATAL 的日志项
定义
fatal<text>(logObject: any): Logger</text>
参数
- logObject
- 要记录的字符串或对象,或者返回要记录的字符串或对象的函数(详细信息)。
返回值
Logger 本身。
示例
这会创建一个严重级别为 FATAL 的日志消息“log message”。
JL().fatal<text>("log message");</text>
fatalException 方法
创建严重级别为 FATAL 的日志项,包含消息和异常
定义
fatalException(logObject: any, e: any): Logger
参数
- logObject
- 要记录的字符串或对象,或者返回要记录的字符串或对象的函数(详细信息)。
- e
- 将与 logObject 一起记录的 Exception。在 Chrome、Firefox 和 IE10 及更高版本中,还会记录堆栈跟踪。但是,请参阅下面的备注。
返回值
Logger 本身。
备注
fatalException 函数会在以下情况下记录异常的堆栈跟踪(显示异常在代码中的发生位置)
- 异常是由浏览器抛出的,例如尝试读取未定义变量时
try { // Browser throws exception i.dont.exist = 666; } catch(e) { // Logs stack trace JL().fatalException("Exception was thrown!", e); }
- 您抛出了 Error 对象 或 Exception 对象
: try { // Throwing Error object throw new Error("Whoops!"); } catch(e) { // Logs stack trace JL().fatalException("Exception was thrown!", e); }
如果您抛出了不是 Error 对象或 Exception 对象的任何内容,fatalException 函数将*不会*记录堆栈跟踪。
try { // Throwing something that is not an Error Object or // Exception Object (in this case a string) throw "Whoops!"; } catch(e) { // Does not log stack trace JL().fatalException("Exception was thrown!", e); }
Exception 对象是 JSNLog 的内置对象。它为更好的异常处理打开了大门。详细信息 在此。
示例
此代码会捕获任何异常并记录它们。
try { ... } catch (e) { JL().fatalException("Exception was thrown!", e); }
此代码会捕获任何异常,并将其与某些变量的值一起记录,以方便调试。
function f1(i, j) { try { ... } catch (e) { JL('f1').fatalException({ "i": i, "j": j}, e); } }
setOptions 方法
为日志记录器设置选项
定义
setOptions(options: any): Logger
参数
- options
- 一个包含选项的 JSON 对象。请参阅下面的“备注”部分。
返回值
Logger 本身。
备注
JSON 对象可以包含以下字段
字段 | 类型 | 默认值 | 描述 |
---|---|---|---|
level optional |
number | (继承自父日志记录器) | 只有严重级别等于或高于此级别的日志消息才能发送到服务器。 |
userAgentRegex optional |
正则表达式 | (继承自父日志记录器) | 如果非空,则仅当此正则表达式与浏览器的 用户代理字符串 匹配时,才会处理日志消息。 |
ipRegex optional |
正则表达式 | (继承自父日志记录器) | 如果非空,则仅当此正则表达式与浏览器的 IP 地址匹配时,才会处理日志消息。如果使用此选项,请务必通过 JL 对象的 setOptions 方法 设置 IP 地址。 |
disallow optional |
正则表达式 | (继承自父日志记录器) | 如果非空,则在日志消息匹配此正则表达式时将其抑制。如果要记录的对象,它会被转换为 JSON 字符串,然后进行匹配。 |
appenders optional |
Appender 数组 | (继承自父日志记录器) | 一个或多个 Appender,供日志记录器发送其日志消息。请参阅示例。 |
onceOnly optional |
字符串数组 | (继承自父日志记录器) | 一个或多个正则表达式。当消息匹配正则表达式时,任何后续匹配同一正则表达式的消息都将被抑制。请参阅备注和示例。 |
Logger 名称和选项继承
日志记录器不仅通过 setOptions 方法获取其选项,还通过继承获取。这基于每个日志记录器的名称。
假设您在“namespace1”命名空间中有一个名为“method1”的方法。那么使用此类命名方案来命名您的日志记录器是有意义的:“namespace1.method1.logger1”、“namespace1.method1.logger2”等。这样,就不会有名称冲突,并且可以轻松跟踪您的日志记录器。
就像命名空间可以包含方法,方法可以包含日志记录器一样,您可以将这些日志记录器名称视为构成一个层次结构。
- “namespace1.method1.logger1”的父级是“namespace1.method1”;
- “namespace1.method1”的父级是“namespace1”;
- “namespace1”的父级是根日志记录器(没有名称的日志记录器)。
您不限于只有 3 个级别,您可以拥有任意多个。
如果您不使用 setOptions 方法设置选项
根日志记录器和默认 Appender
当库加载时,它会创建根日志记录器。它还为根日志记录器创建一个默认的 Appender。
由于每个日志记录器都继承自根日志记录器(除非您使用 setOptions 方法覆盖此设置),因此您可以立即开始日志记录,而无需创建 Appender。
根日志记录器使用以下选项创建
选项 | 默认值 |
---|---|
level | DEBUG |
userAgentRegex | (空) |
ipRegex | (空) |
disallow | (空) |
appenders | (默认 Appender) |
请注意,由于根日志记录器的默认 level 是 DEBUG,因此默认情况下,只有严重级别为 DEBUG 或更高的日志消息才会得到处理。
您可以使用 setOptions 方法以与任何其他日志记录器相同的方式更改根日志记录器的选项。请参阅下面的示例。
选项 | 默认值 |
---|---|
level | TRACE |
userAgentRegex | (空) |
ipRegex | (空) |
disallow | (空) |
storeInBufferLevel | ALL |
sendWithBufferLevel | 关 |
bufferSize | 0 |
batchSize | 1 |
url | jsnlog.logger |
使用 onceOnly 抑制重复消息
您可能在会被多次调用的代码中拥有日志记录器。因此,您可能会收到一系列本质上相同的消息。使用 onceOnly,您可以抑制重复的消息,因此只有第一条消息会发送到服务器。
这通过设置一个或多个正则表达式来实现。当一条日志消息匹配其中一个正则表达式时,日志记录器会记住有一条消息匹配该正则表达式。然后,当另一条消息到达并匹配同一正则表达式时,它将被抑制。
例如,如果您收到以下消息
Parameter x too high - x = 5 Parameter x too high - x = 6 Parameter x too high - x = 7 ... Parameter x too high - x = 49 Parameter x too high - x = 50
那么您可以使用正则表达式
Parameter x too high - x =
以只接收第一条消息
Parameter x too high - x = 5
有关如何设置正则表达式的示例,请参阅示例。
您可以设置多个正则表达式。它们独立工作。因此,如果一条消息匹配第一个正则表达式,然后第二条消息匹配第二个正则表达式但不匹配第一个,那么第二条消息就会通过,因为它不是第一条消息的重复。
正如 此处 所示,您不仅可以记录字符串,还可以记录对象。如果您记录一个对象,该对象会被转换为 JSON 字符串。然后将该字符串与正则表达式进行匹配。
与其他属性类似,日志记录器会从其父级继承 onceOnly。但是,这是全有或全无的。如果您为日志记录器设置了 onceOnly 正则表达式,那么其父级可能拥有的任何 onceOnly 正则表达式都将被忽略。
示例
这会将日志记录器“a.b”的级别设置为 3000。
var logger = JL("a.b"); logger.setOptions({ "level": 3000 });
这会设置根日志记录器的级别。
var rootlogger = JL(); rootlogger.setOptions({ "level": 3000 });
这会将日志记录器“a.b”的级别设置为 INFO(与设置为 3000 相同)。此代码表明您无需使用 logger 变量。
JL("a.b").setOptions({ "level": JL.getInfoLevel() });
这会将级别设置为 OFF,从而完全关闭该日志记录器。
JL("a.b").setOptions({ "level": JL.getOffLevel() });
这会将级别设置为 4000。它还禁用所有浏览器中的日志记录器,但那些用户代理字符串包含 MSIE 7|MSIE 8(即 Internet Explorer 的 7 或 8 版本)的浏览器。
var logger = JL("a.b"); logger.setOptions({ "level": 4000, "userAgentRegex": "MSIE 7|MSIE 8" });
这会创建一个名为“appender”的 Appender,然后告诉日志记录器“a.b”将所有日志消息发送给它。
var appender=JL.createAjaxAppender('appender'); var logger = JL("a.b"); logger.setOptions({ "appenders": [appender] });
这会创建 AjaxAppender 和 ConsoleAppender,然后告诉日志记录器“mylogger”将所有日志消息同时发送给它们。
var ajaxAppender=JL.createAjaxAppender('ajaxAppender'); var consoleAppender=JL.createConsoleAppender('consoleAppender'); JL("mylogger").setOptions({"appenders": [ajaxAppender,consoleAppender]});
抑制与正则表达式“Parameter x too high - x =”匹配的重复消息。
JL("a").setOptions({ "onceOnly": [ "Parameter x too high - x =" ] });
抑制与正则表达式“Parameter x too high - x =”匹配的重复消息。还抑制与“x = \d+ and y = \d+”匹配的重复消息。
JL("a").setOptions({ "onceOnly": [ "Parameter x too high - x =", "x = \\d+ and y = \\d+" ] });
日志记录器从其父级继承 onceOnly。假设您有一个日志记录器“a.b”,其父级“a”会抑制重复项,但您希望日志记录器“a.b”不抑制重复项。要实现这一点,请为其提供一个*不*包含任何正则表达式的 onceOnly 集合。
JL("a.b").setOptions({ "onceOnly": [ ] });
log 方法
创建日志项
定义
log(level: number, logObject: any): Logger
参数
- level
- 要记录的消息的严重级别。
- logObject
- 要记录的字符串或对象,或者返回要记录的字符串或对象的函数。请参阅备注。
返回值
Logger 本身。
备注
您不限于只记录字符串。您可以记录对象、数组、日期、数字、布尔值甚至正则表达式。这些都会在记录之前转换为字符串。
如果生成日志信息成本很高,那么您只会希望在信息实际被记录时才这样做 - 即,所记录信息的严重级别超过日志记录器的级别等。
为了解决这个问题,您可以传递一个函数而不是信息本身。此函数必须返回信息。只有当日志信息实际被记录时才会调用它。
您甚至可以让函数返回另一个返回实际信息的函数 - 或者另一个函数,依此类推。请确保此链中没有循环引用,否则会导致堆栈溢出。
示例
这会创建一个严重级别为 2500 的日志消息“log message”。
JL().log(2500, "log message");
这会记录一个对象。
var obj = {"f1": "v1", "f2": "v2"}; JL().log(2500, obj);
这会传递一个生成日志信息的函数。只有当日志信息实际被记录时才会调用该函数。
JL().log(2500, function() { return "log message"; });
Exception 对象
允许您创建包含 JSON 对象和内部异常的自定义异常。
备注
与 标准 Error 对象 类似,Exception 对象允许您在出现问题时抛出自定义异常。
function f(i, j) { if (i < 10) { throw new JL.Exception("i is too small!"); } ... }
添加信息以辅助调试
但是,您可以传递一个包含更多信息的 JSON 对象,而不是字符串,以帮助您解决问题。
function f(i, j) { if (i < 10) { throw new JL.Exception({ "message": "i is too small!", "i": i, "j": j }); } ... }
添加内部异常
Exception 对象支持内部异常 - 基本上是将一个异常存储在另一个异常内。要了解其工作原理,请考虑此代码:
function f2(v) { var x, y; ... some code if (somethingWentWrong) { throw new JL.Exception({ "x": x, "y": y, "v": v }); } } function f1(anArray) { var i; for(i = 0; i < anArray.length; i++) { f2(anArray[i]); } } try { f1([1, 2, 3]); } catch(e) { JL().fatalException("Exception was thrown!", e); }
函数 f2 可能会抛出异常。如果这样做,它会将所有相关信息放入异常中,以使解决问题更容易。
但是,函数 f1 也包含可能相关的信息,例如索引 i 的值。最好以某种方式将该信息添加到异常中。
在函数 f1 中捕获异常,然后抛出一个包含函数 f2 存储的所有信息以及索引 i 的新异常是可能的。但这将很复杂,并且我们会丢失原始异常的堆栈跟踪。
最简单的解决方案是在函数 f2 中捕获异常,然后抛出一个包含原始异常以及任何附加信息的新异常。这样,我们可以保留原始异常中存储的所有信息,包括其堆栈跟踪。更改将在下方以红色显示。
function f2(v) { var x, y; ... some code if (somethingWentWrong) { throw new JL.Exception({ "x": x, "y": y, "v": v }); } } function f1(anArray) { var i; try { for(i = 0; i < anArray.length; i++) { f2(anArray[i]); } } catch(e) { // Throw new exception that contains the original one throw new JL.Exception({ "i": i }, e); } } try { f1([1, 2, 3]); } catch(e) { JL().fatalException("Exception was thrown!", e); }
fatalException 函数能够读取 Exception 对象中的附加信息和内部异常,并将它们全部记录下来。
如果您愿意,没有什么可以阻止您拥有一个本身具有内部异常的内部异常。您可以深入任意级别。
下一部分
在 JSNLog 的第二部分中,您详细了解了 JSNLog 提供的所有 JavaScript 函数。 下一部分 将介绍您可以在 web.config 中使用的所有元素和属性来配置您的 JavaScript 日志记录器。
如果您喜欢这篇文章,请投它一票。