@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,288 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local AbstractProcessingHandler = TS.import(script, script.Parent, "AbstractProcessingHandler").AbstractProcessingHandler
|
|
4
|
+
local Level = TS.import(script, script.Parent.Parent, "Level").Level
|
|
5
|
+
local Logger = TS.import(script, script.Parent.Parent, "Logger").Logger
|
|
6
|
+
--* PHP: the `array{message: string, context?: mixed[]}` shape `hasRecord()` accepts.
|
|
7
|
+
--* PHP: the `callable(LogRecord, int): mixed $predicate` shape `hasRecordThatPasses()` accepts.
|
|
8
|
+
--* Deep-equality check for two context/extra bags -- PHP's `!==` on arrays compares recursively.
|
|
9
|
+
local function bagsEqual(a, b)
|
|
10
|
+
if a == b then
|
|
11
|
+
return true
|
|
12
|
+
end
|
|
13
|
+
local _a = a
|
|
14
|
+
local _condition = not (type(_a) == "table")
|
|
15
|
+
if not _condition then
|
|
16
|
+
local _b = b
|
|
17
|
+
_condition = not (type(_b) == "table")
|
|
18
|
+
end
|
|
19
|
+
if _condition then
|
|
20
|
+
return false
|
|
21
|
+
end
|
|
22
|
+
local aBag = a
|
|
23
|
+
local bBag = b
|
|
24
|
+
local seen = {}
|
|
25
|
+
for key, value in pairs(aBag) do
|
|
26
|
+
local stringKey = tostring(key)
|
|
27
|
+
seen[stringKey] = true
|
|
28
|
+
if not bagsEqual(value, bBag[stringKey]) then
|
|
29
|
+
return false
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
for key in pairs(bBag) do
|
|
33
|
+
local _arg0 = tostring(key)
|
|
34
|
+
if not (seen[_arg0] ~= nil) then
|
|
35
|
+
return false
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
return true
|
|
39
|
+
end
|
|
40
|
+
--[[
|
|
41
|
+
*
|
|
42
|
+
* PHP: `Monolog\Handler\TestHandler`.
|
|
43
|
+
*
|
|
44
|
+
* Ships in Monolog's real (non-dev) autoload, not `autoload-dev`, because
|
|
45
|
+
* library consumers use it in their own tests -- the same reason this port
|
|
46
|
+
* carries it under `src/Monolog/Handler` rather than `tests/`, and the same
|
|
47
|
+
* justification already made for `Monolog\Test\MonologTestCase`.
|
|
48
|
+
*
|
|
49
|
+
* Upstream's per-level shorthands (`hasWarning()`, `hasWarningRecords()`,
|
|
50
|
+
* `hasWarningThatContains()`, `hasWarningThatMatches()`,
|
|
51
|
+
* `hasWarningThatPasses()`, one set per `Level` case) are dispatched through
|
|
52
|
+
* PHP's `__call` magic method: it regex-matches the requested method name
|
|
53
|
+
* apart into a level name and a generic method name, then redirects to the
|
|
54
|
+
* matching `hasRecord*()` method with the parsed `Level` appended. Luau has
|
|
55
|
+
* no dynamic method dispatch to replicate that with, so every shorthand is
|
|
56
|
+
* spelled out explicitly below instead -- one small delegating method per
|
|
57
|
+
* level per kind, same names, same behavior.
|
|
58
|
+
*
|
|
59
|
+
* `hasRecordThatMatches()`/the `*ThatMatches()` shorthands use Luau string
|
|
60
|
+
* patterns (`string.match`) rather than upstream's PCRE (`preg_match`) --
|
|
61
|
+
* there is no PCRE engine on this platform. Pattern syntax differs
|
|
62
|
+
* (`%d`/`%a`/... instead of `\d`/`\w`/...); callers passing a `regex` should
|
|
63
|
+
* pass a Lua pattern, not a PCRE one.
|
|
64
|
+
|
|
65
|
+
]]
|
|
66
|
+
local TestHandler
|
|
67
|
+
do
|
|
68
|
+
local super = AbstractProcessingHandler
|
|
69
|
+
TestHandler = setmetatable({}, {
|
|
70
|
+
__tostring = function()
|
|
71
|
+
return "TestHandler"
|
|
72
|
+
end,
|
|
73
|
+
__index = super,
|
|
74
|
+
})
|
|
75
|
+
TestHandler.__index = TestHandler
|
|
76
|
+
function TestHandler.new(...)
|
|
77
|
+
local self = setmetatable({}, TestHandler)
|
|
78
|
+
return self:constructor(...) or self
|
|
79
|
+
end
|
|
80
|
+
function TestHandler:constructor(...)
|
|
81
|
+
super.constructor(self, ...)
|
|
82
|
+
self.records = {}
|
|
83
|
+
self.recordsByLevel = {}
|
|
84
|
+
self.skipReset = false
|
|
85
|
+
end
|
|
86
|
+
function TestHandler:getRecords()
|
|
87
|
+
return self.records
|
|
88
|
+
end
|
|
89
|
+
function TestHandler:clear()
|
|
90
|
+
self.records = {}
|
|
91
|
+
self.recordsByLevel = {}
|
|
92
|
+
end
|
|
93
|
+
function TestHandler:reset()
|
|
94
|
+
if not self.skipReset then
|
|
95
|
+
self:clear()
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
function TestHandler:setSkipReset(skipReset)
|
|
99
|
+
self.skipReset = skipReset
|
|
100
|
+
end
|
|
101
|
+
function TestHandler:hasRecords(level)
|
|
102
|
+
local _recordsByLevel = self.recordsByLevel
|
|
103
|
+
local _arg0 = Logger:toMonologLevel(level)
|
|
104
|
+
return _recordsByLevel[_arg0] ~= nil
|
|
105
|
+
end
|
|
106
|
+
function TestHandler:hasRecord(recordAssertions, level)
|
|
107
|
+
local _recordAssertions = recordAssertions
|
|
108
|
+
local assertions = if type(_recordAssertions) == "string" then {
|
|
109
|
+
message = recordAssertions,
|
|
110
|
+
} else recordAssertions
|
|
111
|
+
return self:hasRecordThatPasses(function(record)
|
|
112
|
+
if record.message ~= assertions.message then
|
|
113
|
+
return false
|
|
114
|
+
end
|
|
115
|
+
if assertions.context ~= nil and not bagsEqual(record.context, assertions.context) then
|
|
116
|
+
return false
|
|
117
|
+
end
|
|
118
|
+
return true
|
|
119
|
+
end, level)
|
|
120
|
+
end
|
|
121
|
+
function TestHandler:hasRecordThatContains(message, level)
|
|
122
|
+
return self:hasRecordThatPasses(function(record)
|
|
123
|
+
local _message = record.message
|
|
124
|
+
local _message_1 = message
|
|
125
|
+
return (string.find(_message, _message_1, 1, true)) ~= nil
|
|
126
|
+
end, level)
|
|
127
|
+
end
|
|
128
|
+
function TestHandler:hasRecordThatMatches(regex, level)
|
|
129
|
+
return self:hasRecordThatPasses(function(record)
|
|
130
|
+
local _message = record.message
|
|
131
|
+
local _regex = regex
|
|
132
|
+
return (string.match(_message, _regex)) ~= nil
|
|
133
|
+
end, level)
|
|
134
|
+
end
|
|
135
|
+
function TestHandler:hasRecordThatPasses(predicate, level)
|
|
136
|
+
local resolvedLevel = Logger:toMonologLevel(level)
|
|
137
|
+
local records = self.recordsByLevel[resolvedLevel]
|
|
138
|
+
if records == nil then
|
|
139
|
+
return false
|
|
140
|
+
end
|
|
141
|
+
for index = 0, #records - 1 do
|
|
142
|
+
if predicate(records[index + 1], index) then
|
|
143
|
+
return true
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
return false
|
|
147
|
+
end
|
|
148
|
+
function TestHandler:write(record)
|
|
149
|
+
local _recordsByLevel = self.recordsByLevel
|
|
150
|
+
local _level = record.level
|
|
151
|
+
local _condition = _recordsByLevel[_level]
|
|
152
|
+
if _condition == nil then
|
|
153
|
+
_condition = {}
|
|
154
|
+
end
|
|
155
|
+
local byLevel = _condition
|
|
156
|
+
local _record = record
|
|
157
|
+
table.insert(byLevel, _record)
|
|
158
|
+
local _recordsByLevel_1 = self.recordsByLevel
|
|
159
|
+
local _level_1 = record.level
|
|
160
|
+
_recordsByLevel_1[_level_1] = byLevel
|
|
161
|
+
local _records = self.records
|
|
162
|
+
local _record_1 = record
|
|
163
|
+
table.insert(_records, _record_1)
|
|
164
|
+
end
|
|
165
|
+
function TestHandler:hasEmergencyRecords()
|
|
166
|
+
return self:hasRecords(Level.Emergency)
|
|
167
|
+
end
|
|
168
|
+
function TestHandler:hasEmergency(recordAssertions)
|
|
169
|
+
return self:hasRecord(recordAssertions, Level.Emergency)
|
|
170
|
+
end
|
|
171
|
+
function TestHandler:hasEmergencyThatContains(message)
|
|
172
|
+
return self:hasRecordThatContains(message, Level.Emergency)
|
|
173
|
+
end
|
|
174
|
+
function TestHandler:hasEmergencyThatMatches(regex)
|
|
175
|
+
return self:hasRecordThatMatches(regex, Level.Emergency)
|
|
176
|
+
end
|
|
177
|
+
function TestHandler:hasEmergencyThatPasses(predicate)
|
|
178
|
+
return self:hasRecordThatPasses(predicate, Level.Emergency)
|
|
179
|
+
end
|
|
180
|
+
function TestHandler:hasAlertRecords()
|
|
181
|
+
return self:hasRecords(Level.Alert)
|
|
182
|
+
end
|
|
183
|
+
function TestHandler:hasAlert(recordAssertions)
|
|
184
|
+
return self:hasRecord(recordAssertions, Level.Alert)
|
|
185
|
+
end
|
|
186
|
+
function TestHandler:hasAlertThatContains(message)
|
|
187
|
+
return self:hasRecordThatContains(message, Level.Alert)
|
|
188
|
+
end
|
|
189
|
+
function TestHandler:hasAlertThatMatches(regex)
|
|
190
|
+
return self:hasRecordThatMatches(regex, Level.Alert)
|
|
191
|
+
end
|
|
192
|
+
function TestHandler:hasAlertThatPasses(predicate)
|
|
193
|
+
return self:hasRecordThatPasses(predicate, Level.Alert)
|
|
194
|
+
end
|
|
195
|
+
function TestHandler:hasCriticalRecords()
|
|
196
|
+
return self:hasRecords(Level.Critical)
|
|
197
|
+
end
|
|
198
|
+
function TestHandler:hasCritical(recordAssertions)
|
|
199
|
+
return self:hasRecord(recordAssertions, Level.Critical)
|
|
200
|
+
end
|
|
201
|
+
function TestHandler:hasCriticalThatContains(message)
|
|
202
|
+
return self:hasRecordThatContains(message, Level.Critical)
|
|
203
|
+
end
|
|
204
|
+
function TestHandler:hasCriticalThatMatches(regex)
|
|
205
|
+
return self:hasRecordThatMatches(regex, Level.Critical)
|
|
206
|
+
end
|
|
207
|
+
function TestHandler:hasCriticalThatPasses(predicate)
|
|
208
|
+
return self:hasRecordThatPasses(predicate, Level.Critical)
|
|
209
|
+
end
|
|
210
|
+
function TestHandler:hasErrorRecords()
|
|
211
|
+
return self:hasRecords(Level.Error)
|
|
212
|
+
end
|
|
213
|
+
function TestHandler:hasError(recordAssertions)
|
|
214
|
+
return self:hasRecord(recordAssertions, Level.Error)
|
|
215
|
+
end
|
|
216
|
+
function TestHandler:hasErrorThatContains(message)
|
|
217
|
+
return self:hasRecordThatContains(message, Level.Error)
|
|
218
|
+
end
|
|
219
|
+
function TestHandler:hasErrorThatMatches(regex)
|
|
220
|
+
return self:hasRecordThatMatches(regex, Level.Error)
|
|
221
|
+
end
|
|
222
|
+
function TestHandler:hasErrorThatPasses(predicate)
|
|
223
|
+
return self:hasRecordThatPasses(predicate, Level.Error)
|
|
224
|
+
end
|
|
225
|
+
function TestHandler:hasWarningRecords()
|
|
226
|
+
return self:hasRecords(Level.Warning)
|
|
227
|
+
end
|
|
228
|
+
function TestHandler:hasWarning(recordAssertions)
|
|
229
|
+
return self:hasRecord(recordAssertions, Level.Warning)
|
|
230
|
+
end
|
|
231
|
+
function TestHandler:hasWarningThatContains(message)
|
|
232
|
+
return self:hasRecordThatContains(message, Level.Warning)
|
|
233
|
+
end
|
|
234
|
+
function TestHandler:hasWarningThatMatches(regex)
|
|
235
|
+
return self:hasRecordThatMatches(regex, Level.Warning)
|
|
236
|
+
end
|
|
237
|
+
function TestHandler:hasWarningThatPasses(predicate)
|
|
238
|
+
return self:hasRecordThatPasses(predicate, Level.Warning)
|
|
239
|
+
end
|
|
240
|
+
function TestHandler:hasNoticeRecords()
|
|
241
|
+
return self:hasRecords(Level.Notice)
|
|
242
|
+
end
|
|
243
|
+
function TestHandler:hasNotice(recordAssertions)
|
|
244
|
+
return self:hasRecord(recordAssertions, Level.Notice)
|
|
245
|
+
end
|
|
246
|
+
function TestHandler:hasNoticeThatContains(message)
|
|
247
|
+
return self:hasRecordThatContains(message, Level.Notice)
|
|
248
|
+
end
|
|
249
|
+
function TestHandler:hasNoticeThatMatches(regex)
|
|
250
|
+
return self:hasRecordThatMatches(regex, Level.Notice)
|
|
251
|
+
end
|
|
252
|
+
function TestHandler:hasNoticeThatPasses(predicate)
|
|
253
|
+
return self:hasRecordThatPasses(predicate, Level.Notice)
|
|
254
|
+
end
|
|
255
|
+
function TestHandler:hasInfoRecords()
|
|
256
|
+
return self:hasRecords(Level.Info)
|
|
257
|
+
end
|
|
258
|
+
function TestHandler:hasInfo(recordAssertions)
|
|
259
|
+
return self:hasRecord(recordAssertions, Level.Info)
|
|
260
|
+
end
|
|
261
|
+
function TestHandler:hasInfoThatContains(message)
|
|
262
|
+
return self:hasRecordThatContains(message, Level.Info)
|
|
263
|
+
end
|
|
264
|
+
function TestHandler:hasInfoThatMatches(regex)
|
|
265
|
+
return self:hasRecordThatMatches(regex, Level.Info)
|
|
266
|
+
end
|
|
267
|
+
function TestHandler:hasInfoThatPasses(predicate)
|
|
268
|
+
return self:hasRecordThatPasses(predicate, Level.Info)
|
|
269
|
+
end
|
|
270
|
+
function TestHandler:hasDebugRecords()
|
|
271
|
+
return self:hasRecords(Level.Debug)
|
|
272
|
+
end
|
|
273
|
+
function TestHandler:hasDebug(recordAssertions)
|
|
274
|
+
return self:hasRecord(recordAssertions, Level.Debug)
|
|
275
|
+
end
|
|
276
|
+
function TestHandler:hasDebugThatContains(message)
|
|
277
|
+
return self:hasRecordThatContains(message, Level.Debug)
|
|
278
|
+
end
|
|
279
|
+
function TestHandler:hasDebugThatMatches(regex)
|
|
280
|
+
return self:hasRecordThatMatches(regex, Level.Debug)
|
|
281
|
+
end
|
|
282
|
+
function TestHandler:hasDebugThatPasses(predicate)
|
|
283
|
+
return self:hasRecordThatPasses(predicate, Level.Debug)
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
return {
|
|
287
|
+
TestHandler = TestHandler,
|
|
288
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PHP: `Monolog\Level`, a backed enum.
|
|
3
|
+
*
|
|
4
|
+
* TypeScript enums carry no statics and roblox-ts does not merge namespaces, so
|
|
5
|
+
* `Level::fromName()` and friends live on `Levels` beside the enum.
|
|
6
|
+
*/
|
|
7
|
+
export declare enum Level {
|
|
8
|
+
Debug = 100,
|
|
9
|
+
Info = 200,
|
|
10
|
+
Notice = 250,
|
|
11
|
+
Warning = 300,
|
|
12
|
+
Error = 400,
|
|
13
|
+
Critical = 500,
|
|
14
|
+
Alert = 550,
|
|
15
|
+
Emergency = 600
|
|
16
|
+
}
|
|
17
|
+
export declare class Levels {
|
|
18
|
+
/** PHP: `Level::VALUES`. */
|
|
19
|
+
static readonly VALUES: Array<Level>;
|
|
20
|
+
/** PHP: `Level::NAMES`. */
|
|
21
|
+
static readonly NAMES: Array<string>;
|
|
22
|
+
/** PHP: `Level::fromName()`. */
|
|
23
|
+
static fromName(name: string): Level | undefined;
|
|
24
|
+
/** PHP: `Level::fromValue()`. */
|
|
25
|
+
static fromValue(value: number): Level | undefined;
|
|
26
|
+
/** PHP: `Level->getName()`. */
|
|
27
|
+
static getName(level: Level): string;
|
|
28
|
+
/** PHP: `Level->toPsrLogLevel()`. */
|
|
29
|
+
static toPsrLogLevel(level: Level): string;
|
|
30
|
+
/** PHP: `Level->toRFC5424Level()`. */
|
|
31
|
+
static toRFC5424Level(level: Level): number;
|
|
32
|
+
/** PHP: `Level->includes()` -- true when the given level is at least this one. */
|
|
33
|
+
static includes(level: Level, other: Level): boolean;
|
|
34
|
+
/** PHP: `Level->isHigherThan()`. */
|
|
35
|
+
static isHigherThan(level: Level, other: Level): boolean;
|
|
36
|
+
/** PHP: `Level->isLowerThan()`. */
|
|
37
|
+
static isLowerThan(level: Level, other: Level): boolean;
|
|
38
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
--[[
|
|
3
|
+
*
|
|
4
|
+
* PHP: `Monolog\Level`, a backed enum.
|
|
5
|
+
*
|
|
6
|
+
* TypeScript enums carry no statics and roblox-ts does not merge namespaces, so
|
|
7
|
+
* `Level::fromName()` and friends live on `Levels` beside the enum.
|
|
8
|
+
|
|
9
|
+
]]
|
|
10
|
+
local Level
|
|
11
|
+
do
|
|
12
|
+
local _inverse = {}
|
|
13
|
+
Level = setmetatable({}, {
|
|
14
|
+
__index = _inverse,
|
|
15
|
+
})
|
|
16
|
+
Level.Debug = 100
|
|
17
|
+
_inverse[100] = "Debug"
|
|
18
|
+
Level.Info = 200
|
|
19
|
+
_inverse[200] = "Info"
|
|
20
|
+
Level.Notice = 250
|
|
21
|
+
_inverse[250] = "Notice"
|
|
22
|
+
Level.Warning = 300
|
|
23
|
+
_inverse[300] = "Warning"
|
|
24
|
+
Level.Error = 400
|
|
25
|
+
_inverse[400] = "Error"
|
|
26
|
+
Level.Critical = 500
|
|
27
|
+
_inverse[500] = "Critical"
|
|
28
|
+
Level.Alert = 550
|
|
29
|
+
_inverse[550] = "Alert"
|
|
30
|
+
Level.Emergency = 600
|
|
31
|
+
_inverse[600] = "Emergency"
|
|
32
|
+
end
|
|
33
|
+
local BY_NAME = {
|
|
34
|
+
debug = Level.Debug,
|
|
35
|
+
info = Level.Info,
|
|
36
|
+
notice = Level.Notice,
|
|
37
|
+
warning = Level.Warning,
|
|
38
|
+
error = Level.Error,
|
|
39
|
+
critical = Level.Critical,
|
|
40
|
+
alert = Level.Alert,
|
|
41
|
+
emergency = Level.Emergency,
|
|
42
|
+
}
|
|
43
|
+
local BY_VALUE = {
|
|
44
|
+
[Level.Debug] = "DEBUG",
|
|
45
|
+
[Level.Info] = "INFO",
|
|
46
|
+
[Level.Notice] = "NOTICE",
|
|
47
|
+
[Level.Warning] = "WARNING",
|
|
48
|
+
[Level.Error] = "ERROR",
|
|
49
|
+
[Level.Critical] = "CRITICAL",
|
|
50
|
+
[Level.Alert] = "ALERT",
|
|
51
|
+
[Level.Emergency] = "EMERGENCY",
|
|
52
|
+
}
|
|
53
|
+
local BY_RFC5424 = {
|
|
54
|
+
[Level.Debug] = 7,
|
|
55
|
+
[Level.Info] = 6,
|
|
56
|
+
[Level.Notice] = 5,
|
|
57
|
+
[Level.Warning] = 4,
|
|
58
|
+
[Level.Error] = 3,
|
|
59
|
+
[Level.Critical] = 2,
|
|
60
|
+
[Level.Alert] = 1,
|
|
61
|
+
[Level.Emergency] = 0,
|
|
62
|
+
}
|
|
63
|
+
local Levels
|
|
64
|
+
do
|
|
65
|
+
Levels = setmetatable({}, {
|
|
66
|
+
__tostring = function()
|
|
67
|
+
return "Levels"
|
|
68
|
+
end,
|
|
69
|
+
})
|
|
70
|
+
Levels.__index = Levels
|
|
71
|
+
function Levels.new(...)
|
|
72
|
+
local self = setmetatable({}, Levels)
|
|
73
|
+
return self:constructor(...) or self
|
|
74
|
+
end
|
|
75
|
+
function Levels:constructor()
|
|
76
|
+
end
|
|
77
|
+
function Levels:fromName(name)
|
|
78
|
+
local _arg0 = string.lower(name)
|
|
79
|
+
return BY_NAME[_arg0]
|
|
80
|
+
end
|
|
81
|
+
function Levels:fromValue(value)
|
|
82
|
+
local _value = value
|
|
83
|
+
return if BY_VALUE[_value] ~= nil then value else nil
|
|
84
|
+
end
|
|
85
|
+
function Levels:getName(level)
|
|
86
|
+
local _level = level
|
|
87
|
+
local _condition = BY_VALUE[_level]
|
|
88
|
+
if _condition == nil then
|
|
89
|
+
_condition = "DEBUG"
|
|
90
|
+
end
|
|
91
|
+
return _condition
|
|
92
|
+
end
|
|
93
|
+
function Levels:toPsrLogLevel(level)
|
|
94
|
+
return string.lower(Levels:getName(level))
|
|
95
|
+
end
|
|
96
|
+
function Levels:toRFC5424Level(level)
|
|
97
|
+
local _level = level
|
|
98
|
+
local _condition = BY_RFC5424[_level]
|
|
99
|
+
if _condition == nil then
|
|
100
|
+
_condition = 7
|
|
101
|
+
end
|
|
102
|
+
return _condition
|
|
103
|
+
end
|
|
104
|
+
function Levels:includes(level, other)
|
|
105
|
+
return level <= other
|
|
106
|
+
end
|
|
107
|
+
function Levels:isHigherThan(level, other)
|
|
108
|
+
return level > other
|
|
109
|
+
end
|
|
110
|
+
function Levels:isLowerThan(level, other)
|
|
111
|
+
return level < other
|
|
112
|
+
end
|
|
113
|
+
Levels.VALUES = { Level.Debug, Level.Info, Level.Notice, Level.Warning, Level.Error, Level.Critical, Level.Alert, Level.Emergency }
|
|
114
|
+
Levels.NAMES = { "DEBUG", "INFO", "NOTICE", "WARNING", "ERROR", "CRITICAL", "ALERT", "EMERGENCY" }
|
|
115
|
+
end
|
|
116
|
+
return {
|
|
117
|
+
Level = Level,
|
|
118
|
+
Levels = Levels,
|
|
119
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Level } from "./Level";
|
|
2
|
+
/** PHP: `array<mixed>` for context and extra. */
|
|
3
|
+
export type RecordBag = Record<string, unknown>;
|
|
4
|
+
/**
|
|
5
|
+
* PHP: `Monolog\LogRecord`.
|
|
6
|
+
*
|
|
7
|
+
* `datetime` is a Unix timestamp rather than a `DateTimeImmutable`; there is no
|
|
8
|
+
* date/time object on this platform. `ArrayAccess` is not ported.
|
|
9
|
+
*/
|
|
10
|
+
export declare class LogRecord {
|
|
11
|
+
readonly datetime: number;
|
|
12
|
+
readonly channel: string;
|
|
13
|
+
readonly level: Level;
|
|
14
|
+
readonly message: string;
|
|
15
|
+
readonly context: RecordBag;
|
|
16
|
+
extra: RecordBag;
|
|
17
|
+
formatted?: string | undefined;
|
|
18
|
+
constructor(datetime: number, channel: string, level: Level, message: string, context?: RecordBag, extra?: RecordBag, formatted?: string | undefined);
|
|
19
|
+
/** PHP: `LogRecord::with()`. Returns a copy with the given fields replaced. */
|
|
20
|
+
with(changes: {
|
|
21
|
+
datetime?: number;
|
|
22
|
+
channel?: string;
|
|
23
|
+
level?: Level;
|
|
24
|
+
message?: string;
|
|
25
|
+
context?: RecordBag;
|
|
26
|
+
extra?: RecordBag;
|
|
27
|
+
}): LogRecord;
|
|
28
|
+
/** PHP: `LogRecord::toArray()`. */
|
|
29
|
+
toArray(): RecordBag;
|
|
30
|
+
/**
|
|
31
|
+
* A shallow copy, as PHP's `clone` before handing a record to a handler.
|
|
32
|
+
*
|
|
33
|
+
* `extra` is copied into a new table rather than shared by reference:
|
|
34
|
+
* a PHP array is a value type, so mutating one handler's `$record->extra`
|
|
35
|
+
* (a per-handler processor commonly does exactly that) never touches a
|
|
36
|
+
* sibling handler's `clone($record)`. A Luau table has no such copy-on-
|
|
37
|
+
* write behavior -- sharing the same `extra` table across every handler's
|
|
38
|
+
* clone would let one handler's processor mutation leak into another's.
|
|
39
|
+
* `context` is `readonly` and never mutated in place, so it doesn't need
|
|
40
|
+
* the same treatment.
|
|
41
|
+
*/
|
|
42
|
+
clone(): LogRecord;
|
|
43
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local Levels = TS.import(script, script.Parent, "Level").Levels
|
|
4
|
+
--* PHP: `array<mixed>` for context and extra.
|
|
5
|
+
--[[
|
|
6
|
+
*
|
|
7
|
+
* PHP: `Monolog\LogRecord`.
|
|
8
|
+
*
|
|
9
|
+
* `datetime` is a Unix timestamp rather than a `DateTimeImmutable`; there is no
|
|
10
|
+
* date/time object on this platform. `ArrayAccess` is not ported.
|
|
11
|
+
|
|
12
|
+
]]
|
|
13
|
+
local LogRecord
|
|
14
|
+
do
|
|
15
|
+
LogRecord = setmetatable({}, {
|
|
16
|
+
__tostring = function()
|
|
17
|
+
return "LogRecord"
|
|
18
|
+
end,
|
|
19
|
+
})
|
|
20
|
+
LogRecord.__index = LogRecord
|
|
21
|
+
function LogRecord.new(...)
|
|
22
|
+
local self = setmetatable({}, LogRecord)
|
|
23
|
+
return self:constructor(...) or self
|
|
24
|
+
end
|
|
25
|
+
function LogRecord:constructor(datetime, channel, level, message, context, extra, formatted)
|
|
26
|
+
if context == nil then
|
|
27
|
+
context = {}
|
|
28
|
+
end
|
|
29
|
+
if extra == nil then
|
|
30
|
+
extra = {}
|
|
31
|
+
end
|
|
32
|
+
self.datetime = datetime
|
|
33
|
+
self.channel = channel
|
|
34
|
+
self.level = level
|
|
35
|
+
self.message = message
|
|
36
|
+
self.context = context
|
|
37
|
+
self.extra = extra
|
|
38
|
+
self.formatted = formatted
|
|
39
|
+
end
|
|
40
|
+
function LogRecord:with(changes)
|
|
41
|
+
local _condition = changes.datetime
|
|
42
|
+
if _condition == nil then
|
|
43
|
+
_condition = self.datetime
|
|
44
|
+
end
|
|
45
|
+
local _condition_1 = changes.channel
|
|
46
|
+
if _condition_1 == nil then
|
|
47
|
+
_condition_1 = self.channel
|
|
48
|
+
end
|
|
49
|
+
local _exp = changes.level or self.level
|
|
50
|
+
local _condition_2 = changes.message
|
|
51
|
+
if _condition_2 == nil then
|
|
52
|
+
_condition_2 = self.message
|
|
53
|
+
end
|
|
54
|
+
return LogRecord.new(_condition, _condition_1, _exp, _condition_2, changes.context or self.context, changes.extra or self.extra, self.formatted)
|
|
55
|
+
end
|
|
56
|
+
function LogRecord:toArray()
|
|
57
|
+
return {
|
|
58
|
+
message = self.message,
|
|
59
|
+
context = self.context,
|
|
60
|
+
level = self.level,
|
|
61
|
+
level_name = Levels:getName(self.level),
|
|
62
|
+
channel = self.channel,
|
|
63
|
+
datetime = self.datetime,
|
|
64
|
+
extra = self.extra,
|
|
65
|
+
}
|
|
66
|
+
end
|
|
67
|
+
function LogRecord:clone()
|
|
68
|
+
local extra = {}
|
|
69
|
+
for key, value in pairs(self.extra) do
|
|
70
|
+
extra[key] = value
|
|
71
|
+
end
|
|
72
|
+
return LogRecord.new(self.datetime, self.channel, self.level, self.message, self.context, extra, self.formatted)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
return {
|
|
76
|
+
LogRecord = LogRecord,
|
|
77
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { Level } from "./Level";
|
|
2
|
+
import { LogRecord } from "./LogRecord";
|
|
3
|
+
import type { HandlerInterface } from "./Handler/HandlerInterface";
|
|
4
|
+
import type { LogContext, LogLevel, LoggerInterface as LoggerContract } from "./LoggerInterface";
|
|
5
|
+
import type { Processor } from "./Processor/ProcessorInterface";
|
|
6
|
+
import type { RecordBag } from "./LogRecord";
|
|
7
|
+
import type { ResettableInterface } from "./ResettableInterface";
|
|
8
|
+
/** PHP: `Closure` passed to `Logger::setExceptionHandler()`. */
|
|
9
|
+
export type LoggerExceptionHandler = (error: unknown, record: LogRecord) => void;
|
|
10
|
+
/**
|
|
11
|
+
* PHP: `Monolog\Logger`.
|
|
12
|
+
*
|
|
13
|
+
* Holds the handler stack and the processor stack, builds a `LogRecord` and
|
|
14
|
+
* walks the handlers until one stops the bubbling chain.
|
|
15
|
+
*
|
|
16
|
+
* Not ported: timezones and microsecond timestamps (`os.time` is what a place
|
|
17
|
+
* has) and the serialization hooks (`__serialize`/`__unserialize`, no PHP
|
|
18
|
+
* magic serialization here). The infinite-logging-loop guard is kept, but
|
|
19
|
+
* keyed by a single instance counter rather than a `Fiber`-keyed `WeakMap` --
|
|
20
|
+
* there is no fiber concept on this platform.
|
|
21
|
+
*/
|
|
22
|
+
export declare class Logger implements LoggerContract, ResettableInterface {
|
|
23
|
+
protected name: string;
|
|
24
|
+
/** The handler stack. */
|
|
25
|
+
protected handlers: HandlerInterface[];
|
|
26
|
+
/** The processor stack. */
|
|
27
|
+
protected processors: Processor[];
|
|
28
|
+
/** PHP: `Logger::$exceptionHandler`. */
|
|
29
|
+
protected exceptionHandler?: LoggerExceptionHandler;
|
|
30
|
+
/** PHP: `Logger::$logDepth`. Not fiber-keyed -- see the class comment. */
|
|
31
|
+
private logDepth;
|
|
32
|
+
constructor(name: string, handlers?: Array<HandlerInterface>, processors?: Array<Processor>);
|
|
33
|
+
/** Get the logging channel name. */
|
|
34
|
+
getName(): string;
|
|
35
|
+
/** Return a new cloned instance with the name changed. */
|
|
36
|
+
withName(name: string): Logger;
|
|
37
|
+
/** Pushes a handler on to the stack. */
|
|
38
|
+
pushHandler(handler: HandlerInterface): this;
|
|
39
|
+
/** Pops a handler from the stack. */
|
|
40
|
+
popHandler(): HandlerInterface | undefined;
|
|
41
|
+
/** Set handlers, replacing all existing ones. */
|
|
42
|
+
setHandlers(handlers: Array<HandlerInterface>): this;
|
|
43
|
+
/** Get the handler stack. */
|
|
44
|
+
getHandlers(): Array<HandlerInterface>;
|
|
45
|
+
/** Adds a processor on to the stack. */
|
|
46
|
+
pushProcessor(processor: Processor): this;
|
|
47
|
+
/** Removes the processor on top of the stack and returns it. */
|
|
48
|
+
popProcessor(): Processor | undefined;
|
|
49
|
+
/** Get the processor stack. */
|
|
50
|
+
getProcessors(): Array<Processor>;
|
|
51
|
+
/** Adds a log record. */
|
|
52
|
+
addRecord(level: Level | number, message: string, context?: RecordBag): boolean;
|
|
53
|
+
/** The loop-depth-checked body of `addRecord`, split out so the counter above always unwinds. */
|
|
54
|
+
private addRecordAtDepth;
|
|
55
|
+
/**
|
|
56
|
+
* PHP: `Logger::toMonologLevel()`. Accepts a Level or a PSR level name.
|
|
57
|
+
*
|
|
58
|
+
* PHP throws `Psr\Log\InvalidArgumentException` for an unrecognized name;
|
|
59
|
+
* there is no port of that exception type, so this throws a plain error
|
|
60
|
+
* with the same message shape instead -- an unrecognized string is a
|
|
61
|
+
* caller bug (a typo'd level from outside TS's own type checking, e.g.
|
|
62
|
+
* deserialized from a string), not something to silently downgrade to
|
|
63
|
+
* `Debug`.
|
|
64
|
+
*/
|
|
65
|
+
static toMonologLevel(level: Level | LogLevel): Level;
|
|
66
|
+
/** PHP: `Logger::RFC_5424_LEVELS` remap, applied in `addRecord()`/`log()` before `toMonologLevel()`. */
|
|
67
|
+
private static remapRFC5424;
|
|
68
|
+
/** Checks whether the Logger has a handler that listens on the given level. */
|
|
69
|
+
isHandling(level: Level | LogLevel): boolean;
|
|
70
|
+
/** Set a custom exception handler called if adding a new record fails. */
|
|
71
|
+
setExceptionHandler(callback?: LoggerExceptionHandler): this;
|
|
72
|
+
/** Get the custom exception handler, if any. */
|
|
73
|
+
getExceptionHandler(): LoggerExceptionHandler | undefined;
|
|
74
|
+
/**
|
|
75
|
+
* Delegates exception management to the custom exception handler, or
|
|
76
|
+
* re-raises if no custom handler is set.
|
|
77
|
+
*/
|
|
78
|
+
protected handleException(error_: unknown, record: LogRecord): void;
|
|
79
|
+
/** Ends a log cycle and frees all resources used by handlers. */
|
|
80
|
+
close(): void;
|
|
81
|
+
/** Ends a log cycle and resets all handlers and processors that support it. */
|
|
82
|
+
reset(): void;
|
|
83
|
+
emergency(message: unknown, context?: LogContext): void;
|
|
84
|
+
alert(message: unknown, context?: LogContext): void;
|
|
85
|
+
critical(message: unknown, context?: LogContext): void;
|
|
86
|
+
error(message: unknown, context?: LogContext): void;
|
|
87
|
+
warning(message: unknown, context?: LogContext): void;
|
|
88
|
+
notice(message: unknown, context?: LogContext): void;
|
|
89
|
+
info(message: unknown, context?: LogContext): void;
|
|
90
|
+
debug(message: unknown, context?: LogContext): void;
|
|
91
|
+
/** Logs with an arbitrary level, named as PSR does. */
|
|
92
|
+
log(level: Level | LogLevel | number, message: unknown, context?: LogContext): void;
|
|
93
|
+
}
|