| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
MODE: INLINE |
|
2
|
|
|
|
|
|
|
#include "util.h" |
|
3
|
|
|
|
|
|
|
using namespace xs::xlog; |
|
4
|
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
namespace { |
|
6
|
|
|
|
|
|
|
static bool no_format_warnings; |
|
7
|
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
struct PerlObjectFormatter : IFormatter, Backref { |
|
9
|
|
|
|
|
|
|
string format (std::string& msg, const Info& i) const override { |
|
10
|
|
|
|
|
|
|
if (!is_perl_thread()) throw std::logic_error("can't call pure-perl formatting callback: log() called from perl-foreign thread"); |
|
11
|
|
|
|
|
|
|
Object o = xs::out(this); |
|
12
|
|
|
|
|
|
|
auto ret = o.call("format", xs::out(msg), xs::out(i.level), xs::out(i.module->name()), xs::out(i.file), xs::out(i.line), xs::out(i.func)); |
|
13
|
|
|
|
|
|
|
return xs::in(ret); |
|
14
|
|
|
|
|
|
|
} |
|
15
|
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
~PerlObjectFormatter () { Backref::dtor(); } |
|
17
|
|
|
|
|
|
|
}; |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
struct PerlObjectLogger : ILogger, Backref { |
|
20
|
|
|
|
|
|
|
void log_format (std::string& msg, const Info& i, const IFormatter& fmt) override { |
|
21
|
|
|
|
|
|
|
if (!is_perl_thread()) throw std::logic_error("can't call pure-perl logging callback: log() called from perl-foreign thread"); |
|
22
|
|
|
|
|
|
|
Object o = xs::out(this); |
|
23
|
|
|
|
|
|
|
auto sub = o.method("log_format"); |
|
24
|
|
|
|
|
|
|
if (!sub) return ILogger::log_format(msg, i, fmt); |
|
25
|
|
|
|
|
|
|
sub.call(o.ref(), xs::out(msg), xs::out(i.level), xs::out(i.module->name()), xs::out(i.file), xs::out(i.line), xs::out(i.func), xs::out(&fmt)); |
|
26
|
|
|
|
|
|
|
} |
|
27
|
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
void log (const string& msg, const Info& info) override { |
|
29
|
|
|
|
|
|
|
if (!is_perl_thread()) throw std::logic_error("can't call pure-perl logging callback: log() called from perl-foreign thread"); |
|
30
|
|
|
|
|
|
|
Object o = xs::out(this); |
|
31
|
|
|
|
|
|
|
o.call("log", xs::out(msg), xs::out(info.level)); |
|
32
|
|
|
|
|
|
|
} |
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
~PerlObjectLogger () { Backref::dtor(); } |
|
35
|
|
|
|
|
|
|
}; |
|
36
|
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
struct NoWarningsGuard { |
|
38
|
|
|
|
|
|
|
NoWarningsGuard (bool enabled) : _enabled(enabled), _cop_warnings(), _dowarn() { |
|
39
|
|
|
|
|
|
|
if (!_enabled) return; |
|
40
|
|
|
|
|
|
|
_cop_warnings = PL_curcop->cop_warnings; |
|
41
|
|
|
|
|
|
|
_dowarn = PL_dowarn; |
|
42
|
|
|
|
|
|
|
PL_curcop->cop_warnings = pWARN_STD; |
|
43
|
|
|
|
|
|
|
PL_dowarn &= ~G_WARN_ON; |
|
44
|
|
|
|
|
|
|
} |
|
45
|
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
~NoWarningsGuard () { |
|
47
|
|
|
|
|
|
|
if (!_enabled) return; |
|
48
|
|
|
|
|
|
|
PL_curcop->cop_warnings = _cop_warnings; |
|
49
|
|
|
|
|
|
|
PL_dowarn = _dowarn; |
|
50
|
|
|
|
|
|
|
} |
|
51
|
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
private: |
|
53
|
|
|
|
|
|
|
bool _enabled; |
|
54
|
|
|
|
|
|
|
decltype(PL_curcop->cop_warnings) _cop_warnings; |
|
55
|
|
|
|
|
|
|
U8 _dowarn; |
|
56
|
|
|
|
|
|
|
}; |
|
57
|
|
|
|
|
|
|
} |
|
58
|
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
namespace xs { |
|
60
|
|
|
|
|
|
|
template struct Typemap : Typemap {}; |
|
61
|
|
|
|
|
|
|
template struct Typemap : Typemap {}; |
|
62
|
|
|
|
|
|
|
} |
|
63
|
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
#undef PANDA_LOG_CODE_POINT |
|
65
|
|
|
|
|
|
|
#define PANDA_LOG_CODE_POINT make_code_point() |
|
66
|
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
static inline CV* get_context_sub () { |
|
68
|
|
|
|
|
|
|
int depth = 0; |
|
69
|
|
|
|
|
|
|
auto ctx = caller_cx(depth, nullptr); |
|
70
|
|
|
|
|
|
|
while (ctx) { |
|
71
|
|
|
|
|
|
|
if (CxTYPE(ctx) == CXt_SUB) return ctx->blk_sub.cv; |
|
72
|
|
|
|
|
|
|
ctx = caller_cx(++depth, nullptr); |
|
73
|
|
|
|
|
|
|
} |
|
74
|
|
|
|
|
|
|
return nullptr; |
|
75
|
|
|
|
|
|
|
} |
|
76
|
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
static inline CodePoint make_code_point () { |
|
78
|
|
|
|
|
|
|
auto cop = PL_curcop; |
|
79
|
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
string_view func; |
|
81
|
|
|
|
|
|
|
auto cv = get_context_sub(); |
|
82
|
|
|
|
|
|
|
if (cv) { |
|
83
|
|
|
|
|
|
|
GV* gv = CvGV(cv); |
|
84
|
|
|
|
|
|
|
if (gv) func = string_view(GvNAME(gv), GvNAMELEN(gv)); |
|
85
|
|
|
|
|
|
|
} |
|
86
|
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
return CodePoint{CopFILE(cop), CopLINE(cop), func}; |
|
88
|
|
|
|
|
|
|
} |
|
89
|
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
static inline Sv format_args (SV** args, int items) { |
|
91
|
|
|
|
|
|
|
if (!items) return Simple(default_message); |
|
92
|
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
if (items == 1) { |
|
94
|
|
|
|
|
|
|
Sv arg(args[0]); |
|
95
|
|
|
|
|
|
|
if (arg.is_simple()) { return arg; } |
|
96
|
|
|
|
|
|
|
else { return Simple(SvPV_nolen(args[0])); } |
|
97
|
|
|
|
|
|
|
} |
|
98
|
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
NoWarningsGuard g(no_format_warnings); (void)g; |
|
100
|
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
STRLEN patlen; |
|
102
|
|
|
|
|
|
|
auto pat = SvPV(args[0], patlen); |
|
103
|
|
|
|
|
|
|
Sv ret = Simple::create(patlen * 1.5); |
|
104
|
|
|
|
|
|
|
bool stub = false; |
|
105
|
|
|
|
|
|
|
sv_vcatpvfn(ret, pat, patlen, nullptr, args + 1, items - 1, &stub); |
|
106
|
|
|
|
|
|
|
return ret; |
|
107
|
|
|
|
|
|
|
} |
|
108
|
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
static inline void peep_args (SV**& args, I32& items, const Module*& module, Sub& sub) { |
|
110
|
|
|
|
|
|
|
if (items && SvROK(args[0])) { |
|
111
|
|
|
|
|
|
|
auto first = SvRV(args[0]); |
|
112
|
|
|
|
|
|
|
if (has_module(first)) { |
|
113
|
|
|
|
|
|
|
module = xs::in(first); |
|
114
|
|
|
|
|
|
|
++args; |
|
115
|
|
|
|
|
|
|
--items; |
|
116
|
|
|
|
|
|
|
} |
|
117
|
|
|
|
|
|
|
else if (SvTYPE(first) == SVt_PVCV) { |
|
118
|
|
|
|
|
|
|
if (items > 1) throw exception("no arguments should follow subref when logging"); |
|
119
|
|
|
|
|
|
|
sub = first; |
|
120
|
|
|
|
|
|
|
} |
|
121
|
|
|
|
|
|
|
} |
|
122
|
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
if (!module) module = resolve_module(0); // auto detect module by namespace |
|
124
|
|
|
|
|
|
|
} |
|
125
|
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
template |
|
127
|
|
|
|
|
|
|
void forward(Log&& log, SV**& args, I32& items, Sub& sub) { |
|
128
|
|
|
|
|
|
|
Simple msg; |
|
129
|
|
|
|
|
|
|
if (sub) { |
|
130
|
|
|
|
|
|
|
Sv ret = sub.call(); |
|
131
|
|
|
|
|
|
|
SV* sv = ret; |
|
132
|
|
|
|
|
|
|
msg = format_args(&sv, 1); |
|
133
|
|
|
|
|
|
|
} |
|
134
|
|
|
|
|
|
|
else { |
|
135
|
|
|
|
|
|
|
msg = format_args(args, items); |
|
136
|
|
|
|
|
|
|
} |
|
137
|
|
|
|
|
|
|
log << msg.as_string(); |
|
138
|
|
|
|
|
|
|
} |
|
139
|
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
static void xslog (Level level, SV** args, I32 items) { |
|
141
|
|
|
|
|
|
|
const Module* module = nullptr; |
|
142
|
|
|
|
|
|
|
Sub sub; |
|
143
|
|
|
|
|
|
|
peep_args(args, items, module, sub); |
|
144
|
|
|
|
|
|
|
panda_log(level, *module, [&]{ forward(log, args, items, sub); }); |
|
145
|
|
|
|
|
|
|
} |
|
146
|
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
MODULE = XLog PACKAGE = XLog |
|
148
|
|
|
|
|
|
|
PROTOTYPES: DISABLE |
|
149
|
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
BOOT { |
|
151
|
16
|
50
|
|
|
|
|
Stash stash(__PACKAGE__); |
|
152
|
|
|
|
|
|
|
|
|
153
|
88
|
50
|
|
|
|
|
xs::exp::create_constants(stash, { |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
{"VERBOSE_DEBUG", (int)Level::VerboseDebug}, |
|
155
|
|
|
|
|
|
|
{"DEBUG", (int)Level::Debug}, |
|
156
|
|
|
|
|
|
|
{"INFO", (int)Level::Info}, |
|
157
|
|
|
|
|
|
|
{"NOTICE", (int)Level::Notice}, |
|
158
|
|
|
|
|
|
|
{"WARNING", (int)Level::Warning}, |
|
159
|
|
|
|
|
|
|
{"ERROR", (int)Level::Error}, |
|
160
|
|
|
|
|
|
|
{"CRITICAL", (int)Level::Critical}, |
|
161
|
|
|
|
|
|
|
{"ALERT", (int)Level::Alert}, |
|
162
|
|
|
|
|
|
|
{"EMERGENCY", (int)Level::Emergency}, |
|
163
|
80
|
50
|
|
|
|
|
}); |
|
164
|
|
|
|
|
|
|
|
|
165
|
16
|
50
|
|
|
|
|
auto root_module = xs::out(&::panda_log_module); |
|
166
|
8
|
|
|
|
|
|
root_module.readonly(1); |
|
167
|
8
|
50
|
|
|
|
|
stash.add_const_sub("default_format", xs::out(default_format)); |
|
|
|
50
|
|
|
|
|
|
|
168
|
8
|
50
|
|
|
|
|
stash.add_const_sub("root", root_module); |
|
169
|
8
|
50
|
|
|
|
|
stash.store("root_module", root_module); |
|
170
|
|
|
|
|
|
|
|
|
171
|
32
|
50
|
|
|
|
|
xs::at_perl_destroy([]{ |
|
172
|
8
|
50
|
|
|
|
|
if (dyn_cast(get_logger().get())) set_logger(nullptr); |
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
173
|
8
|
50
|
|
|
|
|
if (dyn_cast(get_formatter().get())) set_formatter(nullptr); |
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
174
|
24
|
50
|
|
|
|
|
}); |
|
175
|
|
|
|
|
|
|
} |
|
176
|
|
|
|
|
|
|
|
|
177
|
31
|
50
|
|
|
|
|
void set_level (Level level, string_view module = {}) |
|
178
|
|
|
|
|
|
|
|
|
179
|
55
|
50
|
|
|
|
|
void set_logger (ILoggerSP logger) |
|
|
|
50
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
void set_formatter (IFormatterSP fmt) : ALIAS(set_format=1) { |
|
182
|
|
|
|
|
|
|
(void)ix; |
|
183
|
52
|
50
|
|
|
|
|
set_formatter(fmt); |
|
|
|
50
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
} |
|
185
|
|
|
|
|
|
|
|
|
186
|
2
|
|
|
|
|
|
ILoggerSP get_logger () |
|
187
|
1
|
50
|
|
|
|
|
|
|
188
|
2
|
|
|
|
|
|
IFormatterSP get_formatter () |
|
189
|
1
|
50
|
|
|
|
|
|
|
190
|
6
|
|
|
|
|
|
Module* get_module (string_view name) |
|
191
|
3
|
50
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
void log (Level level, ...) { |
|
193
|
64
|
|
|
|
|
|
xslog(level, &ST(1), items-1); |
|
194
|
64
|
100
|
|
|
|
|
if (!(PL_op->op_spare & 1)) xlog::optimize(); |
|
195
|
|
|
|
|
|
|
} |
|
196
|
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
Module* resolve_module (size_t depth = 0) { |
|
198
|
40
|
|
|
|
|
|
RETVAL = resolve_module(depth); |
|
199
|
20
|
50
|
|
|
|
|
} |
|
200
|
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
void disable_format_warnings () : ALIAS(enable_format_warnings=1) { |
|
202
|
2
|
|
|
|
|
|
no_format_warnings = !ix; |
|
203
|
|
|
|
|
|
|
} |
|
204
|
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
void __logXXX (...) : ALIAS(verbose_debug=0, debug=1, info=2, notice=3, warning=4, error=5, critical=6, alert=7, emergency=8) { |
|
206
|
104
|
|
|
|
|
|
Level level = Level((int)Level::VerboseDebug + ix); |
|
207
|
104
|
|
|
|
|
|
xslog(level, &ST(0), items); |
|
208
|
102
|
100
|
|
|
|
|
if (!(PL_op->op_spare & 1)) xlog::optimize(level); |
|
209
|
|
|
|
|
|
|
} |