4 * @brief Implementation of logger_t.
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
33 #include <utils/allocator.h>
36 * Maximum length of al log entry (only used for logger_s.log)
40 typedef struct private_logger_t private_logger_t
;
43 * @brief The logger object.
45 struct private_logger_t
{
51 * Detail-level of logger.
59 * File to write log output to.
65 * Should a thread_id be included in the log?
69 /* private functions */
71 * Logs a message to the associated log file.
73 void (*log_to_file
) (private_logger_t
*this, char *format
, ...);
75 * Applies a prefix to string and stores it in buffer.
77 * @warning: buffer must be at least have MAX_LOG size.
79 void (*prepend_prefix
) (private_logger_t
*this, logger_level_t loglevel
, char *string
, char *buffer
);
83 * Implementation of private_logger_t.prepend_prefix.
85 static void prepend_prefix(private_logger_t
*this, logger_level_t loglevel
, char *string
, char *buffer
)
87 char log_type
, log_details
;
88 if (loglevel
& CONTROL
)
92 else if (loglevel
& ERROR
)
96 else if (loglevel
& RAW
)
100 else if (loglevel
& PRIVATE
)
109 if (loglevel
& (ALL
- MOST
))
113 else if (loglevel
& (MOST
- MORE
))
117 else if (loglevel
& MORE
)
127 if (this->log_thread_id
)
129 snprintf(buffer
, MAX_LOG
, "[%c%c] [%s] @%u %s", log_type
, log_details
, this->name
, (int)pthread_self(), string
);
133 snprintf(buffer
, MAX_LOG
, "[%c%c] [%s] %s", log_type
, log_details
, this->name
, string
);
139 * Implementation of logger_t.log.
141 * Yes, logg is wrong written :-).
143 static status_t
logg(private_logger_t
*this, logger_level_t loglevel
, char *format
, ...)
145 if ((this->level
& loglevel
) == loglevel
)
147 char buffer
[MAX_LOG
];
151 if (this->output
== NULL
)
154 this->prepend_prefix(this, loglevel
, format
, buffer
);
155 va_start(args
, format
);
156 vsyslog(LOG_INFO
, buffer
, args
);
162 this->prepend_prefix(this, loglevel
, format
, buffer
);
163 va_start(args
, format
);
164 this->log_to_file(this, buffer
, args
);
173 * Implementation of private_logger_t.log_to_file.
175 static void log_to_file(private_logger_t
*this,char *format
, ...)
177 char buffer
[MAX_LOG
];
180 current_time
= time(NULL
);
182 snprintf(buffer
, MAX_LOG
, "%s\n", format
);
183 va_start(args
, format
);
184 vfprintf(this->output
, buffer
, args
);
189 * Implementation of logger_t.log_bytes.
191 static status_t
log_bytes(private_logger_t
*this, logger_level_t loglevel
, char *label
, char *bytes
, size_t len
)
193 if ((this->level
& loglevel
) == loglevel
)
195 char buffer
[MAX_LOG
];
198 char *bytes_pos
, *bytes_roof
;
202 format
= "%s (%d bytes)";
203 this->prepend_prefix(this, loglevel
, format
, buffer
);
205 if (this->output
== NULL
)
207 syslog(LOG_INFO
, buffer
, label
, len
);
210 this->log_to_file(this, buffer
, label
, len
);
214 bytes_roof
= bytes
+ len
;
217 for (i
= 1; bytes_pos
< bytes_roof
; i
++)
219 static const char hexdig
[] = "0123456789ABCDEF";
220 *buffer_pos
++ = hexdig
[(*bytes_pos
>> 4) & 0xF];
221 *buffer_pos
++ = hexdig
[ *bytes_pos
& 0xF];
224 *buffer_pos
++ = '\0';
226 if (this->output
== NULL
)
228 syslog(LOG_INFO
, "| %s", buffer
);
232 this->log_to_file(this, "| %s", buffer
);
235 else if ((i
% 8) == 0)
241 else if ((i
% 4) == 0)
254 *buffer_pos
++ = '\0';
256 if (this->output
== NULL
)
258 syslog(LOG_INFO
, "| %s", buffer
);
262 this->log_to_file(this, "| %s", buffer
);
271 * Implementation of logger_t.log_chunk.
273 static status_t
log_chunk(logger_t
*this, logger_level_t loglevel
, char *label
, chunk_t
*chunk
)
275 this->log_bytes(this, loglevel
, label
, chunk
->ptr
, chunk
->len
);
281 * Implementation of logger_t.enable_level.
283 static status_t
enable_level(private_logger_t
*this, logger_level_t log_level
)
285 this->level
|= log_level
;
290 * Implementation of logger_t.disable_level.
292 static status_t
disable_level(private_logger_t
*this, logger_level_t log_level
)
294 this->level
&= ~log_level
;
299 * Implementation of logger_t.destroy.
301 static status_t
destroy(private_logger_t
*this)
303 allocator_free(this->name
);
304 allocator_free(this);
309 * Described in header.
311 logger_t
*logger_create(char *logger_name
, logger_level_t log_level
, bool log_thread_id
, FILE * output
)
313 private_logger_t
*this = allocator_alloc_thing(private_logger_t
);
320 if (logger_name
== NULL
)
325 this->public.log
= (status_t(*)(logger_t
*,logger_level_t
,char*,...))logg
;
326 this->public.log_bytes
= (status_t(*)(logger_t
*, logger_level_t
, char*,char*,size_t))log_bytes
;
327 this->public.log_chunk
= log_chunk
;
328 this->public.enable_level
= (status_t(*)(logger_t
*,logger_level_t
))enable_level
;
329 this->public.disable_level
= (status_t(*)(logger_t
*,logger_level_t
))disable_level
;
330 this->public.destroy
= (status_t(*)(logger_t
*))destroy
;
332 this->log_to_file
= log_to_file
;
333 this->prepend_prefix
= prepend_prefix
;
335 /* private variables */
336 this->level
= log_level
;
337 this->log_thread_id
= log_thread_id
;
338 this->name
= allocator_alloc(strlen(logger_name
) + 1);
339 if (this->name
== NULL
)
341 allocator_free(this);
344 strcpy(this->name
,logger_name
);
345 this->output
= output
;
350 openlog(DAEMON_NAME
, 0, LOG_DAEMON
);
353 return (logger_t
*)this;