Index

lognestmonster / 0574934

A general-purpose single-header C logging library and parser for event-based logs. (Incomplete)

Latest Commit

{#}TimeHashSubjectAuthor#(+)(-)GPG?
6512 Aug 2019 17:450574934Set new specification for C++ APIJosh Stockin1151317N

Blob @ lognestmonster / README.md

text/plain7826 bytesdownload raw
1<img src="/static/logo.png" height="200px"/>
2
3_Multilevel logging for advanced programs._
4
51. [lognestmonster](#lognestmonster)
62. [Library Class Structure](#library-class-structure)
7 1. [Semantics](#semantics)
83. [Serialization Format](#serialization-format)
9 1. [Events](#events)
10 2. [Statements](#statements)
11 1. [Verbosity Level Enumeration](#verbosity-level-enumeration)
12 3. [Example](#example)
134. [Temporary Data Saving](#temporary-data-saving)
145. [Copyright](#copyright)
15
16# lognestmonster
17
18## Library Class Structure
19This is subject to future change over security concerns regarding pointers and memory allocation.
20```
21class lognestmonster
22
23 enum VerbosityLevels {INFO, DEBUG, VERBOSE, VERYVERBOSE, WARNING, ERROR}
24
25 struct QueueConfig
26 char * out_dir // directory to output log files
27
28 virtual void * alloc(size_t size) // implementation defaults to cstd malloc()
29 virtual void free(void * block) // implementation defaults to cstd free()
30 virtual void * serialize(LogObject * obj) // implementation defaults to manual serialization of standard LogObject to allocated block
31 virtual bool write(void * serialized, size_t size, std::ostream stream) // implementation defaults to writing entire serialized block to stream
32
33 interface LogObject
34 Pushable * parent
35
36 interface Pushable
37 protected:
38 std::vector<LogObject *> pushed
39 public:
40 push(LogObject * obj)
41 push(int verbosity, char * tag, char * message) // implicitly creates a Statement and then pushes
42
43 class Queue : Pushable
44 public:
45 struct QueueConfig * _config
46 constructor (struct QueueConfig * config)
47 write() // serializes, writes, and clears pushed LogObjects
48 write(LogObject * obj) // implicit push(), then write()
49 write(int verbosity, char * tag, char * message) // implicit Statement creation, push(), then write()
50
51 class Event : LogObject, Pushable
52 public:
53 constructor (LogObject * obj) // implicit push()
54 constructor (int verbosity, char * tag, char * message) // implicit Statement creation, then push()
55
56 class Statement : LogObject
57 public:
58 int verbosity
59 int timestamp
60 char * tag
61 char * message
62 constructor (int verbosity, char * tag, char * message)
63```
64### Semantics
65A `Queue` handles data serialization and file writing to the main logtree file. Queue writing refers to sending serialized logtree data to the outstream. Queue pushing refers to adding an Event or Statement to the queue for future writing.
66
67An `Event` is a pushable list of statements or events, or the "nest". Event pushing refers to adding an Event or Statement to the parent's list.
68
69A `Statement` is the data-containing log item with a timestamp, verbosity level, tag/invoker, and message.
70
71In reference to data serialization, `parser` as used here is just a deserializer.
72
73## Serialization Format
74
75By default the library serializes log tree information in a special format. Events and Statements each have their own open and close tags, but in practice the only bytes that are sensitive to position are the Statement data and metadata bytes. Really, the only bytes *needed* to produce any log format are `0x0` and the following statement description bytes; a parser/deserializer could ignore Event openers and closers and still produce a readable log.
76
77### Events
78Open event with `0x2` and close with `0x3`. Statements or more events can be written inbetween these tags.
79```
800x2 // open event
81 // more events or statements
820x3 // close event
83```
84
85### Statements
86Open statement with `0x0` and close `0x1`.
87
881. 1 byte for an open statement tag
892. 1 byte for a predefined verbosity level enum
903. 4 bytes for an unsigned integer timestamp
914. 1 byte for the length of the tag string
925. 0-255 bytes for the tag string
936. 2 bytes for the length of the message string
947. 0-65535 bytes for the message string
958. 1 byte for a close statement tag
96
97```
980x0
99 unsigned char verbosity
100 unsigned int timestamp
101 unsigned char tag_size
102 unsigned char[] tag
103 unsigned short message_size
104 unsigned char[] message
1050x1
106```
107A close statement tag is always needed in case the serializer method is overriden and provides extra data/metadata. If a close statement tag isn't written, a parser/deserializer won't be able to read a serialized logtree with extra data.
108
109#### Verbosity Level Enumeration
110The 6 verbosity level enums and their byte values are:
111```
112INFO = 0
113DEBUG = 1
114VERBOSE = 2
115VERYVERBOSE = 3
116WARNING = 4
117ERROR = 5
118```
119
120### Example
1211 statement inside one 1 event:
122```
1230x2 // open event 1
1240x0 // open statement 1
1251565561768752 // timestamp 4
1260 // verbosity 1
1274 // tag_size 1
128"INIT" // tag 4
1295 // message_size 2
130"HELLO" // message 5
1310x1 // close statement 1
1320x3 // close event 1
133 // 21 total bytes for this log tree
134```
135With the sample log tree used here, the raw byte file totals 21 bytes. In use, a parser/deserializer could take this file and create output similar to the following:
136```
137Log: sample.raw
138File size: 21 bytes
139Content: 1 statement
140
141v 1 ITEM
142 1565561768752 - INFO - INIT - HELLO
143```
144
145## Temporary Data Saving
146
147By the nature of a push-write logging library, there's a chance that some created Statements and Events might not be pushed and written before the program's exit, whether it hangs, crashes, throws a runtime exception, is SIGKILLed, or anything else. Seeing as the point of logging is to find and diagnose errors with ease, it'd be frustrating to lose critical last-second information like this. The solution: save temporary serialized data for every creation or change to Statements, Events, or Queues. Every logtree that ends in a Statement will have its own temporary data file; when a Statement is pushed to an Event, the Statement's file will be deleted and replaced into the greater Event file. See the following example for how data is separated into files:
148
149```
150Queue queue;
151Event event;
152Statement state1;
153Statement state2;
154
155// Existing files:
156// statement1.raw
157// statement2.raw
158
159event.push(state1)
160
161// Existing files:
162// event.raw
163// statement2.raw
164
165queue.push(event)
166
167// Existing files:
168// queue.raw
169// statement2.raw
170
171event.push(state2)
172
173// Existing files:
174// queue.raw (all log items now exist inside the queue)
175
176queue.write()
177
178// Existing files:
179// log12345.raw (consists of 2 statements inside 1 event)
180```
181
182In reality, file names will likely contain timestamps, hashes, or some other form of identifiable metadata.
183
184## Copyright
185
186lognestmonster Copyright (c) 2019 Joshua 'joshuas3' Stockin under the [GNU General Public License v3](LICENSE).
187
188The following should be present in each file.
189```
190lognestmonster Copyright (c) 2019 Joshua 'joshuas3' Stockin
191<https://github.com/JoshuaS3/lognestmonster/>.
192
193
194This file is part of lognestmonster.
195
196lognestmonster is free software: you can redistribute it and/or modify
197it under the terms of the GNU General Public License as published by
198the Free Software Foundation, either version 3 of the License, or
199(at your option) any later version.
200
201lognestmonster is distributed in the hope that it will be useful,
202but WITHOUT ANY WARRANTY; without even the implied warranty of
203MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
204GNU General Public License for more details.
205
206You should have received a copy of the GNU General Public License
207along with lognestmonster. If not, see <https://www.gnu.org/licenses/>.
208```
209