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, *module, *p;
00199 CURLcode res;
00200 struct tm *tm;
00201 time_t current_time;
00202 struct timeval now, diff;
00203 va_list args;
00204 unsigned int to_python_level[] = {40,20,10,30,0};
00205
00206
00207 if (verbosity_level == LOG_LEVEL_SILENT ||
00208 (type == LOG_DEBUG && verbosity_level != LOG_LEVEL_DEBUG)) {
00209
00210 return;
00211 }
00212
00213
00214
00215
00216 if (type >= 0 && type < LOG_TYPES_COUNT) {
00217 stream_name = stream_names[type];
00218 } else {
00219
00220 stream_name = stream_names[LOG_TYPES_COUNT];
00221 }
00222
00223
00224 time (¤t_time);
00225 tm = localtime (¤t_time);
00226 strftime (timestamp, sizeof (timestamp), "%H:%M:%S", tm);
00227
00228 fprintf (stdout, "[%s] %s ", stream_name, timestamp);
00229 if (type == LOG_DEBUG)
00230 fprintf (stdout, "%s %s() %d ", file, function, lineno);
00231
00232
00233 va_start(args, format);
00234 msg = vcreate_msg (format, args);
00235 va_end(args);
00236
00237 if (!msg)
00238 return;
00239
00240 if (do_syslog)
00241 syslog (type, "%s", msg);
00242
00243 fprintf (stdout, "%s\n", msg);
00244
00245 if (!curl) {
00246 free (msg);
00247 return;
00248 }
00249
00250
00251
00252 gettimeofday (&now, NULL);
00253 timersub (&now, &created, &diff);
00254
00255
00256
00257 module = (char *)malloc (strlen (file) + 1);
00258 strcpy (module, file);
00259 if ((p = strchr (module, '.')))
00260 *p = '\0';
00261
00262
00263
00264 post_msg = create_msg ("levelno=%d&"
00265 "name=testrunner-lite&"
00266 "levelname=%s&"
00267 "module=%s&"
00268 "filename=%s&"
00269 "pathname=testrunner-lite/src&"
00270 "funcName=%s&"
00271 "lineno=%d&"
00272 "msg=%s&"
00273 "exc_info=None&"
00274 "exc_text=None&"
00275 "args=()&"
00276 "threadName=None&"
00277 "thread=0.0&"
00278 "created=%d.%d&"
00279 "process=%d&"
00280 "relativeCreated=%d.%d&"
00281 "msecs=%d.%d&"
00282 ,to_python_level[verbosity_level],
00283 stream_name,
00284 module,
00285 file,
00286 function,
00287 lineno,
00288 msg,
00289 created.tv_sec,
00290 created.tv_usec,
00291 getpid(),
00292 diff.tv_sec,
00293 diff.tv_usec,
00294 diff.tv_usec ? diff.tv_usec/1000 : 0,
00295 diff.tv_usec % 1000);
00296 if (!post_msg) {
00297 free (msg);
00298 return;
00299 }
00300
00301 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_msg);
00302
00303 res = curl_easy_perform(curl);
00304 if (res != CURLE_OK) {
00305 fprintf (stdout, "[ERROR] %s http logging failed: %s\n ",
00306 timestamp, curl_easy_strerror(res));
00307
00308 log_close();
00309 }
00310 free (msg);
00311 free (post_msg);
00312 free (module);
00313
00314 return;
00315 }
00316
00317
00321 void log_init (testrunner_lite_options *opts) {
00322
00323 verbosity_level = 0;
00324
00325 if (opts->log_level > 0 && opts->log_level < LOG_LEVELS_COUNT) {
00326 verbosity_level = opts->log_level;
00327 LOG_MSG (LOG_INFO, "Verbosity level set to: %d\n",
00328 opts->log_level);
00329 } else {
00330 LOG_MSG (LOG_ERR,
00331 "Incorrect verbosity level %d, values [0..%d]\n",
00332 opts->log_level, LOG_LEVELS_COUNT - 1);
00333 }
00334 if (opts->remote_logger) {
00335 curl = curl_easy_init();
00336 curl_easy_setopt(curl,
00337 CURLOPT_URL,
00338 opts->remote_logger);
00339 if (opts->remote_logger_port)
00340 curl_easy_setopt(curl,
00341 CURLOPT_PORT,
00342 opts->remote_logger_port);
00343
00344 }
00345 if (opts->syslog_output) {
00346 openlog ("testrunner-lite", 0, LOG_LOCAL1);
00347 do_syslog = 1;
00348 }
00349 }
00350
00351
00354 void log_close () {
00355 fflush (stdout);
00356 if (curl) {
00357 curl_easy_cleanup(curl);
00358 curl = NULL;
00359 }
00360 if (do_syslog)
00361 closelog();
00362 }
00363
00364
00365
00366
00367
00368
00369
00370