agoo 2.2.2 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of agoo might be problematic. Click here for more details.

@@ -3,15 +3,11 @@
3
3
  #ifndef __AGOO_LOG_H__
4
4
  #define __AGOO_LOG_H__
5
5
 
6
- #include <netdb.h>
7
6
  #include <pthread.h>
8
7
  #include <stdarg.h>
9
8
  #include <stdatomic.h>
10
9
  #include <stdbool.h>
11
10
  #include <stdint.h>
12
- #include <stdio.h>
13
-
14
- #include <ruby.h>
15
11
 
16
12
  #include "err.h"
17
13
 
@@ -89,6 +85,8 @@ struct _Log {
89
85
  atomic_int wait_state;
90
86
  int rsock;
91
87
  int wsock;
88
+
89
+ void (*on_error)(Err err);
92
90
  };
93
91
 
94
92
  extern struct _Log the_log;
@@ -103,7 +101,8 @@ extern struct _LogCat resp_cat;
103
101
  extern struct _LogCat eval_cat;
104
102
  extern struct _LogCat push_cat;
105
103
 
106
- extern void log_init(VALUE mod);
104
+ extern void log_init();
105
+ extern void open_log_file();
107
106
 
108
107
  extern void log_close();
109
108
  extern bool log_flush(double timeout);
@@ -119,4 +118,6 @@ extern void log_catv(LogCat cat, const char *fmt, va_list ap);
119
118
 
120
119
  extern void log_start(bool with_pid);
121
120
 
121
+ extern Color find_color(const char *name);
122
+
122
123
  #endif /* __AGOO_LOG_H__ */
@@ -0,0 +1,25 @@
1
+ // Copyright (c) 2018, Peter Ohler, All rights reserved.
2
+
3
+ #ifndef __AGOO_METHOD_H__
4
+ #define __AGOO_METHOD_H__
5
+
6
+ typedef enum {
7
+ CONNECT = 'C',
8
+ DELETE = 'D',
9
+ GET = 'G',
10
+ HEAD = 'H',
11
+ OPTIONS = 'O',
12
+ POST = 'P',
13
+ PUT = 'U',
14
+ PATCH = 'T',
15
+ ALL = 'A',
16
+ NONE = '\0',
17
+
18
+ ON_MSG = 'M', // use for on_message callback
19
+ ON_BIN = 'B', // use for on_message callback with binary (ASCII8BIT)
20
+ ON_CLOSE = 'X', // use for on_close callback
21
+ ON_SHUTDOWN = 'S', // use for on_shotdown callback
22
+ ON_EMPTY = 'E', // use for on_drained callback
23
+ } Method;
24
+
25
+ #endif // __AGOO_METHOD_H__
@@ -64,6 +64,7 @@ request_create(size_t mlen) {
64
64
  if (NULL != req) {
65
65
  DEBUG_ALLOC(mem_req, req);
66
66
  memset(req, 0, size);
67
+ req->env = Qnil;
67
68
  req->mlen = mlen;
68
69
  }
69
70
  return req;
@@ -546,30 +547,33 @@ rack_logger(VALUE self) {
546
547
  */
547
548
  VALUE
548
549
  request_env(Req req) {
549
- volatile VALUE env = rb_hash_new();
550
+ if (Qnil == req->env) {
551
+ volatile VALUE env = rb_hash_new();
550
552
 
551
- // As described by
552
- // http://www.rubydoc.info/github/rack/rack/master/file/SPEC and
553
- // https://github.com/rack/rack/blob/master/SPEC.
554
-
555
- rb_hash_aset(env, request_method_val, req_method(req));
556
- rb_hash_aset(env, script_name_val, req_script_name(req));
557
- rb_hash_aset(env, path_info_val, req_path_info(req));
558
- rb_hash_aset(env, query_string_val, req_query_string(req));
559
- rb_hash_aset(env, server_name_val, req_server_name(req));
560
- rb_hash_aset(env, server_port_val, req_server_port(req));
561
- fill_headers(req, env);
562
- rb_hash_aset(env, rack_version_val, rack_version_val_val);
563
- rb_hash_aset(env, rack_url_scheme_val, req_rack_url_scheme(req));
564
- rb_hash_aset(env, rack_input_val, req_rack_input(req));
565
- rb_hash_aset(env, rack_errors_val, req_rack_errors(req));
566
- rb_hash_aset(env, rack_multithread_val, req_rack_multithread(req));
567
- rb_hash_aset(env, rack_multiprocess_val, Qfalse);
568
- rb_hash_aset(env, rack_run_once_val, Qfalse);
569
- rb_hash_aset(env, rack_logger_val, req_rack_logger(req));
570
- rb_hash_aset(env, rack_upgrade_val, req_rack_upgrade(req));
571
-
572
- return env;
553
+ // As described by
554
+ // http://www.rubydoc.info/github/rack/rack/master/file/SPEC and
555
+ // https://github.com/rack/rack/blob/master/SPEC.
556
+
557
+ rb_hash_aset(env, request_method_val, req_method(req));
558
+ rb_hash_aset(env, script_name_val, req_script_name(req));
559
+ rb_hash_aset(env, path_info_val, req_path_info(req));
560
+ rb_hash_aset(env, query_string_val, req_query_string(req));
561
+ rb_hash_aset(env, server_name_val, req_server_name(req));
562
+ rb_hash_aset(env, server_port_val, req_server_port(req));
563
+ fill_headers(req, env);
564
+ rb_hash_aset(env, rack_version_val, rack_version_val_val);
565
+ rb_hash_aset(env, rack_url_scheme_val, req_rack_url_scheme(req));
566
+ rb_hash_aset(env, rack_input_val, req_rack_input(req));
567
+ rb_hash_aset(env, rack_errors_val, req_rack_errors(req));
568
+ rb_hash_aset(env, rack_multithread_val, req_rack_multithread(req));
569
+ rb_hash_aset(env, rack_multiprocess_val, Qfalse);
570
+ rb_hash_aset(env, rack_run_once_val, Qfalse);
571
+ rb_hash_aset(env, rack_logger_val, req_rack_logger(req));
572
+ rb_hash_aset(env, rack_upgrade_val, req_rack_upgrade(req));
573
+
574
+ req->env = env;
575
+ }
576
+ return req->env;
573
577
  }
574
578
 
575
579
  /* Document-method: to_h
@@ -34,6 +34,7 @@ typedef struct _Req {
34
34
  struct _Str header;
35
35
  struct _Str body;
36
36
  VALUE handler;
37
+ VALUE env;
37
38
  HookType handler_type;
38
39
  Res res;
39
40
  size_t mlen; // allocated msg length
@@ -53,7 +53,6 @@ response_free(void *ptr) {
53
53
  while (NULL != (h = res->headers)) {
54
54
  res->headers = h->next;
55
55
  DEBUG_FREE(mem_header, h);
56
- // TBD
57
56
  xfree(h);
58
57
  }
59
58
  DEBUG_FREE(mem_res_body, res->body);
@@ -0,0 +1,82 @@
1
+ // Copyright (c) 2018, Peter Ohler, All rights reserved.
2
+
3
+ #include <stdlib.h>
4
+ #include <string.h>
5
+
6
+ #include <ruby.h>
7
+
8
+ #include "debug.h"
9
+ #include "rhook.h"
10
+ #include "hook.h"
11
+
12
+ static VALUE
13
+ resolve_classname(VALUE mod, const char *classname) {
14
+ VALUE clas;
15
+ ID ci = rb_intern(classname);
16
+
17
+ if (rb_const_defined_at(mod, ci)) {
18
+ clas = rb_const_get_at(mod, ci);
19
+ } else {
20
+ clas = Qundef;
21
+ }
22
+ return clas;
23
+ }
24
+
25
+ static VALUE
26
+ resolve_classpath(const char *name, size_t len) {
27
+ char class_name[1024];
28
+ VALUE clas;
29
+ char *end = class_name + sizeof(class_name) - 1;
30
+ char *s;
31
+ const char *n = name;
32
+
33
+ clas = rb_cObject;
34
+ for (s = class_name; 0 < len; n++, len--) {
35
+ if (':' == *n) {
36
+ *s = '\0';
37
+ n++;
38
+ len--;
39
+ if (':' != *n) {
40
+ return Qundef;
41
+ }
42
+ if (Qundef == (clas = resolve_classname(clas, class_name))) {
43
+ return Qundef;
44
+ }
45
+ s = class_name;
46
+ } else if (end <= s) {
47
+ return Qundef;
48
+ } else {
49
+ *s++ = *n;
50
+ }
51
+ }
52
+ *s = '\0';
53
+ return resolve_classname(clas, class_name);
54
+ }
55
+
56
+ Hook
57
+ rhook_create(Method method, const char *pattern, VALUE handler) {
58
+ Hook hook = hook_create(method,pattern, NULL, RACK_HOOK);
59
+
60
+ if (NULL != hook) {
61
+ if (T_STRING == rb_type(handler)) {
62
+ handler = resolve_classpath(StringValuePtr(handler), RSTRING_LEN(handler));
63
+ // TBD does class handle it or should an instance be made?
64
+ //
65
+ }
66
+ hook->handler = (void*)handler;
67
+ rb_gc_register_address(&handler);
68
+ if (rb_respond_to(handler, rb_intern("on_request"))) {
69
+ hook->type = BASE_HOOK;
70
+ } else if (rb_respond_to(handler, rb_intern("call"))) {
71
+ hook->type = RACK_HOOK;
72
+ } else if (rb_respond_to(handler, rb_intern("create")) &&
73
+ rb_respond_to(handler, rb_intern("read")) &&
74
+ rb_respond_to(handler, rb_intern("update")) &&
75
+ rb_respond_to(handler, rb_intern("delete"))) {
76
+ hook->type = WAB_HOOK;
77
+ } else {
78
+ rb_raise(rb_eArgError, "handler does not have a on_request, or call method nor is it a WAB::Controller");
79
+ }
80
+ }
81
+ return hook;
82
+ }
@@ -0,0 +1,13 @@
1
+ // Copyright (c) 2018, Peter Ohler, All rights reserved.
2
+
3
+ #ifndef __AGOO_RHOOK_H__
4
+ #define __AGOO_RHOOK_H__
5
+
6
+ #include <ruby.h>
7
+
8
+ #include "hook.h"
9
+ #include "method.h"
10
+
11
+ extern Hook rhook_create(Method method, const char *pattern, VALUE handler);
12
+
13
+ #endif // __AGOO_RHOOK_H__
@@ -0,0 +1,469 @@
1
+ // Copyright 2018 by Peter Ohler, All Rights Reserved
2
+
3
+ #include <dirent.h>
4
+ #include <fcntl.h>
5
+ #include <poll.h>
6
+ #include <stdio.h>
7
+ #include <stdlib.h>
8
+ #include <string.h>
9
+ #include <sys/stat.h>
10
+ #include <sys/time.h>
11
+ #include <sys/types.h>
12
+ #include <time.h>
13
+ #include <unistd.h>
14
+
15
+ #include "debug.h"
16
+ #include "dtime.h"
17
+ #include "rlog.h"
18
+
19
+ static VALUE log_mod = Qundef;
20
+
21
+ /* Document-method: configure
22
+ *
23
+ * call-seq: configure(options)
24
+ *
25
+ * Configures the logger
26
+ *
27
+ * - *options* [_Hash_] server options
28
+ *
29
+ * - *:dir* [_String_] directory to place log files in. If nil or empty then no log files are written.
30
+ *
31
+ * - *:console* [_true_|_false_] if true log entry are display on the console.
32
+ *
33
+ * - *:classic* [_true_|_false_] if true log entry follow a classic format. If false log entries are JSON.
34
+ *
35
+ * - *:colorize* [_true_|_false_] if true log entries are colorized.
36
+ *
37
+ * - *:states* [_Hash_] a map of logging categories and whether they should be on or off. Categories are:
38
+ * - *:ERROR* errors
39
+ * - *:WARN* warnings
40
+ * - *:INFO* infomational
41
+ * - *:DEBUG* debugging
42
+ * - *:connect* openning and closing of connections
43
+ * - *:request* requests
44
+ * - *:response* responses
45
+ * - *:eval* handler evaluationss
46
+ * - *:push* writes to WebSocket or SSE connection
47
+ */
48
+ static VALUE
49
+ rlog_configure(VALUE self, VALUE options) {
50
+ if (Qnil != options) {
51
+ VALUE v;
52
+
53
+ if (Qnil != (v = rb_hash_lookup(options, ID2SYM(rb_intern("dir"))))) {
54
+ rb_check_type(v, T_STRING);
55
+ strncpy(the_log.dir, StringValuePtr(v), sizeof(the_log.dir));
56
+ the_log.dir[sizeof(the_log.dir) - 1] = '\0';
57
+ }
58
+ if (Qnil != (v = rb_hash_lookup(options, ID2SYM(rb_intern("max_files"))))) {
59
+ int max = FIX2INT(v);
60
+
61
+ if (1 <= max || max < 100) {
62
+ the_log.max_files = max;
63
+ } else {
64
+ rb_raise(rb_eArgError, "max_files must be between 1 and 100.");
65
+ }
66
+ }
67
+ if (Qnil != (v = rb_hash_lookup(options, ID2SYM(rb_intern("max_size"))))) {
68
+ int max = FIX2INT(v);
69
+
70
+ if (1 <= max) {
71
+ the_log.max_size = max;
72
+ } else {
73
+ rb_raise(rb_eArgError, "max_size must be 1 or more.");
74
+ }
75
+ }
76
+ if (Qnil != (v = rb_hash_lookup(options, ID2SYM(rb_intern("console"))))) {
77
+ the_log.console = (Qtrue == v);
78
+ }
79
+ if (Qnil != (v = rb_hash_lookup(options, ID2SYM(rb_intern("classic"))))) {
80
+ the_log.classic = (Qtrue == v);
81
+ }
82
+ if (Qnil != (v = rb_hash_lookup(options, ID2SYM(rb_intern("colorize"))))) {
83
+ the_log.colorize = (Qtrue == v);
84
+ }
85
+ if (Qnil != (v = rb_hash_lookup(options, ID2SYM(rb_intern("states"))))) {
86
+ if (T_HASH == rb_type(v)) {
87
+ LogCat cat = the_log.cats;
88
+ VALUE cv;
89
+
90
+ for (; NULL != cat; cat = cat->next) {
91
+ if (Qnil != (cv = rb_hash_lookup(v, ID2SYM(rb_intern(cat->label))))) {
92
+ if (Qtrue == cv) {
93
+ cat->on = true;
94
+ } else if (Qfalse == cv) {
95
+ cat->on = false;
96
+ }
97
+ }
98
+ }
99
+ } else {
100
+ rb_raise(rb_eArgError, "states must be a Hash.");
101
+ }
102
+ }
103
+ }
104
+ if (NULL != the_log.file) {
105
+ fclose(the_log.file);
106
+ the_log.file = NULL;
107
+ }
108
+ if ('\0' != *the_log.dir) {
109
+ if (0 != mkdir(the_log.dir, 0770) && EEXIST != errno) {
110
+ rb_raise(rb_eIOError, "Failed to create '%s'.", the_log.dir);
111
+ }
112
+ open_log_file();
113
+ }
114
+ return Qnil;
115
+ }
116
+
117
+ /* Document-method: shutdown
118
+ *
119
+ * call-seq: shutdown()
120
+ *
121
+ * Shutdown the logger. Writes are flushed before shutting down.
122
+ */
123
+ static VALUE
124
+ rlog_shutdown(VALUE self) {
125
+ log_close();
126
+ return Qnil;
127
+ }
128
+
129
+ /* Document-method: error?
130
+ *
131
+ * call-seq: error?()
132
+ *
133
+ * Returns true is errors are being logged.
134
+ */
135
+ static VALUE
136
+ rlog_errorp(VALUE self) {
137
+ return error_cat.on ? Qtrue : Qfalse;
138
+ }
139
+
140
+ /* Document-method: warn?
141
+ *
142
+ * call-seq: warn?()
143
+ *
144
+ * Returns true is warnings are being logged.
145
+ */
146
+ static VALUE
147
+ rlog_warnp(VALUE self) {
148
+ return warn_cat.on ? Qtrue : Qfalse;
149
+ }
150
+
151
+ /* Document-method: info?
152
+ *
153
+ * call-seq: info?()
154
+ *
155
+ * Returns true is info entries are being logged.
156
+ */
157
+ static VALUE
158
+ rlog_infop(VALUE self) {
159
+ return info_cat.on ? Qtrue : Qfalse;
160
+ }
161
+
162
+ /* Document-method: debug?
163
+ *
164
+ * call-seq: debug?()
165
+ *
166
+ * Returns true is debug entries are being logged.
167
+ */
168
+ static VALUE
169
+ rlog_debugp(VALUE self) {
170
+ return debug_cat.on ? Qtrue : Qfalse;
171
+ }
172
+
173
+ /* Document-method: error
174
+ *
175
+ * call-seq: error(msg)
176
+ *
177
+ * Log an error message.
178
+ */
179
+ static VALUE
180
+ rlog_error(VALUE self, VALUE msg) {
181
+ log_cat(&error_cat, "%s", StringValuePtr(msg));
182
+ return Qnil;
183
+ }
184
+
185
+ /* Document-method: warn
186
+ *
187
+ * call-seq: warn(msg)
188
+ *
189
+ * Log a warn message.
190
+ */
191
+ static VALUE
192
+ rlog_warn(VALUE self, VALUE msg) {
193
+ log_cat(&warn_cat, "%s", StringValuePtr(msg));
194
+ return Qnil;
195
+ }
196
+
197
+ /* Document-method: info
198
+ *
199
+ * call-seq: info(msg)
200
+ *
201
+ * Log an info message.
202
+ */
203
+ static VALUE
204
+ rlog_info(VALUE self, VALUE msg) {
205
+ log_cat(&info_cat, "%s", StringValuePtr(msg));
206
+ return Qnil;
207
+ }
208
+
209
+ /* Document-method: debug
210
+ *
211
+ * call-seq: debug(msg)
212
+ *
213
+ * Log a debug message.
214
+ */
215
+ static VALUE
216
+ rlog_debug(VALUE self, VALUE msg) {
217
+ log_cat(&debug_cat, "%s", StringValuePtr(msg));
218
+ return Qnil;
219
+ }
220
+
221
+ /* Document-method: color
222
+ *
223
+ * call-seq: color(label)
224
+ *
225
+ * Returns the current color name as a Symbol for the specified label.
226
+ */
227
+ static VALUE
228
+ rlog_color_get(VALUE self, VALUE label) {
229
+ LogCat cat = log_cat_find(StringValuePtr(label));
230
+
231
+ if (NULL == cat) {
232
+ return Qnil;
233
+ }
234
+ return ID2SYM(rb_intern(cat->color->name));
235
+ }
236
+
237
+ /* Document-method: set_color
238
+ *
239
+ * call-seq: set_color(label, color_symbol)
240
+ *
241
+ * Sets color of the category associated with a label. Valid colors are
242
+ * :black, :red, :green, :yellow, :blue, :magenta, :cyan, :white, :gray,
243
+ * :dark_red, :dark_green, :brown, :dark_blue, :purple, and :dark_cyan.
244
+ */
245
+ static VALUE
246
+ rlog_color_set(VALUE self, VALUE label, VALUE color) {
247
+ const char *label_str = StringValuePtr(label);
248
+ const char *color_name = StringValuePtr(color);
249
+ LogCat cat = log_cat_find(label_str);
250
+ Color c = find_color(color_name);
251
+
252
+ if (NULL == cat) {
253
+ rb_raise(rb_eArgError, "%s is not a valid category.", label_str);
254
+ }
255
+ if (NULL == c) {
256
+ rb_raise(rb_eArgError, "%s is not a valid color.", color_name);
257
+ }
258
+ cat->color = c;
259
+
260
+ return Qnil;
261
+ }
262
+
263
+ /* Document-method: state
264
+ *
265
+ * call-seq: state(label)
266
+ *
267
+ * Returns the current state of the category identified by the specified
268
+ * label.
269
+ */
270
+ static VALUE
271
+ rlog_on_get(VALUE self, VALUE label) {
272
+ LogCat cat = log_cat_find(StringValuePtr(label));
273
+
274
+ if (NULL == cat) {
275
+ return Qfalse;
276
+ }
277
+ return cat->on ? Qtrue : Qfalse;
278
+ }
279
+
280
+ /* Document-method: set_state
281
+ *
282
+ * call-seq: set_state(label, state)
283
+ *
284
+ * Sets state of the category associated with a label.
285
+ */
286
+ static VALUE
287
+ rlog_on_set(VALUE self, VALUE label, VALUE state) {
288
+ const char *label_str = StringValuePtr(label);
289
+ LogCat cat = log_cat_find(label_str);
290
+
291
+ if (NULL == cat) {
292
+ rb_raise(rb_eArgError, "%s is not a valid category.", label_str);
293
+ }
294
+ cat->on = (Qtrue == state);
295
+
296
+ return cat->on ? Qtrue : Qfalse;
297
+ }
298
+
299
+ /* Document-method: log
300
+ *
301
+ * call-seq: log[label] = msg
302
+ *
303
+ * Log a message in the specified category.
304
+ */
305
+ static VALUE
306
+ rlog_log(VALUE self, VALUE label, VALUE msg) {
307
+ const char *label_str = StringValuePtr(label);
308
+ LogCat cat = log_cat_find(label_str);
309
+
310
+ if (NULL == cat) {
311
+ rb_raise(rb_eArgError, "%s is not a valid category.", label_str);
312
+ }
313
+ log_cat(cat, "%s", StringValuePtr(msg));
314
+
315
+ return Qnil;
316
+ }
317
+
318
+ /* Document-method: flush
319
+ *
320
+ * call-seq: flush
321
+ *
322
+ * Flush the log queue and write all entries to disk or the console. The call
323
+ * waits for the flush to complete or the timeout to be exceeded.
324
+ */
325
+ static VALUE
326
+ rlog_flush(VALUE self, VALUE to) {
327
+ double timeout = NUM2DBL(to);
328
+
329
+ if (!log_flush(timeout)) {
330
+ rb_raise(rb_eStandardError, "timed out waiting for log flush.");
331
+ }
332
+ return Qnil;
333
+ }
334
+
335
+ /* Document-method: rotate
336
+ *
337
+ * call-seq: rotate()
338
+ *
339
+ * Rotate the log files.
340
+ */
341
+ static VALUE
342
+ rlog_rotate(VALUE self) {
343
+ log_rotate();
344
+ return Qnil;
345
+ }
346
+
347
+ /* Document-method: console=
348
+ *
349
+ * call-seq: console=(on)
350
+ *
351
+ * If on then log output also goes to the console.
352
+ */
353
+ static VALUE
354
+ rlog_console(VALUE self, VALUE on) {
355
+ the_log.console = (Qtrue == on);
356
+ return Qnil;
357
+ }
358
+
359
+ /* Document-method: classic
360
+ *
361
+ * call-seq: classic()
362
+ *
363
+ * Set the log format to classic format.
364
+ */
365
+ static VALUE
366
+ rlog_classic(VALUE self) {
367
+ the_log.classic = true;
368
+ return Qnil;
369
+ }
370
+
371
+ /* Document-method: json
372
+ *
373
+ * call-seq: json()
374
+ *
375
+ * Set the log format to JSON format.
376
+ */
377
+ static VALUE
378
+ rlog_json(VALUE self) {
379
+ the_log.classic = false;
380
+ return Qnil;
381
+ }
382
+
383
+ /* Document-method: max_size
384
+ *
385
+ * call-seq: max_size(size)
386
+ *
387
+ * Maximum log files size is reset.
388
+ */
389
+ static VALUE
390
+ rlog_max_size(VALUE self, VALUE rmax) {
391
+ int max = FIX2INT(rmax);
392
+
393
+ if (1 <= max) {
394
+ the_log.max_size = max;
395
+ } else {
396
+ rb_raise(rb_eArgError, "max_size must be 1 or more.");
397
+ }
398
+ return Qnil;
399
+ }
400
+
401
+ /* Document-method: max_files
402
+ *
403
+ * call-seq: max_files(max)
404
+ *
405
+ * Maximum log files files is reset.
406
+ */
407
+ static VALUE
408
+ rlog_max_files(VALUE self, VALUE rmax) {
409
+ int max = FIX2INT(rmax);
410
+
411
+ if (1 <= max || max < 100) {
412
+ the_log.max_files = max;
413
+ } else {
414
+ rb_raise(rb_eArgError, "max_files must be between 1 and 100.");
415
+ }
416
+ return Qnil;
417
+ }
418
+
419
+ static void
420
+ on_error(Err err) {
421
+ rb_raise(rb_eStandardError, "%s", err->msg);
422
+ }
423
+
424
+ /* Document-class: Agoo::Log
425
+ *
426
+ * An asynchronous and thread safe logger that includes file rollover and
427
+ * multiple logging categories. It is a feature based logger with a level
428
+ * overlay.
429
+ */
430
+ void
431
+ rlog_init(VALUE mod) {
432
+ log_mod = rb_define_module_under(mod, "Log");
433
+
434
+ rb_define_module_function(log_mod, "configure", rlog_configure, 1);
435
+ rb_define_module_function(log_mod, "shutdown", rlog_shutdown, 0);
436
+
437
+ rb_define_module_function(log_mod, "error?", rlog_errorp, 0);
438
+ rb_define_module_function(log_mod, "warn?", rlog_warnp, 0);
439
+ rb_define_module_function(log_mod, "info?", rlog_infop, 0);
440
+ rb_define_module_function(log_mod, "debug?", rlog_debugp, 0);
441
+
442
+ rb_define_module_function(log_mod, "error", rlog_error, 1);
443
+ rb_define_module_function(log_mod, "warn", rlog_warn, 1);
444
+ rb_define_module_function(log_mod, "info", rlog_info, 1);
445
+ rb_define_module_function(log_mod, "debug", rlog_debug, 1);
446
+
447
+ // TBD maybe in a future version
448
+ //rb_define_module_function(log_mod, "register", rlog_register, 2);
449
+
450
+ rb_define_module_function(log_mod, "color", rlog_color_get, 1);
451
+ rb_define_module_function(log_mod, "set_color", rlog_color_set, 2);
452
+
453
+ rb_define_module_function(log_mod, "state", rlog_on_get, 1);
454
+ rb_define_module_function(log_mod, "set_state", rlog_on_set, 2);
455
+
456
+ rb_define_module_function(log_mod, "log", rlog_log, 2);
457
+
458
+ rb_define_module_function(log_mod, "flush", rlog_flush, 1);
459
+ rb_define_module_function(log_mod, "rotate", rlog_rotate, 0);
460
+ rb_define_module_function(log_mod, "console=", rlog_console, 1);
461
+ rb_define_module_function(log_mod, "classic", rlog_classic, 0);
462
+ rb_define_module_function(log_mod, "json", rlog_json, 0);
463
+ rb_define_module_function(log_mod, "max_size=", rlog_max_size, 1);
464
+ rb_define_module_function(log_mod, "max_files=", rlog_max_files, 1);
465
+
466
+ the_log.on_error = on_error;
467
+
468
+ log_init();
469
+ }