@larablox/monolog 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/out/Monolog/Attribute/AsMonologProcessor.d.ts +30 -0
- package/out/Monolog/Attribute/AsMonologProcessor.luau +59 -0
- package/out/Monolog/Attribute/WithMonologChannel.d.ts +18 -0
- package/out/Monolog/Attribute/WithMonologChannel.luau +33 -0
- package/out/Monolog/Formatter/FormatterInterface.d.ts +8 -0
- package/out/Monolog/Formatter/FormatterInterface.luau +3 -0
- package/out/Monolog/Formatter/HtmlFormatter.d.ts +23 -0
- package/out/Monolog/Formatter/HtmlFormatter.luau +128 -0
- package/out/Monolog/Formatter/JsonFormatter.d.ts +34 -0
- package/out/Monolog/Formatter/JsonFormatter.luau +114 -0
- package/out/Monolog/Formatter/LineFormatter.d.ts +52 -0
- package/out/Monolog/Formatter/LineFormatter.luau +228 -0
- package/out/Monolog/Formatter/NormalizerFormatter.d.ts +87 -0
- package/out/Monolog/Formatter/NormalizerFormatter.luau +214 -0
- package/out/Monolog/Formatter/ScalarFormatter.d.ts +19 -0
- package/out/Monolog/Formatter/ScalarFormatter.luau +53 -0
- package/out/Monolog/Handler/AbstractHandler.d.ts +22 -0
- package/out/Monolog/Handler/AbstractHandler.luau +50 -0
- package/out/Monolog/Handler/AbstractProcessingHandler.d.ts +30 -0
- package/out/Monolog/Handler/AbstractProcessingHandler.luau +79 -0
- package/out/Monolog/Handler/Handler.d.ts +15 -0
- package/out/Monolog/Handler/Handler.luau +25 -0
- package/out/Monolog/Handler/HandlerInterface.d.ts +12 -0
- package/out/Monolog/Handler/HandlerInterface.luau +3 -0
- package/out/Monolog/Handler/NullHandler.d.ts +10 -0
- package/out/Monolog/Handler/NullHandler.luau +36 -0
- package/out/Monolog/Handler/RobloxConsoleHandler.d.ts +55 -0
- package/out/Monolog/Handler/RobloxConsoleHandler.luau +141 -0
- package/out/Monolog/Handler/TestHandler.d.ts +90 -0
- package/out/Monolog/Handler/TestHandler.luau +288 -0
- package/out/Monolog/Level.d.ts +38 -0
- package/out/Monolog/Level.luau +119 -0
- package/out/Monolog/LogRecord.d.ts +43 -0
- package/out/Monolog/LogRecord.luau +77 -0
- package/out/Monolog/Logger.d.ts +93 -0
- package/out/Monolog/Logger.luau +248 -0
- package/out/Monolog/LoggerInterface.d.ts +33 -0
- package/out/Monolog/LoggerInterface.luau +15 -0
- package/out/Monolog/Processor/ClosureContextProcessor.d.ts +13 -0
- package/out/Monolog/Processor/ClosureContextProcessor.luau +76 -0
- package/out/Monolog/Processor/IntrospectionProcessor.d.ts +33 -0
- package/out/Monolog/Processor/IntrospectionProcessor.luau +69 -0
- package/out/Monolog/Processor/MemoryPeakUsageProcessor.d.ts +17 -0
- package/out/Monolog/Processor/MemoryPeakUsageProcessor.luau +49 -0
- package/out/Monolog/Processor/MemoryProcessor.d.ts +20 -0
- package/out/Monolog/Processor/MemoryProcessor.luau +41 -0
- package/out/Monolog/Processor/MemoryUsageProcessor.d.ts +12 -0
- package/out/Monolog/Processor/MemoryUsageProcessor.luau +38 -0
- package/out/Monolog/Processor/ProcessIdProcessor.d.ts +13 -0
- package/out/Monolog/Processor/ProcessIdProcessor.luau +33 -0
- package/out/Monolog/Processor/ProcessorInterface.d.ts +13 -0
- package/out/Monolog/Processor/ProcessorInterface.luau +20 -0
- package/out/Monolog/Processor/PsrLogMessageProcessor.d.ts +12 -0
- package/out/Monolog/Processor/PsrLogMessageProcessor.luau +62 -0
- package/out/Monolog/Processor/TagProcessor.d.ts +12 -0
- package/out/Monolog/Processor/TagProcessor.luau +46 -0
- package/out/Monolog/Processor/UidProcessor.d.ts +18 -0
- package/out/Monolog/Processor/UidProcessor.luau +53 -0
- package/out/Monolog/Registry.d.ts +21 -0
- package/out/Monolog/Registry.luau +86 -0
- package/out/Monolog/ResettableInterface.d.ts +11 -0
- package/out/Monolog/ResettableInterface.luau +21 -0
- package/out/Monolog/Test/MonologTestCase.d.ts +26 -0
- package/out/Monolog/Test/MonologTestCase.luau +73 -0
- package/out/Monolog/Test/TestCase.d.ts +4 -0
- package/out/Monolog/Test/TestCase.luau +25 -0
- package/out/Monolog/Utils.d.ts +21 -0
- package/out/Monolog/Utils.luau +181 -0
- package/out/index.d.ts +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
type Constructor = new (...args: Array<unknown>) => object;
|
|
2
|
+
type Target = Constructor | object;
|
|
3
|
+
/** PHP: `AsMonologProcessor`'s constructor parameters. */
|
|
4
|
+
export interface AsMonologProcessorOptions {
|
|
5
|
+
/** The logging channel the processor should be pushed to. */
|
|
6
|
+
channel?: string;
|
|
7
|
+
/** The handler the processor should be pushed to. */
|
|
8
|
+
handler?: string;
|
|
9
|
+
/** The method that processes the records, if the decorator is used at the class level. */
|
|
10
|
+
method?: string;
|
|
11
|
+
/** The priority of the processor so the order can be determined. */
|
|
12
|
+
priority?: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* PHP: `Monolog\Attribute\AsMonologProcessor`.
|
|
16
|
+
*
|
|
17
|
+
* A reusable class-or-method decorator to help configure a class or a method
|
|
18
|
+
* as a processor. Using it offers no guarantee: it needs to be leveraged by a
|
|
19
|
+
* Monolog third-party consumer. Using it with this library alone has no
|
|
20
|
+
* effect at all: processors still need to be turned into a callable and
|
|
21
|
+
* manually pushed to loggers and to processable handlers.
|
|
22
|
+
*
|
|
23
|
+
* PHP's `IS_REPEATABLE` lets the attribute be applied more than once to the
|
|
24
|
+
* same target; there is no attribute system here to grant that, so this
|
|
25
|
+
* stores an array of registrations per decorated target instead of one.
|
|
26
|
+
*/
|
|
27
|
+
export declare function AsMonologProcessor(options?: AsMonologProcessorOptions): (target: Target, propertyKey?: string) => void;
|
|
28
|
+
/** Reads back every registration a class or method was decorated with. */
|
|
29
|
+
export declare function getMonologProcessorRegistrations(target: Target): Array<AsMonologProcessorOptions>;
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
--* PHP: `AsMonologProcessor`'s constructor parameters.
|
|
3
|
+
local REGISTRATIONS = {}
|
|
4
|
+
--[[
|
|
5
|
+
*
|
|
6
|
+
* PHP: `Monolog\Attribute\AsMonologProcessor`.
|
|
7
|
+
*
|
|
8
|
+
* A reusable class-or-method decorator to help configure a class or a method
|
|
9
|
+
* as a processor. Using it offers no guarantee: it needs to be leveraged by a
|
|
10
|
+
* Monolog third-party consumer. Using it with this library alone has no
|
|
11
|
+
* effect at all: processors still need to be turned into a callable and
|
|
12
|
+
* manually pushed to loggers and to processable handlers.
|
|
13
|
+
*
|
|
14
|
+
* PHP's `IS_REPEATABLE` lets the attribute be applied more than once to the
|
|
15
|
+
* same target; there is no attribute system here to grant that, so this
|
|
16
|
+
* stores an array of registrations per decorated target instead of one.
|
|
17
|
+
|
|
18
|
+
]]
|
|
19
|
+
local function AsMonologProcessor(options)
|
|
20
|
+
if options == nil then
|
|
21
|
+
options = {}
|
|
22
|
+
end
|
|
23
|
+
return function(target, propertyKey)
|
|
24
|
+
local _object = {
|
|
25
|
+
channel = options.channel,
|
|
26
|
+
handler = options.handler,
|
|
27
|
+
}
|
|
28
|
+
local _left = "method"
|
|
29
|
+
local _condition = propertyKey
|
|
30
|
+
if _condition == nil then
|
|
31
|
+
_condition = options.method
|
|
32
|
+
end
|
|
33
|
+
_object[_left] = _condition
|
|
34
|
+
_object.priority = options.priority
|
|
35
|
+
local registration = _object
|
|
36
|
+
local _target = target
|
|
37
|
+
local _condition_1 = REGISTRATIONS[_target]
|
|
38
|
+
if _condition_1 == nil then
|
|
39
|
+
_condition_1 = {}
|
|
40
|
+
end
|
|
41
|
+
local existing = _condition_1
|
|
42
|
+
table.insert(existing, registration)
|
|
43
|
+
local _target_1 = target
|
|
44
|
+
REGISTRATIONS[_target_1] = existing
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
--* Reads back every registration a class or method was decorated with.
|
|
48
|
+
local function getMonologProcessorRegistrations(target)
|
|
49
|
+
local _target = target
|
|
50
|
+
local _condition = REGISTRATIONS[_target]
|
|
51
|
+
if _condition == nil then
|
|
52
|
+
_condition = {}
|
|
53
|
+
end
|
|
54
|
+
return _condition
|
|
55
|
+
end
|
|
56
|
+
return {
|
|
57
|
+
AsMonologProcessor = AsMonologProcessor,
|
|
58
|
+
getMonologProcessorRegistrations = getMonologProcessorRegistrations,
|
|
59
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
type Constructor = new (...args: Array<unknown>) => object;
|
|
2
|
+
/**
|
|
3
|
+
* PHP: `Monolog\Attribute\WithMonologChannel`.
|
|
4
|
+
*
|
|
5
|
+
* A reusable class decorator to help configure a class as expecting a given
|
|
6
|
+
* logger channel. Using it offers no guarantee: it needs to be leveraged by a
|
|
7
|
+
* Monolog third-party consumer. Using it with this library alone has no
|
|
8
|
+
* effect at all: wiring a logger instance into other classes is not managed
|
|
9
|
+
* by Monolog.
|
|
10
|
+
*
|
|
11
|
+
* PHP attributes are read back through reflection; there is no reflection API
|
|
12
|
+
* on this platform, so the channel is recorded in a module-level map keyed by
|
|
13
|
+
* the decorated class instead, readable back with `getMonologChannel()`.
|
|
14
|
+
*/
|
|
15
|
+
export declare function WithMonologChannel(channel: string): (target: Constructor) => void;
|
|
16
|
+
/** Reads back the channel a class was decorated with, if any. */
|
|
17
|
+
export declare function getMonologChannel(target: Constructor): string | undefined;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local CHANNELS = {}
|
|
3
|
+
--[[
|
|
4
|
+
*
|
|
5
|
+
* PHP: `Monolog\Attribute\WithMonologChannel`.
|
|
6
|
+
*
|
|
7
|
+
* A reusable class decorator to help configure a class as expecting a given
|
|
8
|
+
* logger channel. Using it offers no guarantee: it needs to be leveraged by a
|
|
9
|
+
* Monolog third-party consumer. Using it with this library alone has no
|
|
10
|
+
* effect at all: wiring a logger instance into other classes is not managed
|
|
11
|
+
* by Monolog.
|
|
12
|
+
*
|
|
13
|
+
* PHP attributes are read back through reflection; there is no reflection API
|
|
14
|
+
* on this platform, so the channel is recorded in a module-level map keyed by
|
|
15
|
+
* the decorated class instead, readable back with `getMonologChannel()`.
|
|
16
|
+
|
|
17
|
+
]]
|
|
18
|
+
local function WithMonologChannel(channel)
|
|
19
|
+
return function(target)
|
|
20
|
+
local _target = target
|
|
21
|
+
local _channel = channel
|
|
22
|
+
CHANNELS[_target] = _channel
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
--* Reads back the channel a class was decorated with, if any.
|
|
26
|
+
local function getMonologChannel(target)
|
|
27
|
+
local _target = target
|
|
28
|
+
return CHANNELS[_target]
|
|
29
|
+
end
|
|
30
|
+
return {
|
|
31
|
+
WithMonologChannel = WithMonologChannel,
|
|
32
|
+
getMonologChannel = getMonologChannel,
|
|
33
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { LogRecord } from "../LogRecord";
|
|
2
|
+
/** PHP: `Monolog\Formatter\FormatterInterface`. */
|
|
3
|
+
export interface FormatterInterface {
|
|
4
|
+
/** Formats a log record. */
|
|
5
|
+
format(record: LogRecord): string;
|
|
6
|
+
/** Formats a set of log records. */
|
|
7
|
+
formatBatch(records: Array<LogRecord>): string;
|
|
8
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Level } from "../Level";
|
|
2
|
+
import { NormalizerFormatter } from "./NormalizerFormatter";
|
|
3
|
+
import type { LogRecord } from "../LogRecord";
|
|
4
|
+
/**
|
|
5
|
+
* PHP: `Monolog\Formatter\HtmlFormatter`.
|
|
6
|
+
*
|
|
7
|
+
* There is no `htmlspecialchars()` on this platform; `escapeHtml()` below
|
|
8
|
+
* escapes the same characters PHP's `ENT_NOQUOTES` mode does (`&`, `<`, `>`),
|
|
9
|
+
* leaving single/double quotes alone exactly as `ENT_NOQUOTES` does.
|
|
10
|
+
*/
|
|
11
|
+
export declare class HtmlFormatter extends NormalizerFormatter {
|
|
12
|
+
/** Translates Monolog log levels to HTML color priorities. */
|
|
13
|
+
protected getLevelColor(level: Level): string;
|
|
14
|
+
/** Creates an HTML table row. */
|
|
15
|
+
protected addRow(th: string, td?: string, escapeTd?: boolean): string;
|
|
16
|
+
/** Create an HTML h1 tag. */
|
|
17
|
+
protected addTitle(title: string, level: Level): string;
|
|
18
|
+
/** Formats a log record. */
|
|
19
|
+
format(record: LogRecord): string;
|
|
20
|
+
/** Formats a set of log records. */
|
|
21
|
+
formatBatch(records: Array<LogRecord>): string;
|
|
22
|
+
protected convertToString(data: unknown): string;
|
|
23
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local _Level = TS.import(script, script.Parent.Parent, "Level")
|
|
4
|
+
local Level = _Level.Level
|
|
5
|
+
local Levels = _Level.Levels
|
|
6
|
+
local NormalizerFormatter = TS.import(script, script.Parent, "NormalizerFormatter").NormalizerFormatter
|
|
7
|
+
local Utils = TS.import(script, script.Parent.Parent, "Utils").Utils
|
|
8
|
+
local LEVEL_COLORS = {
|
|
9
|
+
[Level.Debug] = "#CCCCCC",
|
|
10
|
+
[Level.Info] = "#28A745",
|
|
11
|
+
[Level.Notice] = "#17A2B8",
|
|
12
|
+
[Level.Warning] = "#FFC107",
|
|
13
|
+
[Level.Error] = "#FD7E14",
|
|
14
|
+
[Level.Critical] = "#DC3545",
|
|
15
|
+
[Level.Alert] = "#821722",
|
|
16
|
+
[Level.Emergency] = "#000000",
|
|
17
|
+
}
|
|
18
|
+
local function escapeHtml(value)
|
|
19
|
+
local out = string.gsub(value, "&", "&")
|
|
20
|
+
out = string.gsub(out, "<", "<")
|
|
21
|
+
out = string.gsub(out, ">", ">")
|
|
22
|
+
return out
|
|
23
|
+
end
|
|
24
|
+
--[[
|
|
25
|
+
*
|
|
26
|
+
* PHP: `Monolog\Formatter\HtmlFormatter`.
|
|
27
|
+
*
|
|
28
|
+
* There is no `htmlspecialchars()` on this platform; `escapeHtml()` below
|
|
29
|
+
* escapes the same characters PHP's `ENT_NOQUOTES` mode does (`&`, `<`, `>`),
|
|
30
|
+
* leaving single/double quotes alone exactly as `ENT_NOQUOTES` does.
|
|
31
|
+
|
|
32
|
+
]]
|
|
33
|
+
local HtmlFormatter
|
|
34
|
+
do
|
|
35
|
+
local super = NormalizerFormatter
|
|
36
|
+
HtmlFormatter = setmetatable({}, {
|
|
37
|
+
__tostring = function()
|
|
38
|
+
return "HtmlFormatter"
|
|
39
|
+
end,
|
|
40
|
+
__index = super,
|
|
41
|
+
})
|
|
42
|
+
HtmlFormatter.__index = HtmlFormatter
|
|
43
|
+
function HtmlFormatter.new(...)
|
|
44
|
+
local self = setmetatable({}, HtmlFormatter)
|
|
45
|
+
return self:constructor(...) or self
|
|
46
|
+
end
|
|
47
|
+
function HtmlFormatter:constructor(...)
|
|
48
|
+
super.constructor(self, ...)
|
|
49
|
+
end
|
|
50
|
+
function HtmlFormatter:getLevelColor(level)
|
|
51
|
+
local _level = level
|
|
52
|
+
local _condition = LEVEL_COLORS[_level]
|
|
53
|
+
if _condition == nil then
|
|
54
|
+
_condition = "#000000"
|
|
55
|
+
end
|
|
56
|
+
return _condition
|
|
57
|
+
end
|
|
58
|
+
function HtmlFormatter:addRow(th, td, escapeTd)
|
|
59
|
+
if td == nil then
|
|
60
|
+
td = " "
|
|
61
|
+
end
|
|
62
|
+
if escapeTd == nil then
|
|
63
|
+
escapeTd = true
|
|
64
|
+
end
|
|
65
|
+
local heading = escapeHtml(th)
|
|
66
|
+
local cell = if escapeTd then `<pre>{escapeHtml(td)}</pre>` else td
|
|
67
|
+
return `<tr style="padding: 4px;text-align: left;">\n<th style="vertical-align: top;background: #ccc;color: #000" width="100">{heading}:</th>\n<td style="padding: 4px;text-align: left;vertical-align: top;background: #eee;color: #000">{cell}</td>\n</tr>`
|
|
68
|
+
end
|
|
69
|
+
function HtmlFormatter:addTitle(title, level)
|
|
70
|
+
return `<h1 style="background: {self:getLevelColor(level)};color: #ffffff;padding: 5px;" class="monolog-output">{escapeHtml(title)}</h1>`
|
|
71
|
+
end
|
|
72
|
+
function HtmlFormatter:format(record)
|
|
73
|
+
local output = self:addTitle(Levels:getName(record.level), record.level)
|
|
74
|
+
output ..= '<table cellspacing="1" width="100%" class="monolog-output">'
|
|
75
|
+
output ..= self:addRow("Message", record.message)
|
|
76
|
+
output ..= self:addRow("Time", self:formatDate(record.datetime))
|
|
77
|
+
output ..= self:addRow("Channel", record.channel)
|
|
78
|
+
if (next(record.context)) ~= nil then
|
|
79
|
+
local embedded = '<table cellspacing="1" width="100%">'
|
|
80
|
+
for key, value in pairs(record.context) do
|
|
81
|
+
embedded ..= self:addRow(tostring(key), self:convertToString(value))
|
|
82
|
+
end
|
|
83
|
+
embedded ..= "</table>"
|
|
84
|
+
output ..= self:addRow("Context", embedded, false)
|
|
85
|
+
end
|
|
86
|
+
if (next(record.extra)) ~= nil then
|
|
87
|
+
local embedded = '<table cellspacing="1" width="100%">'
|
|
88
|
+
for key, value in pairs(record.extra) do
|
|
89
|
+
embedded ..= self:addRow(tostring(key), self:convertToString(value))
|
|
90
|
+
end
|
|
91
|
+
embedded ..= "</table>"
|
|
92
|
+
output ..= self:addRow("Extra", embedded, false)
|
|
93
|
+
end
|
|
94
|
+
return `{output}</table>`
|
|
95
|
+
end
|
|
96
|
+
function HtmlFormatter:formatBatch(records)
|
|
97
|
+
local message = ""
|
|
98
|
+
for _, record in records do
|
|
99
|
+
message ..= self:format(record)
|
|
100
|
+
end
|
|
101
|
+
return message
|
|
102
|
+
end
|
|
103
|
+
function HtmlFormatter:convertToString(data)
|
|
104
|
+
local _condition = data == nil
|
|
105
|
+
if not _condition then
|
|
106
|
+
local _data = data
|
|
107
|
+
_condition = type(_data) == "string"
|
|
108
|
+
if not _condition then
|
|
109
|
+
local _data_1 = data
|
|
110
|
+
_condition = type(_data_1) == "number"
|
|
111
|
+
if not _condition then
|
|
112
|
+
local _data_2 = data
|
|
113
|
+
_condition = type(_data_2) == "boolean"
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
if _condition then
|
|
118
|
+
return if data == nil then "" else tostring(data)
|
|
119
|
+
end
|
|
120
|
+
-- Upstream always pretty-prints here regardless of the formatter's own
|
|
121
|
+
-- `setJsonPrettyPrint()` toggle -- call the encoder directly instead of
|
|
122
|
+
-- going through `toJson()`, which would use that toggle's value.
|
|
123
|
+
return Utils:jsonEncode(self:normalize(data), true)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
return {
|
|
127
|
+
HtmlFormatter = HtmlFormatter,
|
|
128
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { NormalizerFormatter } from "./NormalizerFormatter";
|
|
2
|
+
import type { LogRecord, RecordBag } from "../LogRecord";
|
|
3
|
+
/**
|
|
4
|
+
* PHP: `Monolog\Formatter\JsonFormatter`.
|
|
5
|
+
*
|
|
6
|
+
* Upstream marks an empty `context`/`extra` with `new \stdClass` so it
|
|
7
|
+
* encodes as `{}` rather than `[]`; there is no `\stdClass` here, so
|
|
8
|
+
* `markAsJsonObject()` marks the (still-empty) `RecordBag` instead -- see
|
|
9
|
+
* that function's comment in `Utils.ts`.
|
|
10
|
+
*/
|
|
11
|
+
export declare class JsonFormatter extends NormalizerFormatter {
|
|
12
|
+
protected batchMode: number;
|
|
13
|
+
protected appendNewline: boolean;
|
|
14
|
+
protected ignoreEmptyContextAndExtra: boolean;
|
|
15
|
+
static readonly BATCH_MODE_JSON = 1;
|
|
16
|
+
static readonly BATCH_MODE_NEWLINES = 2;
|
|
17
|
+
private includeStacktracesFlag;
|
|
18
|
+
constructor(batchMode?: number, appendNewline?: boolean, ignoreEmptyContextAndExtra?: boolean, includeStacktraces?: boolean);
|
|
19
|
+
/** The batch mode option configures the formatting style for multiple records. */
|
|
20
|
+
getBatchMode(): number;
|
|
21
|
+
/** True if newlines are appended to every formatted record. */
|
|
22
|
+
isAppendingNewlines(): boolean;
|
|
23
|
+
/** Formats a log record. */
|
|
24
|
+
format(record: LogRecord): string;
|
|
25
|
+
/** Formats a set of log records. */
|
|
26
|
+
formatBatch(records: Array<LogRecord>): string;
|
|
27
|
+
/** Kept for signature parity; there is no PHP trace string here -- see `LineFormatter`'s class comment. */
|
|
28
|
+
includeStacktraces(include?: boolean): this;
|
|
29
|
+
protected normalizeRecord(record: LogRecord): RecordBag;
|
|
30
|
+
/** Returns a JSON-encoded array of records. */
|
|
31
|
+
protected formatBatchJson(records: Array<LogRecord>): string;
|
|
32
|
+
/** Uses new lines to separate records instead of a JSON-encoded array. */
|
|
33
|
+
protected formatBatchNewlines(records: Array<LogRecord>): string;
|
|
34
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local NormalizerFormatter = TS.import(script, script.Parent, "NormalizerFormatter").NormalizerFormatter
|
|
4
|
+
local markAsJsonObject = TS.import(script, script.Parent.Parent, "Utils").markAsJsonObject
|
|
5
|
+
local function isEmptyBag(bag)
|
|
6
|
+
local key = next(bag)
|
|
7
|
+
return key == nil
|
|
8
|
+
end
|
|
9
|
+
--[[
|
|
10
|
+
*
|
|
11
|
+
* PHP: `Monolog\Formatter\JsonFormatter`.
|
|
12
|
+
*
|
|
13
|
+
* Upstream marks an empty `context`/`extra` with `new \stdClass` so it
|
|
14
|
+
* encodes as `{}` rather than `[]`; there is no `\stdClass` here, so
|
|
15
|
+
* `markAsJsonObject()` marks the (still-empty) `RecordBag` instead -- see
|
|
16
|
+
* that function's comment in `Utils.ts`.
|
|
17
|
+
|
|
18
|
+
]]
|
|
19
|
+
local JsonFormatter
|
|
20
|
+
do
|
|
21
|
+
local super = NormalizerFormatter
|
|
22
|
+
JsonFormatter = setmetatable({}, {
|
|
23
|
+
__tostring = function()
|
|
24
|
+
return "JsonFormatter"
|
|
25
|
+
end,
|
|
26
|
+
__index = super,
|
|
27
|
+
})
|
|
28
|
+
JsonFormatter.__index = JsonFormatter
|
|
29
|
+
function JsonFormatter.new(...)
|
|
30
|
+
local self = setmetatable({}, JsonFormatter)
|
|
31
|
+
return self:constructor(...) or self
|
|
32
|
+
end
|
|
33
|
+
function JsonFormatter:constructor(batchMode, appendNewline, ignoreEmptyContextAndExtra, includeStacktraces)
|
|
34
|
+
if batchMode == nil then
|
|
35
|
+
batchMode = JsonFormatter.BATCH_MODE_JSON
|
|
36
|
+
end
|
|
37
|
+
if appendNewline == nil then
|
|
38
|
+
appendNewline = true
|
|
39
|
+
end
|
|
40
|
+
if ignoreEmptyContextAndExtra == nil then
|
|
41
|
+
ignoreEmptyContextAndExtra = false
|
|
42
|
+
end
|
|
43
|
+
if includeStacktraces == nil then
|
|
44
|
+
includeStacktraces = false
|
|
45
|
+
end
|
|
46
|
+
super.constructor(self)
|
|
47
|
+
self.batchMode = batchMode
|
|
48
|
+
self.appendNewline = appendNewline
|
|
49
|
+
self.ignoreEmptyContextAndExtra = ignoreEmptyContextAndExtra
|
|
50
|
+
self.includeStacktracesFlag = includeStacktraces
|
|
51
|
+
end
|
|
52
|
+
function JsonFormatter:getBatchMode()
|
|
53
|
+
return self.batchMode
|
|
54
|
+
end
|
|
55
|
+
function JsonFormatter:isAppendingNewlines()
|
|
56
|
+
return self.appendNewline
|
|
57
|
+
end
|
|
58
|
+
function JsonFormatter:format(record)
|
|
59
|
+
local normalized = self:normalizeRecord(record)
|
|
60
|
+
return self:toJson(normalized) .. (if self.appendNewline then "\n" else "")
|
|
61
|
+
end
|
|
62
|
+
function JsonFormatter:formatBatch(records)
|
|
63
|
+
return if self.batchMode == JsonFormatter.BATCH_MODE_NEWLINES then self:formatBatchNewlines(records) else self:formatBatchJson(records)
|
|
64
|
+
end
|
|
65
|
+
function JsonFormatter:includeStacktraces(include)
|
|
66
|
+
if include == nil then
|
|
67
|
+
include = true
|
|
68
|
+
end
|
|
69
|
+
self.includeStacktracesFlag = include
|
|
70
|
+
return self
|
|
71
|
+
end
|
|
72
|
+
function JsonFormatter:normalizeRecord(record)
|
|
73
|
+
local normalized = super.normalizeRecord(self, record)
|
|
74
|
+
if isEmptyBag(normalized.context) then
|
|
75
|
+
if self.ignoreEmptyContextAndExtra then
|
|
76
|
+
normalized.context = nil
|
|
77
|
+
else
|
|
78
|
+
normalized.context = markAsJsonObject({})
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
if isEmptyBag(normalized.extra) then
|
|
82
|
+
if self.ignoreEmptyContextAndExtra then
|
|
83
|
+
normalized.extra = nil
|
|
84
|
+
else
|
|
85
|
+
normalized.extra = markAsJsonObject({})
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
return normalized
|
|
89
|
+
end
|
|
90
|
+
function JsonFormatter:formatBatchJson(records)
|
|
91
|
+
local normalized = {}
|
|
92
|
+
for _, record in records do
|
|
93
|
+
local _arg0 = self:normalizeRecord(record)
|
|
94
|
+
table.insert(normalized, _arg0)
|
|
95
|
+
end
|
|
96
|
+
return self:toJson(normalized)
|
|
97
|
+
end
|
|
98
|
+
function JsonFormatter:formatBatchNewlines(records)
|
|
99
|
+
local oldAppendNewline = self.appendNewline
|
|
100
|
+
self.appendNewline = false
|
|
101
|
+
local lines = {}
|
|
102
|
+
for _, record in records do
|
|
103
|
+
local _arg0 = self:format(record)
|
|
104
|
+
table.insert(lines, _arg0)
|
|
105
|
+
end
|
|
106
|
+
self.appendNewline = oldAppendNewline
|
|
107
|
+
return table.concat(lines, "\n")
|
|
108
|
+
end
|
|
109
|
+
JsonFormatter.BATCH_MODE_JSON = 1
|
|
110
|
+
JsonFormatter.BATCH_MODE_NEWLINES = 2
|
|
111
|
+
end
|
|
112
|
+
return {
|
|
113
|
+
JsonFormatter = JsonFormatter,
|
|
114
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { NormalizerFormatter } from "./NormalizerFormatter";
|
|
2
|
+
import type { LogRecord } from "../LogRecord";
|
|
3
|
+
/**
|
|
4
|
+
* PHP: `Monolog\Formatter\LineFormatter`.
|
|
5
|
+
*
|
|
6
|
+
* The default format drops PHP's trailing newline -- `print` and `warn` add
|
|
7
|
+
* their own.
|
|
8
|
+
*
|
|
9
|
+
* `includeStacktraces`/`indentStacktraces`/`stacktracesParser` are kept for
|
|
10
|
+
* API-shape parity but have nothing to act on: they format PHP's
|
|
11
|
+
* `getTraceAsString()` output, and there is no PHP exception/stack-trace
|
|
12
|
+
* object on this platform for `NormalizerFormatter.normalize()` to have kept
|
|
13
|
+
* a trace from in the first place (see that file's class comment). Setting
|
|
14
|
+
* them changes bookkeeping only, never formatted output.
|
|
15
|
+
*
|
|
16
|
+
* TypeScript can't have a property and a method share a name the way PHP's
|
|
17
|
+
* `$ignoreEmptyContextAndExtra`/`ignoreEmptyContextAndExtra()` (and similarly
|
|
18
|
+
* `allowInlineLineBreaks`, `includeStacktraces`) do -- each such flag's
|
|
19
|
+
* backing field is suffixed (`...Flag`/`...Value`) below; the public method
|
|
20
|
+
* names match upstream exactly.
|
|
21
|
+
*/
|
|
22
|
+
export declare class LineFormatter extends NormalizerFormatter {
|
|
23
|
+
protected readonly format_: string;
|
|
24
|
+
static readonly SIMPLE_FORMAT = "[%datetime%] %channel%.%level_name%: %message% %context% %extra%";
|
|
25
|
+
static readonly SIMPLE_DATE: string;
|
|
26
|
+
private allowInlineLineBreaksFlag;
|
|
27
|
+
private ignoreEmptyContextAndExtraFlag;
|
|
28
|
+
private includeStacktracesFlag;
|
|
29
|
+
private indentStacktracesValue;
|
|
30
|
+
private stacktracesParser?;
|
|
31
|
+
private maxLevelNameLength?;
|
|
32
|
+
constructor(format_?: string, dateFormat?: string, allowInlineLineBreaks?: boolean, ignoreEmptyContextAndExtra?: boolean, includeStacktraces?: boolean);
|
|
33
|
+
/** Kept for signature parity; there is no PHP trace string to reformat -- see the class comment. */
|
|
34
|
+
includeStacktraces(include?: boolean, parser?: (record: LogRecord) => string): this;
|
|
35
|
+
/** Kept for signature parity; there is no stack trace here to indent -- see the class comment. */
|
|
36
|
+
indentStacktraces(indent: string): this;
|
|
37
|
+
allowInlineLineBreaks(allow?: boolean): this;
|
|
38
|
+
ignoreEmptyContextAndExtra(ignore?: boolean): this;
|
|
39
|
+
/** Allows cutting the level name to fixed-length levels, e.g. "INF" for "INFO" if set to 3. */
|
|
40
|
+
setMaxLevelNameLength(maxLevelNameLength?: number): this;
|
|
41
|
+
/** Formats a log record. */
|
|
42
|
+
format(record: LogRecord): string;
|
|
43
|
+
/**
|
|
44
|
+
* Upstream concatenates records with no separator, relying on
|
|
45
|
+
* `SIMPLE_FORMAT`'s trailing `\n`; this port's `SIMPLE_FORMAT` drops that
|
|
46
|
+
* newline (see the class comment), so records are joined with one instead.
|
|
47
|
+
*/
|
|
48
|
+
formatBatch(records: Array<LogRecord>): string;
|
|
49
|
+
stringify(value: unknown): string;
|
|
50
|
+
protected convertToString(data: unknown): string;
|
|
51
|
+
protected replaceNewlines(str: string): string;
|
|
52
|
+
}
|