File: cf_journal.mli

package info (click to toggle)
pagodacf 0.10-5
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 1,356 kB
  • sloc: ml: 8,458; ansic: 3,339; makefile: 173
file content (337 lines) | stat: -rw-r--r-- 13,623 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
(*---------------------------------------------------------------------------*
  INTERFACE  cf_journal.mli

  Copyright (c) 2004-2006, James H. Woodyatt
  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions
  are met:

    Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.

    Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in
    the documentation and/or other materials provided with the
    distribution

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  OF THE POSSIBILITY OF SUCH DAMAGE. 
 *---------------------------------------------------------------------------*)

(** Diagnostic event journaling. *)

(** {6 Overview} *)

(** This module implements a lightweight foundation for diagnostic event
    journaling, similar to the core Java classes in the {b Log4j} project from
    the Apache Foundation.
    
    The core interface is functorial, and is intended for extensibility.  An
    additional interface is provided for simplicity of use in the common case
    of journaling diagnostic messages to [Pervasives.out_channel] objects, e.g
    [stdout] and [stderr].
*)

(** {6 Functorial Interface} *)

(** The type of the module produced the [Create(P: Cf_ordered.Total_T)]
    functor defined below.
*)

module type T = sig

    (** The module used to define the total order of priority levels. *)
    module Priority: Cf_ordered.Total_T
    
    (** The base class for prioritizers.  Defines methods for converting
        priority levels into 1) their corresponding code, and 2) their
        corresponding message tag.
    *)
    class virtual ['level] prioritizer:
        object
            (** Use [p#code v] to convert the priority level [v] to a priority
                code with the prioritizer [p].
            *)
            method virtual code: 'level -> Priority.t

            (** Use [p#tag v] to convert the priority level [v] to a message
                tag with the prioritizer [p].
            *)
            method virtual tag: 'level -> string
        end

    (** The minimal class of diagnostic events.  Use [new event p v m] to
        construct an [event] object with the prioritizer [p], the priority
        level [v], and the message [m].
    *)
    class ['level] event:
        'level #prioritizer -> 'level -> string ->
        object
        
            (** Returns the prioritizer used to construct the object. *)
            method prioritizer: 'level prioritizer
        
            (** Returns the priority level used to construct the object. *)
            method level: 'level
        
            (** Returns the message text used to construct the object. *)
            method message: string
        end
    
    (** The base class for event archivers.  Use [inherit archiver] to derive
        a subclass that defines the [emit] method to archive a diagnostic
        event into a journaling system.
    *)
    class virtual ['event] archiver:
        object
            constraint 'event = 'level #event
            
            (** Define the [emit] method in a subclass to archive diagnostic
                events into a journaling system.
            *)
            method virtual emit: 'event -> unit
        end

    (** The base class for journaling agents.  Use [inherit agent p v s] to
        derive a subclass that defines the private [event_] method to construct
        an event object with a priority level and a message text using the
        prioritizer [p].  Sets the initial priority code minimum to [v], and
        the initial list of archivers to [s].
    *)
    class virtual ['archiver] agent:
        'level #prioritizer -> 'level -> 'archiver list ->
        object
            constraint 'event = 'level #event
            constraint 'archiver = 'event #archiver

            (** The current list of archivers that journal events from
                this agent. *)
            val mutable archivers_: 'archiver list
            
            (** The minimum priority code for a diagnostic event to be
                constructed and passed to the archivers.
            *)
            val mutable limit_: Priority.t            

            (** Define the private [event] method to construct an event object
                with a priority level and a message text.
            *)
            method private virtual event: 'level -> string -> 'event

            (** Use [a#setlimit v] to set the minimum priority code to the
                code corresponding to the priority level [v].
            *)
            method setlimit: 'level -> unit
            
            (** Use [a#enabled v] to test whether the priority code
                corresponding to the priority level [v] is preceded in the
                total order by the minimum priority code.
            *)
            method enabled: 'level -> bool
            
            (** Use this method in level-specific methods of the derived class
                for constructing events and putting them to archivers.  Use
                [super#put v c] to construct a function that takes a format
                string (and arguments thereby specified) and, if [self#enabled
                v] returns [true] then calls [self#event v m] (where [m] is
                the message text given to the continuation provided to
                [Printf.kprintf]), iterates on [archivers_] invoking the
                [emit] method for each one with the constructed event, and
                finally passing the event to the continuation [c].  The value
                returned by [c] is returned by the method when invoked with
                a format string (and associated arguments).
            *)
            method private put:
                'a 'b. 'level -> ('event -> 'b) ->
                ('a, unit, string, 'b) format4 -> 'a
        end
end

(** A functor that produces a module of type [T] that defines extensible
    diagnostic event journaling with messages prioritized by codes in the total
    order defined by the module [P].
*)
module Create(P: Cf_ordered.Total_T): T with module Priority = P

(** {6 Basic Interface} *)

(** A module defining basic diagnostic event journaling with a simple set of
    priority levels associated to integer priority codes.
*)
module Basic: sig
    
    (** Event journaling with integer priority codes. *)
    include T with type Priority.t = int

    (** The priority level for events indicating that an internal program
        function has been called with invalid arguments.  Code=7000.
    *)
    type invalid = [ `Invalid ]

    (** The priority level for events indicating that an internal program
        function has failed, results may have been lost and recovery is not
        expected.  Code=6000.
    *)
    type fail = [ `Fail ]

    (** The priority level for events indicating that a program has encountered
        invalid input.  The program is expected to recover and continue
        processing further valid input correctly.  Code=5000.
    *)
    type error = [ `Error ]

    (** The priority level for events indicating that a program has encountered
        unexpected input, indicating that an external process may have failed.
        The program is expected to continue processing further input normally.
        Code=4000.
    *)
    type warn = [ `Warn ]

    (** The priority level for events indicating exceptional information about
        the processing of the program useful for diagnosing external processes.
        Code=2000.
    *)
    type notice = [ `Notice ]

    (** The priority level for events indicating normal information about the
        processing of the program useful for diagnosing external processes.
        Code=2000.
    *)
    type info = [ `Info ]

    (** The priority level for events describing internal processing of the
        program for the purpose of diagnosing programming errors.  Code=1000.
    *)
    type debug = [ `Debug ]
    
    (** The priority levels corresponding to events that the basic agent has
        public methods for journaling.
    *)
    type basic = [ invalid | fail | error | warn | notice | info | debug ]
    
    (** Additional priority levels corresponding to limit levels in the basic
        event prioritizer used for completely enabling or disabling all
        messages.  These levels do not have message tags defined.
    *)
    type enable = [ `None | `All ]
    
    (** The sum of all basic priority levels. *)
    type level = [ basic | enable ]
end

(** The basic prioritizer class, defining the priority codes and message tags
    for all of the basic priority levels: [`Invalid], [`Fail], [`Error],
    [`Warn], [`Info] and [`Debug].  Derive a subclass to define a prioritizer
    for additional priority levels corresponding to other integer codes.
*)
class ['level] basic_prioritizer :
    object
        constraint 'level = [> Basic.level ]

        (** Returns the integer corresponding to the priority level. *)
        method code: 'level -> Basic.Priority.t
        
        (** Returns the message tag corresponding to the priority level. *)
        method tag: 'level -> string
    end

(** The basic channel archiver.  Use [new basic_channel_archiver c] to
    construct an archiver that emits each basic event [e] with a priority level
    less than [`Fail] to the channel [c] using [Printf.fprintf c "%s: %s\n"
    e#prioritizer#tag e#message].
*)
class ['event] basic_channel_archiver:
    out_channel ->
    object
        constraint 'event = [> Basic.level ] #Basic.event

        (** Returns the channel used to construct the archiver. *)
        method channel: out_channel
        
        (** Emits each basic event [e] with a priority level less than [`Fail]
            to the channel [c] using [Printf.fprintf c "%s: %s\n"
            e#prioritizer#tag e#message].
        *)
        method emit: 'event -> unit
    end

(** The basic journaling agent.  Derive a subclass to define an agent that can
    construct events derived from the basic event (which may also require
    archivers derived from the basic archiver that can format any additional
    required output).  The class defines six public methods for output of
    diagnostic events, one for each basic priority level.
*)
class virtual ['archiver] basic_agent:
    'level #basic_prioritizer -> 'level -> 'archiver list ->
    object
        constraint 'level = [> Basic.level ]
        constraint 'event = 'level #Basic.event
        constraint 'archiver = 'event #Basic.archiver
        inherit ['archiver] Basic.agent

        (** Use [a#invalid msg ...] to format message text to put to the
            archivers at the [`Invalid] level, and finally used to raise an
            [Invalid_argument] exception.
        *)
        method invalid: 'a 'b. ('a, unit, string, 'b) format4 -> 'a

        (** Use [a#fail msg ...] to format message text to put to the
            archivers at the [`Fail] level, and finally used to raise an
            [Failure] exception.
        *)
        method fail: 'a 'b. ('a, unit, string, 'b) format4 -> 'a

        (** Use [a#error msg ...] to format message text to put to the
            archivers at the [`Error] level.
        *)
        method error: 'a. ('a, unit, string, unit) format4 -> 'a

        (** Use [a#warn msg ...] to format message text to put to the
            archivers at the [`Warn] level.
        *)
        method warn: 'a. ('a, unit, string, unit) format4 -> 'a

        (** Use [a#notice msg ...] to format message text to put to the
            archivers at the [`Notice] level.
        *)
        method notice: 'a. ('a, unit, string, unit) format4 -> 'a

        (** Use [a#info msg ...] to format message text to put to the
            archivers at the [`Info] level.
        *)
        method info: 'a. ('a, unit, string, unit) format4 -> 'a

        (** Use [a#debug msg ...] to format message text to put to the
            archivers at the [`Debug] level.  The result of the formatting
            continuation is always [true].  This is to facilitate using the
            method inside [assert] blocks.
        *)
        method debug: 'a. ('a, unit, string, bool) format4 -> 'a
    end

(** The type of the most basic agent, used for [stdout] and [stderr] below. *)
type t = Basic.level Basic.event Basic.archiver basic_agent

(** A basic agent, initially set with a limit of [`Notice], and with with one
    basic archiver for the [Pervasives.stdout] channel.
*)
val stdout: t

(** A basic agent, initially set with a limit of [`Notice], and with with one
    basic archiver for the [Pervasives.stderr] channel.
*)
val stderr: t

(*--- End of File [ cf_journal.mli ] ---*)