A general-purpose single-header C logging library and parser for event-based logs. (Incomplete)
{#} | Time | Hash | Subject | Author | # | (+) | (-) | GPG? |
---|---|---|---|---|---|---|---|---|
65 | 12 Aug 2019 17:45 | 0574934 | Set new specification for C++ API | Josh Stockin | 13 | 152 | 795 | N |
Object | Latest Commit Subject | Time | Hash |
---|---|---|---|
static | Logo | 25 Dec 2018 19:58 | 5a96206 |
.gitignore | Set new specification for C++ API | 12 Aug 2019 17:45 | 0574934 |
LICENSE | Create LICENSE | 26 Dec 2018 17:01 | 9046b13 |
README.md | Set new specification for C++ API | 12 Aug 2019 17:45 | 0574934 |
Multilevel logging for advanced programs.
This is subject to future change over security concerns regarding pointers and memory allocation.
class lognestmonster
enum VerbosityLevels {INFO, DEBUG, VERBOSE, VERYVERBOSE, WARNING, ERROR}
struct QueueConfig
char * out_dir // directory to output log files
virtual void * alloc(size_t size) // implementation defaults to cstd malloc()
virtual void free(void * block) // implementation defaults to cstd free()
virtual void * serialize(LogObject * obj) // implementation defaults to manual serialization of standard LogObject to allocated block
virtual bool write(void * serialized, size_t size, std::ostream stream) // implementation defaults to writing entire serialized block to stream
interface LogObject
Pushable * parent
interface Pushable
protected:
std::vector<LogObject *> pushed
public:
push(LogObject * obj)
push(int verbosity, char * tag, char * message) // implicitly creates a Statement and then pushes
class Queue : Pushable
public:
struct QueueConfig * _config
constructor (struct QueueConfig * config)
write() // serializes, writes, and clears pushed LogObjects
write(LogObject * obj) // implicit push(), then write()
write(int verbosity, char * tag, char * message) // implicit Statement creation, push(), then write()
class Event : LogObject, Pushable
public:
constructor (LogObject * obj) // implicit push()
constructor (int verbosity, char * tag, char * message) // implicit Statement creation, then push()
class Statement : LogObject
public:
int verbosity
int timestamp
char * tag
char * message
constructor (int verbosity, char * tag, char * message)
A 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.
An 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.
A Statement
is the data-containing log item with a timestamp, verbosity level, tag/invoker, and message.
In reference to data serialization, parser
as used here is just a deserializer.
By 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.
Open event with 0x2
and close with 0x3
. Statements or more events can be written inbetween these tags.
0x2 // open event
// more events or statements
0x3 // close event
Open statement with 0x0
and close 0x1
.
0x0
unsigned char verbosity
unsigned int timestamp
unsigned char tag_size
unsigned char[] tag
unsigned short message_size
unsigned char[] message
0x1
A 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.
The 6 verbosity level enums and their byte values are:
INFO = 0
DEBUG = 1
VERBOSE = 2
VERYVERBOSE = 3
WARNING = 4
ERROR = 5
1 statement inside one 1 event:
0x2 // open event 1
0x0 // open statement 1
1565561768752 // timestamp 4
0 // verbosity 1
4 // tag_size 1
"INIT" // tag 4
5 // message_size 2
"HELLO" // message 5
0x1 // close statement 1
0x3 // close event 1
// 21 total bytes for this log tree
With 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:
Log: sample.raw
File size: 21 bytes
Content: 1 statement
v 1 ITEM
1565561768752 - INFO - INIT - HELLO
By 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:
Queue queue;
Event event;
Statement state1;
Statement state2;
// Existing files:
// statement1.raw
// statement2.raw
event.push(state1)
// Existing files:
// event.raw
// statement2.raw
queue.push(event)
// Existing files:
// queue.raw
// statement2.raw
event.push(state2)
// Existing files:
// queue.raw (all log items now exist inside the queue)
queue.write()
// Existing files:
// log12345.raw (consists of 2 statements inside 1 event)
In reality, file names will likely contain timestamps, hashes, or some other form of identifiable metadata.
lognestmonster Copyright (c) 2019 Joshua 'joshuas3' Stockin under the GNU General Public License v3.
The following should be present in each file.
lognestmonster Copyright (c) 2019 Joshua 'joshuas3' Stockin
<https://github.com/JoshuaS3/lognestmonster/>.
This file is part of lognestmonster.
lognestmonster is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
lognestmonster is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with lognestmonster. If not, see <https://www.gnu.org/licenses/>.