1 mike 1.1 /*
2 **==============================================================================
3 **
4 ** Open Management Infrastructure (OMI)
5 **
6 ** Copyright (c) Microsoft Corporation
7 **
8 ** Licensed under the Apache License, Version 2.0 (the "License"); you may not
9 ** use this file except in compliance with the License. You may obtain a copy
10 ** of the License at
11 **
12 ** http://www.apache.org/licenses/LICENSE-2.0
13 **
14 ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
16 ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
17 ** MERCHANTABLITY OR NON-INFRINGEMENT.
18 **
19 ** See the Apache 2 License for the specific language governing permissions
20 ** and limitations under the License.
21 **
22 mike 1.1 **==============================================================================
23 */
24
|
25 krisbash 1.3 #include "logbase.h"
|
26 mike 1.1
27 #if defined(CONFIG_OS_WINDOWS)
28 # include <windows.h>
29 # include <time.h>
30 #else
31 # include <unistd.h>
32 # include <sys/time.h>
33 # include <sys/types.h>
34 # include <time.h>
|
35 krisbash 1.3 # if defined(linux)
36 # include <syscall.h>
37 # endif
|
38 mike 1.1 #endif
39
|
40 krisbash 1.3 // Disable this by default as it slows down performance (by about 12% in tests with 2 threads)
41 // it can be re-activated if intermingled traces become too difficult to read and it doesnt affect repro in that particular case
42 // Note though that It will not prevent the case of different executables logging to the same files
43 //#define LOGC_USES_LOCK
44
45 #include <pal/strings.h>
46 #include <pal/format.h>
47 #include <pal/process.h>
48 #include <pal/thread.h>
49 #ifdef LOGC_USES_LOCK
50 #include <pal/lock.h>
51 #endif
|
52 mike 1.1
53 /*
54 **==============================================================================
55 **
56 ** Local definitions:
57 **
58 **==============================================================================
59 */
60
61 static FILE* _os;
|
62 krisbash 1.3 #ifdef LOGC_USES_LOCK
63 static Lock _logLock;
64 #endif
65 static Log_Level _level = OMI_WARNING;
66
|
67 mike 1.1
68 static const char* _levelStrings[] =
69 {
70 "FATAL",
71 "ERROR",
72 "WARNING",
73 "INFO",
74 "DEBUG",
|
75 krisbash 1.3 "VERBOSE",
|
76 mike 1.1 };
77
|
78 krisbash 1.3 PAL_INLINE PAL_Boolean _ShouldLog(int level)
79 {
80 if (level > Log_GetLevel())
81 return PAL_FALSE;
82 else
83 return PAL_TRUE;
84 }
85
86 #define FMTSIZE 1024
87 void FilePutLog(
88 int priority,
89 int eventId,
90 const char * file,
91 int line,
92 const PAL_Char* format,
93 ...)
94 {
95 if ((unsigned int)priority > OMI_VERBOSE)
96 return;
97
98 if (_ShouldLog(priority))
99 krisbash 1.3 {
100 TChar fmt[FMTSIZE];
101 va_list ap;
102
103 Stprintf(fmt, FMTSIZE, PAL_T("EventId=%d Priority=%s "), eventId, _levelStrings[priority]);
104 Tcslcat(fmt, format, FMTSIZE);
105
106 va_start(ap, format);
107 Log_VPut((Log_Level)priority, file, line, fmt, ap);
108 va_end(ap);
109 }
110 }
|
111 mike 1.1
|
112 krisbash 1.3 int _GetCurrentTimeInUsec(MI_Uint64* usec)
|
113 mike 1.1 {
114 #if defined(CONFIG_OS_WINDOWS)
115 FILETIME ft;
116 ULARGE_INTEGER tmp;
117
118 GetSystemTimeAsFileTime(&ft);
119 tmp.u.LowPart = ft.dwLowDateTime;
120 tmp.u.HighPart = ft.dwHighDateTime;
121 tmp.QuadPart -= 0X19DB1DED53E8000;
122 *usec = tmp.QuadPart / (UINT64)10;
123
124 return 0;
125 #else
126 struct timeval tv;
127 struct timezone tz;
128 memset(&tv, 0, sizeof(tv));
129 memset(&tz, 0, sizeof(tz));
130
131 if (gettimeofday(&tv, &tz) != 0)
132 return -1;
133
134 mike 1.1 *usec = (MI_Uint64)tv.tv_sec * (MI_Uint64)1000000 + (MI_Uint64)tv.tv_usec;
135 return 0;
136 #endif
137 }
138
139 #define TIMESTAMP_SIZE 128
140
|
141 krisbash 1.3 static int _GetTimeStamp(_Pre_writable_size_(TIMESTAMP_SIZE) char buf[TIMESTAMP_SIZE])
|
142 mike 1.1 {
|
143 krisbash 1.3 #if defined(CONFIG_OS_WINDOWS)
144 {
145 SYSTEMTIME systime;
146 GetLocalTime(&systime);
147
148 sprintf_s(
149 buf,
150 TIMESTAMP_SIZE,
151 "%02u/%02u/%02u %02u:%02u:%02u",
152 systime.wYear,
153 systime.wMonth,
154 systime.wDay,
155 systime.wHour,
156 systime.wMinute,
157 systime.wSecond);
158 }
159 #else
|
160 mike 1.1 MI_Uint64 usec;
161
162 if (_GetCurrentTimeInUsec(&usec) != 0)
163 {
164 buf[0] = '\0';
165 return -1;
166 }
167
168 {
169 time_t t = usec / 1000000;
170 struct tm tm;
171 localtime_r(&t, &tm);
172 sprintf(
173 buf,
174 "%02u/%02u/%02u %02u:%02u:%02u",
175 tm.tm_year + 1900,
176 tm.tm_mon + 1,
177 tm.tm_mday,
178 tm.tm_hour,
179 tm.tm_min,
180 tm.tm_sec);
181 mike 1.1 }
182 #endif
183
184 return 0;
185 }
186
187 static void _PutHeader(
188 FILE* os,
189 const char* file,
190 unsigned int line,
191 Log_Level level)
192 {
193 char buf[TIMESTAMP_SIZE];
194
195 _GetTimeStamp(buf);
|
196 krisbash 1.3 Ftprintf(os, ZT("%s "), scs(buf));
197 Ftprintf(os, ZT("[%u,%lu] "), (unsigned int)Process_ID(), (unsigned long)Thread_TID());
198 Ftprintf(os, ZT("%s: "), scs(_levelStrings[(int)level]));
199
200 if (file)
201 Ftprintf(os, ZT("%s(%u): "), scs(file), line);
|
202 mike 1.1 }
203
204 /*
205 **==============================================================================
206 **
207 ** Public definitions:
208 **
209 **==============================================================================
210 */
211
|
212 krisbash 1.3 MI_Boolean Log_IsOpen()
213 {
214 return (_os != NULL);
215 }
216
217 #if defined(CONFIG_OS_WINDOWS)
218 #include <share.h>
219 #endif
220
|
221 mike 1.1 MI_Result Log_Open(
|
222 krisbash 1.3 const ZChar* path)
|
223 mike 1.1 {
224 if (!path || _os)
225 return MI_RESULT_FAILED;
226
|
227 krisbash 1.3 #ifdef LOGC_USES_LOCK
228 Lock_Init(&_logLock);
229 #endif
230
|
231 mike 1.1 #if defined(CONFIG_OS_WINDOWS)
232 # if (MI_CHAR_TYPE == 1)
233 {
|
234 krisbash 1.3 _os = _fsopen(path, "a", _SH_DENYWR);
235 if (_os == NULL)
|
236 mike 1.1 return MI_RESULT_FAILED;
237
238 return MI_RESULT_OK;
239 }
240 # else
241 {
|
242 krisbash 1.3 _os = _wfsopen(path, L"a", _SH_DENYWR);
243 if (_os == NULL)
|
244 mike 1.1 return MI_RESULT_FAILED;
245
246 return MI_RESULT_OK;
247 }
248 # endif
249 #else
250 # if (MI_CHAR_TYPE == 1)
251 {
252 _os = fopen(path, "a");
|
253 krisbash 1.3
|
254 mike 1.1 if (!_os)
255 return MI_RESULT_FAILED;
256
257 return MI_RESULT_OK;
258 }
259 # else
260 {
|
261 krisbash 1.3 char path7[PAL_MAX_PATH_SIZE];
262 if (StrWcslcpy(path7, path, PAL_MAX_PATH_SIZE) >= PAL_MAX_PATH_SIZE)
|
263 mike 1.1 return MI_RESULT_FAILED;
264
|
265 krisbash 1.3 _os = fopen(path7, "a");
|
266 mike 1.1
267 if (!_os)
268 {
269 return MI_RESULT_FAILED;
270 }
271
272 return MI_RESULT_OK;
273 }
274 # endif
275 #endif
276 }
277
278 MI_Result Log_OpenFD(
279 int fd)
280 {
281 #if defined(CONFIG_OS_WINDOWS)
282 MI_UNUSED(fd);
283 return MI_RESULT_FAILED;
284 #else
285 if (fd < 0 || _os)
286 return MI_RESULT_FAILED;
287 mike 1.1
288 _os = fdopen(fd, "a");
289 if (!_os)
290 return MI_RESULT_FAILED;
291
292 return MI_RESULT_OK;
293
294 #endif
295 }
296
297 MI_Result Log_OpenStdErr()
298 {
299 _os = stderr;
300 return MI_RESULT_OK;
301 }
302
|
303 krisbash 1.3 MI_Boolean Log_IsRoutedToStdErr()
304 {
305 return (_os == stderr);
306 }
307
|
308 mike 1.1 void Log_Close()
309 {
310 if (_os && _os != stderr)
311 {
312 fclose(_os);
313 _os = NULL;
314 }
315 }
316
317 void Log_SetLevel(
318 Log_Level level)
319 {
320 _level = level;
321 }
322
323 Log_Level Log_GetLevel()
324 {
325 return _level;
326 }
327
|
328 krisbash 1.3 int Log_SetLevelFromString(_In_z_ const char* level)
|
329 mike 1.1 {
330 size_t i;
331
332 for (i = 0; i < sizeof(_levelStrings) / sizeof(_levelStrings[0]); i++)
333 {
|
334 krisbash 1.3 char buf[12];
335 size_t size;
336 const char* str = Uint32ToStr(buf, (MI_Uint32)i, &size);
|
337 mike 1.1
338 if (Strcasecmp(level, _levelStrings[i]) == 0 ||
|
339 krisbash 1.3 (str && Strcasecmp(level, str) == 0))
|
340 mike 1.1 {
341 _level = (Log_Level)i;
342 return 0;
343 }
344 }
345
346 return -1;
347 }
348
|
349 krisbash 1.3 int Log_SetLevelFromPalCharString(_In_z_ const PAL_Char* level)
350 {
351 if(level && (Tcslen(level) < MAX_LOG_LEVEL_STRING_LENGTH))
352 {
353 char buf[MAX_LOG_LEVEL_STRING_LENGTH];
354 #if defined(CONFIG_ENABLE_WCHAR)
355 StrWcslcpy(buf, level, MAX_LOG_LEVEL_STRING_LENGTH);
356 #else
357 Strlcpy(buf, level, MAX_LOG_LEVEL_STRING_LENGTH);
358 #endif
359 if(Log_SetLevelFromString(buf) != 0)
360 {
361 return -1;
362 }
363
364 return 0;
365 }
366
367 return -1;
368 }
369
|
370 mike 1.1 const char* Log_GetLevelString(Log_Level level)
371 {
372 return _levelStrings[(int)level];
373 }
374
375 int Log_Put(
376 Log_Level level,
377 const char* file,
378 MI_Uint32 line,
|
379 krisbash 1.3 const ZChar* format,
|
380 mike 1.1 ...)
381 {
382 va_list ap;
383 memset(&ap, 0, sizeof(ap));
384
385 if (!_os || level > _level)
386 return 0;
387
|
388 krisbash 1.3 #ifdef LOGC_USES_LOCK
389 Lock_Acquire(&_logLock);
390 #endif
391
|
392 mike 1.1 _PutHeader(_os, file, line, level);
|
393 krisbash 1.3
|
394 mike 1.1 va_start(ap, format);
|
395 krisbash 1.3
396 Vftprintf(_os, format, ap);
397
398 va_end(ap);
399 Ftprintf(_os, ZT("\n"));
400
401 #ifdef LOGC_USES_LOCK
402 Lock_Release(&_logLock);
|
403 mike 1.1 #endif
404
405 return 1;
406 }
407
408 int Log_VPut(
409 Log_Level level,
410 const char* file,
411 MI_Uint32 line,
|
412 krisbash 1.3 const ZChar* format,
|
413 mike 1.1 va_list ap)
414 {
415 if (!_os || level > _level)
416 return 0;
417
|
418 krisbash 1.3 file = scs(file);
419
420 #ifdef LOGC_USES_LOCK
421 Lock_Acquire(&_logLock);
422 #endif
423
|
424 mike 1.1 _PutHeader(_os, file, line, level);
|
425 krisbash 1.3
426 Vftprintf(_os, format, ap);
427
428 Ftprintf(_os, ZT("\n"));
429 fflush(_os);
430
431 #ifdef LOGC_USES_LOCK
432 Lock_Release(&_logLock);
|
433 mike 1.1 #endif
434
435 return 1;
436 }
437
|
438 krisbash 1.3 #if defined(CONFIG_ENABLE_DEBUG)
439
|
440 mike 1.1 int __Log_Put1(
441 Log_Level level,
442 const char* file,
443 MI_Uint32 line)
444 {
445 if (!_os || level > _level)
446 return 0;
447
|
448 krisbash 1.3 #ifdef LOGC_USES_LOCK
449 Lock_Acquire(&_logLock);
450 #endif
|
451 mike 1.1 _PutHeader(_os, file, line, level);
|
452 krisbash 1.3 #ifdef LOGC_USES_LOCK
453 Lock_Release(&_logLock);
454 #endif
|
455 mike 1.1
456 return 1;
457 }
458
|
459 krisbash 1.3 #endif /* defined(CONFIG_ENABLE_DEBUG) */
460
|
461 mike 1.1 void __Log_Put2(
|
462 krisbash 1.3 const ZChar* format,
|
463 mike 1.1 ...)
464 {
465 va_list ap;
466 memset(&ap, 0, sizeof(ap));
467
|
468 krisbash 1.3 if (!_os)
|
469 mike 1.1 return;
470
|
471 krisbash 1.3 #ifdef LOGC_USES_LOCK
472 Lock_Acquire(&_logLock);
473 #endif
|
474 mike 1.1 va_start(ap, format);
|
475 krisbash 1.3
476 Vftprintf(_os, format, ap);
477
478 Ftprintf(_os, ZT("\n"));
479 fflush(_os);
480 #ifdef LOGC_USES_LOCK
481 Lock_Release(&_logLock);
|
482 mike 1.1 #endif
483 }
484
|
485 krisbash 1.3 void __Logf(const ZChar* format, ...)
486 {
487 va_list ap;
488 va_start(ap, format);
489 Log_VPut(OMI_FATAL, NULL, 0, format, ap);
490 va_end(ap);
491 }
492
493 void __Loge(const ZChar* format, ...)
494 {
495 va_list ap;
496 va_start(ap, format);
497 Log_VPut(OMI_ERROR, NULL, 0, format, ap);
498 va_end(ap);
499 }
500
501 void __Logw(const ZChar* format, ...)
502 {
503 va_list ap;
504 va_start(ap, format);
505 Log_VPut(OMI_WARNING, NULL, 0, format, ap);
506 krisbash 1.3 va_end(ap);
507 }
508
509 void __Logi(const ZChar* format, ...)
|
510 mike 1.1 {
511 va_list ap;
|
512 krisbash 1.3 va_start(ap, format);
513 Log_VPut(OMI_INFO, NULL, 0, format, ap);
514 va_end(ap);
515 }
|
516 mike 1.1
|
517 krisbash 1.3 void __Logd(const ZChar* format, ...)
518 {
519 va_list ap;
520 va_start(ap, format);
521 Log_VPut(OMI_DEBUG, NULL, 0, format, ap);
522 va_end(ap);
523 }
|
524 mike 1.1
|
525 krisbash 1.3 void __Logv(const ZChar* format, ...)
526 {
527 va_list ap;
|
528 mike 1.1 va_start(ap, format);
|
529 krisbash 1.3 Log_VPut(OMI_VERBOSE, NULL, 0, format, ap);
530 va_end(ap);
|
531 mike 1.1 }
|
532 krisbash 1.3
|