Index

lognestmonster / 11ee284

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

Latest Commit

{#}TimeHashSubjectAuthor#(+)(-)GPG?
14121 Nov 2019 20:3911ee284Log item/queue registry started, basic queue handlingJosh Stockin1612N

Blob @ lognestmonster / src / c / lognestmonster.h

text/plain9163 bytesdownload raw
1// lognestmonster Copyright (c) 2019 Joshua 'joshuas3' Stockin
2// lognestmonster.h
3// C header file for implementation of the lognestmonster logging library
4
5// <https://github.com/JoshuaS3/lognestmonster/>.
6
7
8// This file is part of lognestmonster.
9
10// lognestmonster is free software: you can redistribute it and/or modify
11// it under the terms of the GNU General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14
15// lognestmonster is distributed in the hope that it will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License for more details.
19
20// You should have received a copy of the GNU General Public License
21// along with lognestmonster. If not, see <https://www.gnu.org/licenses/>.
22
23#ifndef __LOGNESTMONSTER__
24#define __LOGNESTMONSTER__ 1
25
26// SEMANTICS
27// internal definitions: lnm_lower_camel_case
28// public definitions: lnmUpperCamelCase
29
30// stdc inclusions
31
32#include <stdint.h>
33#include <stdlib.h>
34#include <string.h>
35#include <sys/time.h>
36
37
38// Base definitions
39
40enum lnmVerbosityLevel {lnmInfo, lnmDebug, lnmVerbose, lnmVeryVerbose, lnmWarning, lnmError};
41typedef uint8_t * lnmItem;
42typedef uint8_t * lnmQueue;
43
44
45// Pushable structure
46
47typedef struct {
48 uint16_t length;
49 lnmItem * pushed;
50} lnm_pushable;
51
52lnm_pushable * lnm_new_pushable() {
53 lnm_pushable * new_pushable = malloc(sizeof(lnm_pushable));
54 new_pushable->length = 0;
55 new_pushable->pushed = malloc(0);
56 return new_pushable;
57}
58
59void lnm_pushable_push(lnm_pushable * pushable, lnmItem item) {
60 if (pushable->length+1 >= 65535) {
61 printf("lognestmonster (lnm_pushable_push): pushable reached cap length 65535. exiting...\n");
62 exit(1);
63 }
64 pushable->pushed = realloc(pushable->pushed, sizeof(lnmItem)*(pushable->length+1)); // reallocate with size: length+1
65 pushable->pushed[pushable->length] = item;
66 pushable->length += 1;
67}
68
69int lnm_pushable_indexof(lnm_pushable * pushable, lnmItem item) {
70 int len = pushable->length;
71 for (int iter = 0; iter<len; iter++) {
72 if (item == pushable->pushed[iter]) return iter;
73 }
74 return -1;
75}
76
77void lnm_pushable_remove(lnm_pushable * pushable, int index) {
78 if (index>=pushable->length || index < 0) {
79 printf("lognestmonster (lnm_pushable_remove): attempt to remove index out of pushable bounds. exiting...\n");
80 exit(1);
81 }
82 lnmItem * new_pushed = malloc(sizeof(lnmItem)*(pushable->length-1)); // map array excluding index
83 for (int iter = 0; iter<index; iter++) {
84 new_pushed[iter] = pushable->pushed[iter];
85 }
86 for (int iter = index+1; iter<pushable->length; iter++) {
87 new_pushed[iter-1] = pushable->pushed[iter];
88 }
89 free(pushable->pushed);
90 pushable->length--;
91 pushable->pushed = new_pushed;
92}
93
94
95// Statement and event structure definitions
96
97typedef struct {
98 uint8_t type:1; // Used internally; 0 = statement, 1 = event
99 lnm_pushable * pushed; // array of memory locations for lnm_log_event and lnm_log_statement structs
100} lnm_log_event;
101
102typedef struct {
103 // word 1, 4 bytes data 4 bytes padding
104 uint8_t type:1; // Used internally; 0 = statement, 1 = event
105 uint8_t verbosity:3; // lnmVerbosityLevel, 0-5
106 uint8_t tag_size; // character length of the tag
107 uint16_t message_size; // character length of the message
108
109 // word 2, 8 bytes data
110 uint64_t timestamp; // 64-bit millisecond timestamp
111
112 // word 3, 8 bytes data
113 char * log; // tag string + message string
114} lnm_log_statement;
115
116
117// Queue structure definition
118
119typedef struct {
120 char * name;
121 char * out_path;
122 uint64_t timestamp;
123 lnm_pushable * pushed;
124} lnm_queue;
125
126
127// Library utilities
128
129unsigned long lnm_getus(void) {
130 struct timeval current_time;
131 gettimeofday(&current_time, NULL);
132 unsigned long ms = (current_time.tv_sec*1000000+current_time.tv_usec);
133 return ms;
134}
135
136unsigned long lnm_getms(void) {
137 return lnm_getus()/1000;
138}
139
140
141int lnm_isstatement(lnmItem item) {
142 lnm_log_statement * s = (lnm_log_statement *)item;
143 return !s->type;
144}
145
146
147// Item registry utils
148
149lnm_pushable * registered_queues;
150lnm_pushable * registered_items;
151
152int lnm_treescan_match(lnmItem toscan, lnmItem match) {
153
154}
155
156void lnm_registry_update(void) { // scan each registered item
157
158}
159
160
161// Core library
162
163lnmQueue lnmQueueInit(char * name, char * out_path) {
164 if (registered_queues == NULL) {
165 registered_queues = lnm_new_pushable();
166 }
167 if (registered_items == NULL) {
168 registered_items = lnm_new_pushable();
169 }
170
171 lnm_queue * new_queue = malloc(sizeof(lnm_queue));
172 new_queue->name = malloc(strlen(name)+1);
173 new_queue->out_path = malloc(strlen(out_path)+1);
174 strcpy(new_queue->name, name);
175 strcpy(new_queue->out_path, out_path);
176 new_queue->pushed = lnm_new_pushable();
177
178 lnm_pushable_push(registered_queues, (lnmQueue)new_queue);
179 return (lnmQueue)new_queue;
180}
181
182lnmQueue lnmQueueByName(char * name) {
183 if (registered_queues == NULL) {
184 printf("lognestmonster (lnmQueueByName): queue registry is nonexistant. exiting...\n");
185 exit(1);
186 }
187 if (registered_queues->length == 0) {
188 printf("lognestmonster (lnmQueueByName): queue registry is empty. exiting...\n");
189 exit(1);
190 }
191 for (int iter = 0; iter<registered_queues->length; iter++) {
192 lnm_queue * iterqueue = (lnm_queue *)registered_queues->pushed[iter];
193 if (strcmp(iterqueue->name, name)==0) {
194 return (lnmQueue)iterqueue;
195 }
196 }
197 printf("lognestmonster (lnmQueueByName): queue not found in registry. exiting...\n");
198 exit(1);
199}
200
201
202lnmItem lnmStatement(uint8_t verbosity, char * tag, char * message) {
203 lnm_log_statement * new_statement = malloc(sizeof(lnm_log_statement));
204 new_statement->type = 0;
205 new_statement->verbosity = verbosity;
206 new_statement->timestamp = lnm_getms();
207 int tlen = strlen(tag);
208 if (tlen > 255 || tlen < 0) {
209 printf("lognestmonster (lnmStatement): tag length %i is longer than the cap 255 characters. exiting...\n", tlen);
210 exit(1);
211 }
212 int mlen = strlen(message);
213 if (mlen > 65535 || mlen < 0) {
214 printf("lognestmonster (lnmStatement): message length %i is longer than the cap 65535 characters. exiting...\n", mlen);
215 exit(1);
216 }
217 new_statement->tag_size = tlen;
218 new_statement->message_size = mlen;
219 new_statement->log = malloc(tlen+mlen+1);
220 strcpy(new_statement->log, tag);
221 strcat(new_statement->log, message);
222 return (lnmItem)new_statement;
223}
224
225
226lnmItem lnmEvent(void) {
227 lnm_log_event * new_event = malloc(sizeof(lnm_log_event));
228 new_event->type = 1;
229 new_event->pushed = lnm_new_pushable();
230 return (lnmItem)new_event;
231}
232
233void lnmEventPush(lnmItem event, lnmItem item) {
234 if (event == item) {
235 printf("lognestmonster (lnmEventPush): attempt to push event to self. exiting...\n");
236 exit(1);
237 }
238 lnm_log_event * event_t = (lnm_log_event *)event;
239 if (event_t->type != 1) {
240 printf("lognestmonster (lnmEventPush): cannot cast non-event to event type. exiting...\n");
241 exit(1);
242 }
243 lnm_pushable_push(event_t->pushed, item);
244}
245
246void lnmEventPushS(lnmItem event, uint8_t verbosity, char * tag, char * message) {
247 lnmItem statement = lnmStatement(verbosity, tag, message);
248 lnmEventPush(event, statement);
249}
250
251lnmItem lnmEventI(lnmItem item) {
252 lnmItem event = lnmEvent();
253 lnmEventPush(event, item);
254 return event;
255}
256
257lnmItem lnmEventS(uint8_t verbosity, char * tag, char * message) {
258 lnmItem statement = lnmStatement(verbosity, tag, message);
259 return lnmEventI(statement);
260}
261
262
263void lnm_debug_tabs(int count) {
264 for (int i = 0; i < count; i++) {
265 printf(" ");
266 }
267}
268
269void lnm_debug_parse(lnmItem item, int tabcount) {
270 if (lnm_isstatement(item)) {
271 lnm_log_statement * statement = (lnm_log_statement *) item;
272 lnm_debug_tabs(tabcount);
273 printf("Statement {\n");
274
275 lnm_debug_tabs(tabcount+1);
276 char * verbosity;
277 switch (statement->verbosity) {
278 case 0:
279 verbosity = "INFO";
280 break;
281 case 1:
282 verbosity = "DEBUG";
283 break;
284 case 2:
285 verbosity = "VERBOSE";
286 break;
287 case 3:
288 verbosity = "VERYVERBOSE";
289 break;
290 case 4:
291 verbosity = "WARNING";
292 break;
293 case 5:
294 verbosity = "ERROR";
295 break;
296 }
297 printf("Verbosity %s\n", verbosity);
298
299 lnm_debug_tabs(tabcount+1);
300 printf("Timestamp %ld\n", statement->timestamp);
301
302 lnm_debug_tabs(tabcount+1);
303 char tag[statement->tag_size+1];
304 strncpy(tag, statement->log, statement->tag_size);
305 tag[statement->tag_size] = '\0';
306 printf("Tag (%i) %s\n", statement->tag_size, tag);
307
308 lnm_debug_tabs(tabcount+1);
309 char message[statement->message_size+1];
310 strncpy(message, statement->log+statement->tag_size, statement->message_size);
311 message[statement->message_size] = '\0';
312 printf("Message (%i) %s\n", statement->message_size, message);
313
314 lnm_debug_tabs(tabcount);
315 printf("}\n");
316 } else if (!lnm_isstatement(item)) {
317 lnm_log_event * event = (lnm_log_event *) item;
318 lnm_debug_tabs(tabcount);
319 printf("Event (%i) [\n", event->pushed->length);
320 for (int i = 0; i < event->pushed->length; i++) {
321 lnmItem item = event->pushed->pushed[i];
322 lnm_debug_parse(item, tabcount + 1);
323 }
324 lnm_debug_tabs(tabcount);
325 printf("]\n");
326 } else {
327 printf("lognestmonster (lnm_debug_parse): unknown item type. exiting...\n");
328 exit(1);
329 }
330}
331
332#endif
333