00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <errno.h>
00029 #include <string.h>
00030 #include <time.h>
00031 #include <sys/time.h>
00032 #include <stdarg.h>
00033 #include <unistd.h>
00034 #include <curl/curl.h>
00035 #include "testrunnerlite.h"
00036 #include "log.h"
00037
00038
00039
00040
00041
00042
00043
00044 extern struct timeval created;
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 LOCAL CURL *curl;
00066 LOCAL int do_syslog = 0;
00067
00068
00069
00070
00071
00072 const char *stream_names[] = {"EMERG", "ALERT", "CRITICAL", "ERROR",
00073 "WARNING", "NOTICE", "INFO", "DEBUG", "UNKNOWN" };
00074
00075
00076
00077 LOCAL int verbosity_level = 0;
00078
00079
00080
00081
00082
00083 LOCAL char *create_msg(const char *fmt, ...);
00084
00085 LOCAL char *vcreate_msg (const char *fmt, va_list ap);
00086
00087
00088
00089
00090
00091
00092
00097 LOCAL char *create_msg (const char *fmt, ...)
00098 {
00099 int written, size = 128;
00100 char *buff, *new_buff;
00101 va_list ap;
00102
00103 if ((buff = malloc(size)) == NULL) {
00104 fprintf (stderr, "%s: %s: malloc() failed can not log %s\n",
00105 PROGNAME, __FUNCTION__, strerror (errno));
00106 return NULL;
00107 }
00108 while (1) {
00109 va_start(ap, fmt);
00110 written = vsnprintf(buff, size, fmt, ap);
00111 va_end(ap);
00112 if (written > -1 && written < size)
00113 return buff;
00114 size = size * 2;
00115 if (size > LOG_MSG_MAX_SIZE) {
00116 fprintf (stderr,
00117 "%s: %s: log msg max size exceeded, "
00118 "msg omitted\n",
00119 PROGNAME, __FUNCTION__);
00120 free(buff);
00121 return NULL;
00122 }
00123 if ((new_buff = realloc (buff, size)) == NULL) {
00124 fprintf (stderr,
00125 "%s: %s: realloc() failed can not log %s\n",
00126 PROGNAME, __FUNCTION__, strerror (errno));
00127 free(buff);
00128 return NULL;
00129 } else {
00130 buff = new_buff;
00131 }
00132 }
00133
00134 return NULL;
00135 }
00136
00142 LOCAL char *vcreate_msg (const char *fmt, va_list ap)
00143 {
00144 int written, size = 128;
00145 char *buff, *new_buff;
00146
00147 if ((buff = malloc(size)) == NULL) {
00148 fprintf (stderr, "%s: %s: malloc() failed can not log %s\n",
00149 PROGNAME, __FUNCTION__, strerror (errno));
00150 return NULL;
00151 }
00152 while (1) {
00153 written = vsnprintf(buff, size, fmt, ap);
00154 if (written > -1 && written < size)
00155 return buff;
00156 size = size * 2;
00157 if (size > LOG_MSG_MAX_SIZE) {
00158 fprintf (stderr,
00159 "%s: %s: log msg max size exceeded, "
00160 "msg omitted\n",
00161 PROGNAME, __FUNCTION__);
00162 free(buff);
00163 return NULL;
00164 }
00165 if ((new_buff = realloc (buff, size)) == NULL) {
00166 fprintf (stderr,
00167 "%s: %s: realloc() failed can not log %s\n",
00168 PROGNAME, __FUNCTION__, strerror (errno));
00169 free(buff);
00170 return NULL;
00171 } else {
00172 buff = new_buff;
00173 }
00174 }
00175
00176 return NULL;
00177 }
00178
00179
00180
00181
00182
00192 void log_msg(int type, const char *file, const char *function,
00193 int lineno, char *format, ...)
00194 {
00195
00196 const char *stream_name;
00197 char timestamp[10];
00198 char *msg, *post_msg, *url_enc_msg,*module, *p;
00199 CURLcode res;
00200 struct tm *tm;
00201 time_t current_time;
00202 struct timeval now, diff;
00203 va_list args;
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221 unsigned int to_python_level[] = {50, 50, 50, 40,
00222 30, 20, 20, 10, 0};
00223
00224
00225 if (verbosity_level == LOG_LEVEL_SILENT ||
00226 (type == LOG_DEBUG && verbosity_level != LOG_LEVEL_DEBUG)) {
00227
00228 return;
00229 }
00230
00231
00232
00233
00234 if (type >= 0 && type < LOG_TYPES_COUNT) {
00235 stream_name = stream_names[type];
00236 } else {
00237
00238 stream_name = stream_names[LOG_TYPES_COUNT];
00239 }
00240
00241
00242 time (¤t_time);
00243 tm = localtime (¤t_time);
00244 strftime (timestamp, sizeof (timestamp), "%H:%M:%S", tm);
00245
00246 fprintf (stdout, "[%s] %s ", stream_name, timestamp);
00247 if (type == LOG_DEBUG)
00248 fprintf (stdout, "%s %s() %d ", file, function, lineno);
00249
00250
00251 va_start(args, format);
00252 msg = vcreate_msg (format, args);
00253 va_end(args);
00254
00255 if (!msg)
00256 return;
00257
00258 if (do_syslog)
00259 syslog (type, "%s", msg);
00260
00261 fprintf (stdout, "%s\n", msg);
00262 fflush (stdout);
00263
00264 if (!curl) {
00265 free (msg);
00266 return;
00267 }
00268
00269
00270
00271 gettimeofday (&now, NULL);
00272 timersub (&now, &created, &diff);
00273
00274
00275
00276 module = (char *)malloc (strlen (file) + 1);
00277 strcpy (module, file);
00278 if ((p = strchr (module, '.')))
00279 *p = '\0';
00280
00281
00282
00283
00284 url_enc_msg = curl_easy_escape (curl, msg, strlen(msg));
00285 post_msg = create_msg ("levelno=%d&"
00286 "name=testrunner-lite&"
00287 "levelname=%s&"
00288 "module=%s&"
00289 "filename=%s&"
00290 "pathname=testrunner-lite/src&"
00291 "funcName=%s&"
00292 "lineno=%d&"
00293 "msg=%s&"
00294 "exc_info=None&"
00295 "exc_text=None&"
00296 "args=()&"
00297 "threadName=None&"
00298 "thread=0.0&"
00299 "created=%d.%d&"
00300 "process=%d&"
00301 "relativeCreated=%d.%d&"
00302 "msecs=%d.%d&"
00303 ,to_python_level[type],
00304 stream_name,
00305 module,
00306 file,
00307 function,
00308 lineno,
00309 url_enc_msg,
00310 created.tv_sec,
00311 created.tv_usec,
00312 getpid(),
00313 diff.tv_sec,
00314 diff.tv_usec,
00315 diff.tv_usec ? diff.tv_usec/1000 : 0,
00316 diff.tv_usec % 1000);
00317 if (!post_msg) {
00318 curl_free (url_enc_msg);
00319 free (msg);
00320 return;
00321 }
00322
00323 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_msg);
00324
00325 res = curl_easy_perform(curl);
00326 if (res != CURLE_OK) {
00327 fprintf (stdout, "[ERROR] %s http logging failed: %s\n ",
00328 timestamp, curl_easy_strerror(res));
00329
00330 log_close();
00331 }
00332 curl_free (url_enc_msg);
00333 free (msg);
00334 free (post_msg);
00335 free (module);
00336
00337 return;
00338 }
00339
00340
00344 void log_init (testrunner_lite_options *opts) {
00345
00346 verbosity_level = 0;
00347
00348 if (opts->log_level > 0 && opts->log_level < LOG_LEVELS_COUNT) {
00349 verbosity_level = opts->log_level;
00350 LOG_MSG (LOG_INFO, "Verbosity level set to: %d\n",
00351 opts->log_level);
00352 } else {
00353 LOG_MSG (LOG_ERR,
00354 "Incorrect verbosity level %d, values [0..%d]\n",
00355 opts->log_level, LOG_LEVELS_COUNT - 1);
00356 }
00357 if (opts->remote_logger) {
00358 curl = curl_easy_init();
00359 curl_easy_setopt(curl,
00360 CURLOPT_URL,
00361 opts->remote_logger);
00362 if (opts->remote_logger_port)
00363 curl_easy_setopt(curl,
00364 CURLOPT_PORT,
00365 opts->remote_logger_port);
00366
00367 }
00368 if (opts->syslog_output) {
00369 openlog ("testrunner-lite", 0, LOG_LOCAL1);
00370 do_syslog = 1;
00371 }
00372 }
00373
00374
00377 void log_close () {
00378 fflush (stdout);
00379 if (curl) {
00380 curl_easy_cleanup(curl);
00381 curl = NULL;
00382 }
00383 if (do_syslog)
00384 closelog();
00385 }
00386
00387
00388
00389
00390
00391
00392
00393