@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.
Files changed (70) hide show
  1. package/out/Monolog/Attribute/AsMonologProcessor.d.ts +30 -0
  2. package/out/Monolog/Attribute/AsMonologProcessor.luau +59 -0
  3. package/out/Monolog/Attribute/WithMonologChannel.d.ts +18 -0
  4. package/out/Monolog/Attribute/WithMonologChannel.luau +33 -0
  5. package/out/Monolog/Formatter/FormatterInterface.d.ts +8 -0
  6. package/out/Monolog/Formatter/FormatterInterface.luau +3 -0
  7. package/out/Monolog/Formatter/HtmlFormatter.d.ts +23 -0
  8. package/out/Monolog/Formatter/HtmlFormatter.luau +128 -0
  9. package/out/Monolog/Formatter/JsonFormatter.d.ts +34 -0
  10. package/out/Monolog/Formatter/JsonFormatter.luau +114 -0
  11. package/out/Monolog/Formatter/LineFormatter.d.ts +52 -0
  12. package/out/Monolog/Formatter/LineFormatter.luau +228 -0
  13. package/out/Monolog/Formatter/NormalizerFormatter.d.ts +87 -0
  14. package/out/Monolog/Formatter/NormalizerFormatter.luau +214 -0
  15. package/out/Monolog/Formatter/ScalarFormatter.d.ts +19 -0
  16. package/out/Monolog/Formatter/ScalarFormatter.luau +53 -0
  17. package/out/Monolog/Handler/AbstractHandler.d.ts +22 -0
  18. package/out/Monolog/Handler/AbstractHandler.luau +50 -0
  19. package/out/Monolog/Handler/AbstractProcessingHandler.d.ts +30 -0
  20. package/out/Monolog/Handler/AbstractProcessingHandler.luau +79 -0
  21. package/out/Monolog/Handler/Handler.d.ts +15 -0
  22. package/out/Monolog/Handler/Handler.luau +25 -0
  23. package/out/Monolog/Handler/HandlerInterface.d.ts +12 -0
  24. package/out/Monolog/Handler/HandlerInterface.luau +3 -0
  25. package/out/Monolog/Handler/NullHandler.d.ts +10 -0
  26. package/out/Monolog/Handler/NullHandler.luau +36 -0
  27. package/out/Monolog/Handler/RobloxConsoleHandler.d.ts +55 -0
  28. package/out/Monolog/Handler/RobloxConsoleHandler.luau +141 -0
  29. package/out/Monolog/Handler/TestHandler.d.ts +90 -0
  30. package/out/Monolog/Handler/TestHandler.luau +288 -0
  31. package/out/Monolog/Level.d.ts +38 -0
  32. package/out/Monolog/Level.luau +119 -0
  33. package/out/Monolog/LogRecord.d.ts +43 -0
  34. package/out/Monolog/LogRecord.luau +77 -0
  35. package/out/Monolog/Logger.d.ts +93 -0
  36. package/out/Monolog/Logger.luau +248 -0
  37. package/out/Monolog/LoggerInterface.d.ts +33 -0
  38. package/out/Monolog/LoggerInterface.luau +15 -0
  39. package/out/Monolog/Processor/ClosureContextProcessor.d.ts +13 -0
  40. package/out/Monolog/Processor/ClosureContextProcessor.luau +76 -0
  41. package/out/Monolog/Processor/IntrospectionProcessor.d.ts +33 -0
  42. package/out/Monolog/Processor/IntrospectionProcessor.luau +69 -0
  43. package/out/Monolog/Processor/MemoryPeakUsageProcessor.d.ts +17 -0
  44. package/out/Monolog/Processor/MemoryPeakUsageProcessor.luau +49 -0
  45. package/out/Monolog/Processor/MemoryProcessor.d.ts +20 -0
  46. package/out/Monolog/Processor/MemoryProcessor.luau +41 -0
  47. package/out/Monolog/Processor/MemoryUsageProcessor.d.ts +12 -0
  48. package/out/Monolog/Processor/MemoryUsageProcessor.luau +38 -0
  49. package/out/Monolog/Processor/ProcessIdProcessor.d.ts +13 -0
  50. package/out/Monolog/Processor/ProcessIdProcessor.luau +33 -0
  51. package/out/Monolog/Processor/ProcessorInterface.d.ts +13 -0
  52. package/out/Monolog/Processor/ProcessorInterface.luau +20 -0
  53. package/out/Monolog/Processor/PsrLogMessageProcessor.d.ts +12 -0
  54. package/out/Monolog/Processor/PsrLogMessageProcessor.luau +62 -0
  55. package/out/Monolog/Processor/TagProcessor.d.ts +12 -0
  56. package/out/Monolog/Processor/TagProcessor.luau +46 -0
  57. package/out/Monolog/Processor/UidProcessor.d.ts +18 -0
  58. package/out/Monolog/Processor/UidProcessor.luau +53 -0
  59. package/out/Monolog/Registry.d.ts +21 -0
  60. package/out/Monolog/Registry.luau +86 -0
  61. package/out/Monolog/ResettableInterface.d.ts +11 -0
  62. package/out/Monolog/ResettableInterface.luau +21 -0
  63. package/out/Monolog/Test/MonologTestCase.d.ts +26 -0
  64. package/out/Monolog/Test/MonologTestCase.luau +73 -0
  65. package/out/Monolog/Test/TestCase.d.ts +4 -0
  66. package/out/Monolog/Test/TestCase.luau +25 -0
  67. package/out/Monolog/Utils.d.ts +21 -0
  68. package/out/Monolog/Utils.luau +181 -0
  69. package/out/index.d.ts +1 -0
  70. package/package.json +51 -0
@@ -0,0 +1,248 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local TS = _G[script]
3
+ local _Level = TS.import(script, script.Parent, "Level")
4
+ local Level = _Level.Level
5
+ local Levels = _Level.Levels
6
+ local LogRecord = TS.import(script, script.Parent, "LogRecord").LogRecord
7
+ local isResettable = TS.import(script, script.Parent, "ResettableInterface").isResettable
8
+ local runProcessor = TS.import(script, script.Parent, "Processor", "ProcessorInterface").runProcessor
9
+ --* PHP: `Closure` passed to `Logger::setExceptionHandler()`.
10
+ --* PHP: `Logger::RFC_5424_LEVELS`, reversed (RFC 5424 number -> Monolog `Level`).
11
+ local RFC_5424_LEVELS = {
12
+ [7] = Level.Debug,
13
+ [6] = Level.Info,
14
+ [5] = Level.Notice,
15
+ [4] = Level.Warning,
16
+ [3] = Level.Error,
17
+ [2] = Level.Critical,
18
+ [1] = Level.Alert,
19
+ [0] = Level.Emergency,
20
+ }
21
+ --[[
22
+ *
23
+ * PHP: `Monolog\Logger`.
24
+ *
25
+ * Holds the handler stack and the processor stack, builds a `LogRecord` and
26
+ * walks the handlers until one stops the bubbling chain.
27
+ *
28
+ * Not ported: timezones and microsecond timestamps (`os.time` is what a place
29
+ * has) and the serialization hooks (`__serialize`/`__unserialize`, no PHP
30
+ * magic serialization here). The infinite-logging-loop guard is kept, but
31
+ * keyed by a single instance counter rather than a `Fiber`-keyed `WeakMap` --
32
+ * there is no fiber concept on this platform.
33
+
34
+ ]]
35
+ local Logger
36
+ do
37
+ Logger = setmetatable({}, {
38
+ __tostring = function()
39
+ return "Logger"
40
+ end,
41
+ })
42
+ Logger.__index = Logger
43
+ function Logger.new(...)
44
+ local self = setmetatable({}, Logger)
45
+ return self:constructor(...) or self
46
+ end
47
+ function Logger:constructor(name, handlers, processors)
48
+ if handlers == nil then
49
+ handlers = {}
50
+ end
51
+ if processors == nil then
52
+ processors = {}
53
+ end
54
+ self.name = name
55
+ self.handlers = {}
56
+ self.processors = {}
57
+ self.logDepth = 0
58
+ self:setHandlers(handlers)
59
+ for _, processor in processors do
60
+ local _exp = self.processors
61
+ table.insert(_exp, processor)
62
+ end
63
+ end
64
+ function Logger:getName()
65
+ return self.name
66
+ end
67
+ function Logger:withName(name)
68
+ return Logger.new(name, self.handlers, self.processors)
69
+ end
70
+ function Logger:pushHandler(handler)
71
+ local _handlers = self.handlers
72
+ local _handler = handler
73
+ table.insert(_handlers, 1, _handler)
74
+ return self
75
+ end
76
+ function Logger:popHandler()
77
+ return table.remove(self.handlers, 1)
78
+ end
79
+ function Logger:setHandlers(handlers)
80
+ table.clear(self.handlers)
81
+ for index = #handlers - 1, 0, -1 do
82
+ self:pushHandler(handlers[index + 1])
83
+ end
84
+ return self
85
+ end
86
+ function Logger:getHandlers()
87
+ return self.handlers
88
+ end
89
+ function Logger:pushProcessor(processor)
90
+ local _processors = self.processors
91
+ local _processor = processor
92
+ table.insert(_processors, 1, _processor)
93
+ return self
94
+ end
95
+ function Logger:popProcessor()
96
+ return table.remove(self.processors, 1)
97
+ end
98
+ function Logger:getProcessors()
99
+ return self.processors
100
+ end
101
+ function Logger:addRecord(level, message, context)
102
+ if context == nil then
103
+ context = {}
104
+ end
105
+ self.logDepth += 1
106
+ local handled = self:addRecordAtDepth(Logger:remapRFC5424(level), message, context)
107
+ self.logDepth -= 1
108
+ return handled
109
+ end
110
+ function Logger:addRecordAtDepth(level, message, context)
111
+ if self.logDepth == 3 then
112
+ self:warning("A possible infinite logging loop was detected and aborted. It appears some of your handler code is triggering logging, see the previous log record for a hint as to what may be the cause.")
113
+ return false
114
+ elseif self.logDepth >= 5 then
115
+ -- log depth 4 is let through, so we can log the warning above
116
+ return false
117
+ end
118
+ local record = LogRecord.new(os.time(), self.name, Logger:toMonologLevel(level), message, context, {})
119
+ local recordInitialized = #self.processors == 0
120
+ local handled = false
121
+ for _, handler in self.handlers do
122
+ if not recordInitialized then
123
+ -- Skip initializing the record as long as no handler will take it.
124
+ if not handler:isHandling(record) then
125
+ continue
126
+ end
127
+ local processedOk, processedResult = pcall(function()
128
+ local processed = record
129
+ for _1, processor in self.processors do
130
+ processed = runProcessor(processor, processed)
131
+ end
132
+ return processed
133
+ end)
134
+ if not processedOk then
135
+ self:handleException(processedResult, record)
136
+ return true
137
+ end
138
+ record = processedResult
139
+ recordInitialized = true
140
+ end
141
+ handled = true
142
+ local handledOk, handledResult = pcall(function()
143
+ return handler:handle(record:clone())
144
+ end)
145
+ if not handledOk then
146
+ self:handleException(handledResult, record)
147
+ return true
148
+ end
149
+ if handledResult == true then
150
+ break
151
+ end
152
+ end
153
+ return handled
154
+ end
155
+ function Logger:toMonologLevel(level)
156
+ local _level = level
157
+ if not (type(_level) == "string") then
158
+ return level
159
+ end
160
+ local found = Levels:fromName(level)
161
+ if found == nil then
162
+ error(`Level "{level}" is not defined, use one of: {table.concat(Levels.NAMES, ", ")}`)
163
+ end
164
+ return found
165
+ end
166
+ function Logger:remapRFC5424(level)
167
+ local _level = level
168
+ local _condition = type(_level) == "number"
169
+ if _condition then
170
+ local _level_1 = level
171
+ _condition = RFC_5424_LEVELS[_level_1] ~= nil
172
+ end
173
+ if _condition then
174
+ local _level_1 = level
175
+ return RFC_5424_LEVELS[_level_1]
176
+ end
177
+ return level
178
+ end
179
+ function Logger:isHandling(level)
180
+ local record = LogRecord.new(os.time(), self.name, Logger:toMonologLevel(level), "")
181
+ for _, handler in self.handlers do
182
+ if handler:isHandling(record) then
183
+ return true
184
+ end
185
+ end
186
+ return false
187
+ end
188
+ function Logger:setExceptionHandler(callback)
189
+ self.exceptionHandler = callback
190
+ return self
191
+ end
192
+ function Logger:getExceptionHandler()
193
+ return self.exceptionHandler
194
+ end
195
+ function Logger:handleException(error_, record)
196
+ if self.exceptionHandler == nil then
197
+ error(error_)
198
+ end
199
+ self.exceptionHandler(error_, record)
200
+ end
201
+ function Logger:close()
202
+ for _, handler in self.handlers do
203
+ handler:close()
204
+ end
205
+ end
206
+ function Logger:reset()
207
+ for _, handler in self.handlers do
208
+ if isResettable(handler) then
209
+ handler:reset()
210
+ end
211
+ end
212
+ for _, processor in self.processors do
213
+ if isResettable(processor) then
214
+ processor:reset()
215
+ end
216
+ end
217
+ end
218
+ function Logger:emergency(message, context)
219
+ self:addRecord(Level.Emergency, tostring(message), context or {})
220
+ end
221
+ function Logger:alert(message, context)
222
+ self:addRecord(Level.Alert, tostring(message), context or {})
223
+ end
224
+ function Logger:critical(message, context)
225
+ self:addRecord(Level.Critical, tostring(message), context or {})
226
+ end
227
+ function Logger:error(message, context)
228
+ self:addRecord(Level.Error, tostring(message), context or {})
229
+ end
230
+ function Logger:warning(message, context)
231
+ self:addRecord(Level.Warning, tostring(message), context or {})
232
+ end
233
+ function Logger:notice(message, context)
234
+ self:addRecord(Level.Notice, tostring(message), context or {})
235
+ end
236
+ function Logger:info(message, context)
237
+ self:addRecord(Level.Info, tostring(message), context or {})
238
+ end
239
+ function Logger:debug(message, context)
240
+ self:addRecord(Level.Debug, tostring(message), context or {})
241
+ end
242
+ function Logger:log(level, message, context)
243
+ self:addRecord(Logger:toMonologLevel(Logger:remapRFC5424(level)), tostring(message), context or {})
244
+ end
245
+ end
246
+ return {
247
+ Logger = Logger,
248
+ }
@@ -0,0 +1,33 @@
1
+ /** PHP: the levels `Psr\Log\LogLevel` defines, in ascending severity. */
2
+ export type LogLevel = "debug" | "info" | "notice" | "warning" | "error" | "critical" | "alert" | "emergency";
3
+ /** PHP: `array $context`. */
4
+ export type LogContext = Record<string, unknown>;
5
+ /**
6
+ * PHP: `Psr\Log\LoggerInterface`.
7
+ *
8
+ * Real Monolog implements this from the separate `psr/log` package, not from
9
+ * `laravel/framework`. There is no Luau port of `psr/log` to depend on
10
+ * instead, so the shape lives here, where the class that actually implements
11
+ * it lives -- `Illuminate\Contracts\Log\Logger` re-exports it rather than
12
+ * declaring its own copy.
13
+ */
14
+ export interface LoggerInterface {
15
+ /** System is unusable. */
16
+ emergency(message: unknown, context?: LogContext): void;
17
+ /** Action must be taken immediately. */
18
+ alert(message: unknown, context?: LogContext): void;
19
+ /** Critical conditions. */
20
+ critical(message: unknown, context?: LogContext): void;
21
+ /** Runtime errors that do not require immediate action. */
22
+ error(message: unknown, context?: LogContext): void;
23
+ /** Exceptional occurrences that are not errors. */
24
+ warning(message: unknown, context?: LogContext): void;
25
+ /** Normal but significant events. */
26
+ notice(message: unknown, context?: LogContext): void;
27
+ /** Interesting events. */
28
+ info(message: unknown, context?: LogContext): void;
29
+ /** Detailed debug information. */
30
+ debug(message: unknown, context?: LogContext): void;
31
+ /** Logs with an arbitrary level. */
32
+ log(level: LogLevel, message: unknown, context?: LogContext): void;
33
+ }
@@ -0,0 +1,15 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ --* PHP: the levels `Psr\Log\LogLevel` defines, in ascending severity.
3
+ --* PHP: `array $context`.
4
+ --[[
5
+ *
6
+ * PHP: `Psr\Log\LoggerInterface`.
7
+ *
8
+ * Real Monolog implements this from the separate `psr/log` package, not from
9
+ * `laravel/framework`. There is no Luau port of `psr/log` to depend on
10
+ * instead, so the shape lives here, where the class that actually implements
11
+ * it lives -- `Illuminate\Contracts\Log\Logger` re-exports it rather than
12
+ * declaring its own copy.
13
+
14
+ ]]
15
+ return nil
@@ -0,0 +1,13 @@
1
+ import type { LogRecord } from "../LogRecord";
2
+ import type { ProcessorInterface } from "./ProcessorInterface";
3
+ /**
4
+ * PHP: `Monolog\Processor\ClosureContextProcessor`.
5
+ *
6
+ * Upstream keys this off `$context[0]`, PHP's implicit first-array-index; a
7
+ * `RecordBag` has no positional index, so this checks whether context has
8
+ * exactly one entry and that entry's value is a function, regardless of its
9
+ * key name.
10
+ */
11
+ export declare class ClosureContextProcessor implements ProcessorInterface {
12
+ process(record: LogRecord): LogRecord;
13
+ }
@@ -0,0 +1,76 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ --* True when `bag` has exactly one entry; returns that entry.
3
+ local function soleEntry(bag)
4
+ local firstKey, firstValue = next(bag)
5
+ if firstKey == nil then
6
+ return nil
7
+ end
8
+ local secondKey = next(bag, firstKey)
9
+ if secondKey ~= nil then
10
+ return nil
11
+ end
12
+ return {
13
+ key = firstKey,
14
+ value = firstValue,
15
+ }
16
+ end
17
+ --[[
18
+ *
19
+ * PHP: `Monolog\Processor\ClosureContextProcessor`.
20
+ *
21
+ * Upstream keys this off `$context[0]`, PHP's implicit first-array-index; a
22
+ * `RecordBag` has no positional index, so this checks whether context has
23
+ * exactly one entry and that entry's value is a function, regardless of its
24
+ * key name.
25
+
26
+ ]]
27
+ local ClosureContextProcessor
28
+ do
29
+ ClosureContextProcessor = setmetatable({}, {
30
+ __tostring = function()
31
+ return "ClosureContextProcessor"
32
+ end,
33
+ })
34
+ ClosureContextProcessor.__index = ClosureContextProcessor
35
+ function ClosureContextProcessor.new(...)
36
+ local self = setmetatable({}, ClosureContextProcessor)
37
+ return self:constructor(...) or self
38
+ end
39
+ function ClosureContextProcessor:constructor()
40
+ end
41
+ function ClosureContextProcessor:process(record)
42
+ local sole = soleEntry(record.context)
43
+ local _condition = sole == nil
44
+ if not _condition then
45
+ local _value = sole.value
46
+ _condition = not (type(_value) == "function")
47
+ end
48
+ if _condition then
49
+ return record
50
+ end
51
+ local ok, result = pcall(sole.value)
52
+ local context
53
+ if not ok then
54
+ context = {
55
+ error_on_context_generation = tostring(result),
56
+ exception = result,
57
+ }
58
+ elseif type(result) == "table" then
59
+ context = result
60
+ else
61
+ -- Upstream wraps a non-array result as `[$context]`, which lands back
62
+ -- at key `0` -- the same key it started under, since PHP's implicit
63
+ -- index was always `0`. Re-using the original key name here is this
64
+ -- port's equivalent, since there is no positional index to fall back to.
65
+ context = {
66
+ [sole.key] = result,
67
+ }
68
+ end
69
+ return record:with({
70
+ context = context,
71
+ })
72
+ end
73
+ end
74
+ return {
75
+ ClosureContextProcessor = ClosureContextProcessor,
76
+ }
@@ -0,0 +1,33 @@
1
+ import { Level } from "../Level";
2
+ import type { LogLevel } from "../LoggerInterface";
3
+ import type { LogRecord } from "../LogRecord";
4
+ import type { ProcessorInterface } from "./ProcessorInterface";
5
+ /**
6
+ * PHP: `Monolog\Processor\IntrospectionProcessor`.
7
+ *
8
+ * Upstream walks `debug_backtrace()`, skipping frames belonging to
9
+ * `skipClassesPartials` (default `["Monolog\\"]`) and PHP's
10
+ * `call_user_func`/`call_user_func_array` wrappers, to find the frame that
11
+ * actually logged the message. Luau's `debug.info` reports one stack level at
12
+ * a time with no per-frame "class" the way a PHP trace frame has, so there is
13
+ * nothing for a class-partial skip list to match against -- `skipClassesPartials`
14
+ * is dropped entirely rather than faked.
15
+ *
16
+ * `BASE_STACK_OFFSET` is this port's analog of upstream's two `array_shift()`
17
+ * calls (its own frame, then the generic invoker frame -- `runProcessor()`
18
+ * here, `call_user_func` there). Unlike upstream's flat PHP call stack,
19
+ * `Logger.addRecord()` on this platform adds its own internal frames before
20
+ * reaching a processor, so the reported file/line will typically land inside
21
+ * that dispatch machinery rather than the original log call site. Tune
22
+ * `skipStackFramesCount` to compensate if more precision is needed.
23
+ *
24
+ * Warning: this only works if the handler processes the logs directly -- see
25
+ * upstream's own caveat, which applies here unchanged.
26
+ */
27
+ export declare class IntrospectionProcessor implements ProcessorInterface {
28
+ protected skipStackFramesCount: number;
29
+ private static readonly BASE_STACK_OFFSET;
30
+ protected level: Level;
31
+ constructor(level?: Level | LogLevel, skipStackFramesCount?: number);
32
+ process(record: LogRecord): LogRecord;
33
+ }
@@ -0,0 +1,69 @@
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 Logger = TS.import(script, script.Parent.Parent, "Logger").Logger
7
+ --[[
8
+ *
9
+ * PHP: `Monolog\Processor\IntrospectionProcessor`.
10
+ *
11
+ * Upstream walks `debug_backtrace()`, skipping frames belonging to
12
+ * `skipClassesPartials` (default `["Monolog\\"]`) and PHP's
13
+ * `call_user_func`/`call_user_func_array` wrappers, to find the frame that
14
+ * actually logged the message. Luau's `debug.info` reports one stack level at
15
+ * a time with no per-frame "class" the way a PHP trace frame has, so there is
16
+ * nothing for a class-partial skip list to match against -- `skipClassesPartials`
17
+ * is dropped entirely rather than faked.
18
+ *
19
+ * `BASE_STACK_OFFSET` is this port's analog of upstream's two `array_shift()`
20
+ * calls (its own frame, then the generic invoker frame -- `runProcessor()`
21
+ * here, `call_user_func` there). Unlike upstream's flat PHP call stack,
22
+ * `Logger.addRecord()` on this platform adds its own internal frames before
23
+ * reaching a processor, so the reported file/line will typically land inside
24
+ * that dispatch machinery rather than the original log call site. Tune
25
+ * `skipStackFramesCount` to compensate if more precision is needed.
26
+ *
27
+ * Warning: this only works if the handler processes the logs directly -- see
28
+ * upstream's own caveat, which applies here unchanged.
29
+
30
+ ]]
31
+ local IntrospectionProcessor
32
+ do
33
+ IntrospectionProcessor = setmetatable({}, {
34
+ __tostring = function()
35
+ return "IntrospectionProcessor"
36
+ end,
37
+ })
38
+ IntrospectionProcessor.__index = IntrospectionProcessor
39
+ function IntrospectionProcessor.new(...)
40
+ local self = setmetatable({}, IntrospectionProcessor)
41
+ return self:constructor(...) or self
42
+ end
43
+ function IntrospectionProcessor:constructor(level, skipStackFramesCount)
44
+ if level == nil then
45
+ level = Level.Debug
46
+ end
47
+ if skipStackFramesCount == nil then
48
+ skipStackFramesCount = 0
49
+ end
50
+ self.skipStackFramesCount = skipStackFramesCount
51
+ self.level = Logger:toMonologLevel(level)
52
+ end
53
+ function IntrospectionProcessor:process(record)
54
+ if Levels:isLowerThan(record.level, self.level) then
55
+ return record
56
+ end
57
+ local source, line, name = debug.info(IntrospectionProcessor.BASE_STACK_OFFSET + self.skipStackFramesCount, "sln")
58
+ record.extra.file = source
59
+ record.extra.line = line
60
+ record.extra["function"] = name
61
+ -- `class`/`callType` are left unset -- Luau has no reflective notion of
62
+ -- "the class this call happened in" the way `$trace[$i]['class']` does.
63
+ return record
64
+ end
65
+ IntrospectionProcessor.BASE_STACK_OFFSET = 3
66
+ end
67
+ return {
68
+ IntrospectionProcessor = IntrospectionProcessor,
69
+ }
@@ -0,0 +1,17 @@
1
+ import { MemoryProcessor } from "./MemoryProcessor";
2
+ import type { LogRecord } from "../LogRecord";
3
+ /**
4
+ * PHP: `Monolog\Processor\MemoryPeakUsageProcessor`.
5
+ *
6
+ * There is no `memory_get_peak_usage()` equivalent -- Luau only reports
7
+ * *current* GC memory, not a running peak, so this tracks one itself: a
8
+ * private field updated to the highest reading seen so far on every call,
9
+ * seeded at construction. "Peak" here means the highest reading this
10
+ * processor instance has observed since it was created, not an OS-level
11
+ * peak -- a real, necessary behavioral divergence, not a cosmetic one.
12
+ */
13
+ export declare class MemoryPeakUsageProcessor extends MemoryProcessor {
14
+ private peakBytes;
15
+ constructor(realUsage?: boolean, useFormatting?: boolean);
16
+ process(record: LogRecord): LogRecord;
17
+ }
@@ -0,0 +1,49 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local TS = _G[script]
3
+ local MemoryProcessor = TS.import(script, script.Parent, "MemoryProcessor").MemoryProcessor
4
+ --[[
5
+ *
6
+ * PHP: `Monolog\Processor\MemoryPeakUsageProcessor`.
7
+ *
8
+ * There is no `memory_get_peak_usage()` equivalent -- Luau only reports
9
+ * *current* GC memory, not a running peak, so this tracks one itself: a
10
+ * private field updated to the highest reading seen so far on every call,
11
+ * seeded at construction. "Peak" here means the highest reading this
12
+ * processor instance has observed since it was created, not an OS-level
13
+ * peak -- a real, necessary behavioral divergence, not a cosmetic one.
14
+
15
+ ]]
16
+ local MemoryPeakUsageProcessor
17
+ do
18
+ local super = MemoryProcessor
19
+ MemoryPeakUsageProcessor = setmetatable({}, {
20
+ __tostring = function()
21
+ return "MemoryPeakUsageProcessor"
22
+ end,
23
+ __index = super,
24
+ })
25
+ MemoryPeakUsageProcessor.__index = MemoryPeakUsageProcessor
26
+ function MemoryPeakUsageProcessor.new(...)
27
+ local self = setmetatable({}, MemoryPeakUsageProcessor)
28
+ return self:constructor(...) or self
29
+ end
30
+ function MemoryPeakUsageProcessor:constructor(realUsage, useFormatting)
31
+ if realUsage == nil then
32
+ realUsage = true
33
+ end
34
+ if useFormatting == nil then
35
+ useFormatting = true
36
+ end
37
+ super.constructor(self, realUsage, useFormatting)
38
+ self.peakBytes = gcinfo() * 1024
39
+ end
40
+ function MemoryPeakUsageProcessor:process(record)
41
+ local currentBytes = gcinfo() * 1024
42
+ self.peakBytes = math.max(self.peakBytes, currentBytes)
43
+ record.extra.memory_peak_usage = self:formatBytes(self.peakBytes)
44
+ return record
45
+ end
46
+ end
47
+ return {
48
+ MemoryPeakUsageProcessor = MemoryPeakUsageProcessor,
49
+ }
@@ -0,0 +1,20 @@
1
+ import type { LogRecord } from "../LogRecord";
2
+ import type { ProcessorInterface } from "./ProcessorInterface";
3
+ /**
4
+ * PHP: `Monolog\Processor\MemoryProcessor`.
5
+ *
6
+ * `realUsage` has no real platform distinction here: `gcinfo()` (Roblox's
7
+ * replacement for the deprecated `collectgarbage("count")`) is the only
8
+ * memory reading source Luau exposes, and there is no PHP
9
+ * `emalloc()`-vs-OS-allocated split to choose between. The constructor
10
+ * parameter is kept for API-shape parity but does not change behavior in
11
+ * either subclass -- said once here rather than repeated in each.
12
+ */
13
+ export declare abstract class MemoryProcessor implements ProcessorInterface {
14
+ protected realUsage: boolean;
15
+ protected useFormatting: boolean;
16
+ constructor(realUsage?: boolean, useFormatting?: boolean);
17
+ abstract process(record: LogRecord): LogRecord;
18
+ /** Formats bytes into a human-readable string if `useFormatting` is true, otherwise returns `bytes` as-is. */
19
+ protected formatBytes(bytes: number): string | number;
20
+ }
@@ -0,0 +1,41 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ --[[
3
+ *
4
+ * PHP: `Monolog\Processor\MemoryProcessor`.
5
+ *
6
+ * `realUsage` has no real platform distinction here: `gcinfo()` (Roblox's
7
+ * replacement for the deprecated `collectgarbage("count")`) is the only
8
+ * memory reading source Luau exposes, and there is no PHP
9
+ * `emalloc()`-vs-OS-allocated split to choose between. The constructor
10
+ * parameter is kept for API-shape parity but does not change behavior in
11
+ * either subclass -- said once here rather than repeated in each.
12
+
13
+ ]]
14
+ local MemoryProcessor
15
+ do
16
+ MemoryProcessor = {}
17
+ function MemoryProcessor:constructor(realUsage, useFormatting)
18
+ if realUsage == nil then
19
+ realUsage = true
20
+ end
21
+ if useFormatting == nil then
22
+ useFormatting = true
23
+ end
24
+ self.realUsage = realUsage
25
+ self.useFormatting = useFormatting
26
+ end
27
+ function MemoryProcessor:formatBytes(bytes)
28
+ if not self.useFormatting then
29
+ return bytes
30
+ end
31
+ if bytes > 1024 * 1024 then
32
+ return `{math.round((bytes / 1024 / 1024) * 100) / 100} MB`
33
+ elseif bytes > 1024 then
34
+ return `{math.round((bytes / 1024) * 100) / 100} KB`
35
+ end
36
+ return `{bytes} B`
37
+ end
38
+ end
39
+ return {
40
+ MemoryProcessor = MemoryProcessor,
41
+ }
@@ -0,0 +1,12 @@
1
+ import { MemoryProcessor } from "./MemoryProcessor";
2
+ import type { LogRecord } from "../LogRecord";
3
+ /**
4
+ * PHP: `Monolog\Processor\MemoryUsageProcessor`.
5
+ *
6
+ * `gcinfo()` (Roblox's replacement for the deprecated `collectgarbage("count")`)
7
+ * reports kilobytes; multiplied by 1024 so `formatBytes()` sees the same unit
8
+ * PHP's `memory_get_usage()` returns.
9
+ */
10
+ export declare class MemoryUsageProcessor extends MemoryProcessor {
11
+ process(record: LogRecord): LogRecord;
12
+ }
@@ -0,0 +1,38 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local TS = _G[script]
3
+ local MemoryProcessor = TS.import(script, script.Parent, "MemoryProcessor").MemoryProcessor
4
+ --[[
5
+ *
6
+ * PHP: `Monolog\Processor\MemoryUsageProcessor`.
7
+ *
8
+ * `gcinfo()` (Roblox's replacement for the deprecated `collectgarbage("count")`)
9
+ * reports kilobytes; multiplied by 1024 so `formatBytes()` sees the same unit
10
+ * PHP's `memory_get_usage()` returns.
11
+
12
+ ]]
13
+ local MemoryUsageProcessor
14
+ do
15
+ local super = MemoryProcessor
16
+ MemoryUsageProcessor = setmetatable({}, {
17
+ __tostring = function()
18
+ return "MemoryUsageProcessor"
19
+ end,
20
+ __index = super,
21
+ })
22
+ MemoryUsageProcessor.__index = MemoryUsageProcessor
23
+ function MemoryUsageProcessor.new(...)
24
+ local self = setmetatable({}, MemoryUsageProcessor)
25
+ return self:constructor(...) or self
26
+ end
27
+ function MemoryUsageProcessor:constructor(...)
28
+ super.constructor(self, ...)
29
+ end
30
+ function MemoryUsageProcessor:process(record)
31
+ local usage = gcinfo() * 1024
32
+ record.extra.memory_usage = self:formatBytes(usage)
33
+ return record
34
+ end
35
+ end
36
+ return {
37
+ MemoryUsageProcessor = MemoryUsageProcessor,
38
+ }
@@ -0,0 +1,13 @@
1
+ import type { LogRecord } from "../LogRecord";
2
+ import type { ProcessorInterface } from "./ProcessorInterface";
3
+ /**
4
+ * PHP: `Monolog\Processor\ProcessIdProcessor`.
5
+ *
6
+ * There is no OS process id on Roblox. `game.JobId` is the closest identifier
7
+ * for "which running process is this" -- a string, not the int
8
+ * `getmypid()` returns, and empty outside a real server (e.g. Studio Play
9
+ * testing), where it falls back to `"studio"`.
10
+ */
11
+ export declare class ProcessIdProcessor implements ProcessorInterface {
12
+ process(record: LogRecord): LogRecord;
13
+ }