Document of c-modernization-kit (util) 1.0.0
Loading...
Searching...
No Matches
trace-provider.c
Go to the documentation of this file.
1#include <trace-util.h>
2#include <trace-file-util.h>
3#include <stdlib.h>
4#include <string.h>
5#include <stdarg.h>
6#include <stdio.h>
7#include <inttypes.h>
8
9/* ===== Windows: TraceLogging プロバイダ定義 ===== */
10
11#ifdef _WIN32
12
13#include <windows.h>
14#include <TraceLoggingProvider.h>
15
16/* trace-util が管理するデフォルトプロバイダ定義 */
17TRACELOGGING_DEFINE_PROVIDER(
18 s_trace_provider,
19 TRACE_DEFAULT_PROVIDER_NAME,
20 TRACE_DEFAULT_PROVIDER_GUID);
21
23static volatile LONG s_trace_ref = 0;
24
26static etw_provider_t *s_etw_handle = NULL;
27
28#else /* !_WIN32 */
29#include <time.h>
30#include <pthread.h>
31#endif /* _WIN32 */
32
37{
39 int64_t identifier;
40
41#ifdef _WIN32
43 char *service_name;
44#else /* !_WIN32 */
47#endif /* _WIN32 */
48
51
54
57
60
62 volatile int running;
63
64#ifdef _WIN32
67 SRWLOCK config_rwlock;
68#else /* !_WIN32 */
70 pthread_rwlock_t config_rwlock;
75#endif /* _WIN32 */
76};
77
78#ifdef _WIN32
79
83static int to_etw_level(enum trace_level lv)
84{
85 switch (lv)
86 {
87 case TRACE_LV_CRITICAL: return 1;
88 case TRACE_LV_ERROR: return 2;
89 case TRACE_LV_WARNING: return 3;
90 case TRACE_LV_INFO: return 4;
91 default: return 5;
92 }
93}
94
95#else /* !_WIN32 */
96
97#include <syslog.h>
98
102static int to_syslog_level(enum trace_level lv)
103{
104 switch (lv)
105 {
106 case TRACE_LV_CRITICAL: return LOG_CRIT;
107 case TRACE_LV_ERROR: return LOG_ERR;
108 case TRACE_LV_WARNING: return LOG_WARNING;
109 case TRACE_LV_INFO: return LOG_INFO;
110 case TRACE_LV_VERBOSE: return LOG_DEBUG;
111 case TRACE_LV_NONE: /* fall through */
112 default: return LOG_DEBUG;
113 }
114}
115
116#endif /* _WIN32 */
117
119#define FALLBACK_NAME "unknown"
120
121#ifdef _WIN32
122
129static const char *get_process_basename(char *buf, size_t buf_size)
130{
131 DWORD len;
132 const char *sep;
133
134 len = GetModuleFileNameA(NULL, buf, (DWORD)buf_size);
135 if (len == 0 || len >= (DWORD)buf_size)
136 {
137 return FALLBACK_NAME;
138 }
139
140 sep = strrchr(buf, '\\');
141 if (sep == NULL)
142 {
143 sep = strrchr(buf, '/');
144 }
145 return sep ? sep + 1 : buf;
146}
147#else /* !_WIN32 */
148#include <unistd.h>
149
156static const char *get_process_basename(char *buf, size_t buf_size)
157{
158 ssize_t len;
159 const char *slash;
160
161 len = readlink("/proc/self/exe", buf, buf_size - 1);
162 if (len <= 0)
163 {
164 return FALLBACK_NAME;
165 }
166 buf[len] = '\0';
167
168 slash = strrchr(buf, '/');
169 return slash ? slash + 1 : buf;
170}
171#endif /* _WIN32 */
172
178{
179#ifdef _WIN32
180 AcquireSRWLockExclusive(&handle->config_rwlock);
181#else /* !_WIN32 */
182 pthread_rwlock_wrlock(&handle->config_rwlock);
183#endif /* _WIN32 */
184}
185
190{
191#ifdef _WIN32
192 ReleaseSRWLockExclusive(&handle->config_rwlock);
193#else /* !_WIN32 */
194 pthread_rwlock_unlock(&handle->config_rwlock);
195#endif /* _WIN32 */
196}
197
199#define LOCK_TIMEOUT_MS 100
200
208{
209#ifdef _WIN32
210 /* SRWLOCK には timed 取得 API がないため spin + TryAcquireSRWLockShared で代替する */
211 DWORD deadline = GetTickCount() + (DWORD)LOCK_TIMEOUT_MS;
212 while (!TryAcquireSRWLockShared(&handle->config_rwlock))
213 {
214 if ((LONG)(GetTickCount() - deadline) >= 0)
215 {
216 return -1;
217 }
218 SwitchToThread();
219 }
220 return 0;
221#else /* !_WIN32 */
222 struct timespec abs_timeout;
223 clock_gettime(CLOCK_REALTIME, &abs_timeout);
224 abs_timeout.tv_nsec += (long)LOCK_TIMEOUT_MS * 1000000L;
225 if (abs_timeout.tv_nsec >= 1000000000L)
226 {
227 abs_timeout.tv_sec += 1;
228 abs_timeout.tv_nsec -= 1000000000L;
229 }
230 return (pthread_rwlock_timedrdlock(&handle->config_rwlock, &abs_timeout) == 0) ? 0 : -1;
231#endif /* _WIN32 */
232}
233
238{
239#ifdef _WIN32
240 ReleaseSRWLockShared(&handle->config_rwlock);
241#else /* !_WIN32 */
242 pthread_rwlock_unlock(&handle->config_rwlock);
243#endif /* _WIN32 */
244}
245
254static char *build_effective_name(const char *name, int64_t identifier)
255{
256 char path_buf[256];
257 const char *base;
258 char *result;
259
260 base = (name != NULL) ? name : get_process_basename(path_buf, sizeof(path_buf));
261
262 if (identifier == 0)
263 {
264#ifdef _WIN32
265 return _strdup(base);
266#else
267 return strdup(base);
268#endif
269 }
270
271 {
272 int id_len = snprintf(NULL, 0, "%" PRId64, identifier);
273 size_t base_len = strlen(base);
274 /* "<base>-<identifier>\0" */
275 size_t total = base_len + 1 /* '-' */ + (size_t)id_len + 1;
276
277 result = (char *)malloc(total);
278 if (result == NULL)
279 {
280 return NULL;
281 }
282 snprintf(result, total, "%s-%" PRId64, base, identifier);
283 return result;
284 }
285}
286
289{
290 trace_provider_t *handle;
291 char path_buf[256];
292 const char *effective_name;
293
294 effective_name = get_process_basename(path_buf, sizeof(path_buf));
295
296#ifdef _WIN32
297 {
298 char *svc;
299
300 svc = _strdup(effective_name);
301 if (svc == NULL)
302 {
303 return NULL;
304 }
305
306 handle = (trace_provider_t *)malloc(sizeof(trace_provider_t));
307 if (handle == NULL)
308 {
309 free(svc);
310 return NULL;
311 }
312
313 handle->identifier = 0;
314 handle->service_name = svc;
317 handle->file_handle = NULL;
319 handle->running = 0;
320
321 InitializeSRWLock(&handle->config_rwlock);
322
323 if (InterlockedIncrement(&s_trace_ref) == 1)
324 {
325 s_etw_handle = etw_provider_init(s_trace_provider);
326 if (s_etw_handle == NULL)
327 {
328 InterlockedDecrement(&s_trace_ref);
329 free(handle->service_name);
330 free(handle);
331 return NULL;
332 }
333 }
334 }
335#else /* !_WIN32 */
336 {
338
339 sp = syslog_provider_init(effective_name, LOG_USER);
340 if (sp == NULL)
341 {
342 return NULL;
343 }
344
345 handle = (trace_provider_t *)malloc(sizeof(trace_provider_t));
346 if (handle == NULL)
347 {
349 return NULL;
350 }
351
352 handle->identifier = 0;
353 handle->syslog_handle = sp;
356 handle->file_handle = NULL;
358 handle->running = 0;
359
360 if (pthread_rwlock_init(&handle->config_rwlock, NULL) != 0)
361 {
363 free(handle);
364 return NULL;
365 }
366 handle->config_rwlock_initialized = 1;
367 }
368#endif /* _WIN32 */
369
370 return handle;
371}
372
375{
376 if (handle == NULL)
377 {
378 return -1;
379 }
380
381 config_lock_exclusive(handle);
382
383 if (handle->running)
384 {
386 return 0;
387 }
388
389 handle->running = 1;
391 return 0;
392}
393
396{
397 if (handle == NULL)
398 {
399 return -1;
400 }
401
402 config_lock_exclusive(handle);
403
404 if (!handle->running)
405 {
407 return 0;
408 }
409
410 handle->running = 0;
412 return 0;
413}
414
416#define MAX_BODY (TRACE_MESSAGE_MAX_BYTES - 1)
417
423static size_t utf8_safe_truncate(const char *s, size_t pos)
424{
425 /* pos が文字列長以下なら調整不要 */
426 while (pos > 0 && ((unsigned char)s[pos] & 0xC0) == 0x80)
427 {
428 /* 継続バイト (10xxxxxx) を跨がないよう先頭バイトまで戻る */
429 pos--;
430 }
431 return pos;
432}
433
437static int write_to_provider(trace_provider_t *handle, enum trace_level level, const char *msg)
438{
439#ifdef _WIN32
440 return etw_provider_write(s_etw_handle, to_etw_level(level),
441 handle->service_name, msg);
442#else /* !_WIN32 */
443 return syslog_provider_write(handle->syslog_handle, to_syslog_level(level), msg);
444#endif /* _WIN32 */
445}
446
451static int should_output(enum trace_level msg_level, enum trace_level threshold)
452{
453 if (threshold == TRACE_LV_NONE)
454 {
455 return 0;
456 }
457 return (int)msg_level <= (int)threshold;
458}
459
461#define STDERR_TS_BUF_SIZE 24
462
468static void write_stderr_entry(enum trace_level level, const char *msg)
469{
470 char ts[STDERR_TS_BUF_SIZE];
471 static const char lc_table[] = {'C', 'E', 'W', 'I', 'V'};
472 char lc;
473
474#ifdef _WIN32
475 SYSTEMTIME st;
476 GetSystemTime(&st);
477 snprintf(ts, sizeof(ts),
478 "%04d-%02d-%02d %02d:%02d:%02d.%03d",
479 (int)st.wYear, (int)st.wMonth, (int)st.wDay,
480 (int)st.wHour, (int)st.wMinute, (int)st.wSecond,
481 (int)st.wMilliseconds);
482#else /* !_WIN32 */
483 struct timespec tsp;
484 struct tm tm_val;
485 clock_gettime(CLOCK_REALTIME, &tsp);
486 gmtime_r(&tsp.tv_sec, &tm_val);
487 /* -Wformat-truncation の抑制: gmtime_r() が返す tm 構造体の各フィールドは POSIX で
488 * 範囲が保証されており (tm_mon: 0-11, tm_mday: 1-31 等)、出力は常に 23 文字以内に
489 * 収まる。GCC は int 型の理論上の最大範囲 [-2147483648, 2147483647] を使って静的
490 * 検証するため false positive が発生する。pragma はその誤報を局所的に抑制する。 */
491#pragma GCC diagnostic push
492#pragma GCC diagnostic ignored "-Wformat-truncation"
493 snprintf(ts, sizeof(ts),
494 "%04d-%02d-%02d %02d:%02d:%02d.%03d",
495 tm_val.tm_year + 1900, tm_val.tm_mon + 1, tm_val.tm_mday,
496 tm_val.tm_hour, tm_val.tm_min, tm_val.tm_sec,
497 (int)(tsp.tv_nsec / 1000000));
498#pragma GCC diagnostic pop
499#endif /* _WIN32 */
500
501 lc = ((int)level < (int)TRACE_LV_NONE) ? lc_table[(int)level] : 'V';
502 fprintf(stderr, "%s %c %s\n", ts, lc, msg);
503}
504
511static int write_dual(trace_provider_t *handle, enum trace_level level, const char *msg)
512{
513 int os_result = 0;
514 int file_result = 0;
515
516 /* OS トレース出力 */
517 if (should_output(level, handle->os_level))
518 {
519 os_result = write_to_provider(handle, level, msg);
520 }
521
522 /* ファイルトレース出力 */
523 if (handle->file_handle != NULL && should_output(level, handle->file_level))
524 {
525 file_result = trace_file_provider_write(handle->file_handle, (int)level, msg);
526 }
527
528 /* stderr 出力 */
529 if (should_output(level, handle->stderr_level))
530 {
531 write_stderr_entry(level, msg);
532 }
533
534 return (os_result != 0 || file_result != 0) ? -1 : 0;
535}
536
538 trace_write(trace_provider_t *handle, enum trace_level level, const char *message)
539{
540 const char *msg;
541 char buf[TRACE_MESSAGE_MAX_BYTES];
542 size_t len;
543 int ret;
544
545 if (handle == NULL || message == NULL)
546 {
547 return 0;
548 }
549
550 if (config_lock_shared_timed(handle) != 0)
551 {
552 return -1;
553 }
554
555 if (!handle->running)
556 {
557 config_unlock_shared(handle);
558 return -1;
559 }
560
561 msg = message;
562 len = strlen(message);
563
564 if (len > MAX_BODY)
565 {
566 size_t safe_len = utf8_safe_truncate(message, MAX_BODY);
567 memcpy(buf, message, safe_len);
568 buf[safe_len] = '\0';
569 msg = buf;
570 }
571
572 ret = write_dual(handle, level, msg);
573 config_unlock_shared(handle);
574 return ret;
575}
576
578 trace_writef(trace_provider_t *handle, enum trace_level level, const char *format, ...)
579{
580 va_list args;
581 char buf[TRACE_MESSAGE_MAX_BYTES];
582 int ret;
583
584 if (handle == NULL || format == NULL)
585 {
586 return 0;
587 }
588
589 if (config_lock_shared_timed(handle) != 0)
590 {
591 return -1;
592 }
593
594 if (!handle->running)
595 {
596 config_unlock_shared(handle);
597 return -1;
598 }
599
600 va_start(args, format);
601 vsnprintf(buf, sizeof(buf), format, args);
602 va_end(args);
603
604 ret = write_dual(handle, level, buf);
605 config_unlock_shared(handle);
606 return ret;
607}
608
610static const char hex_chars[] = "0123456789ABCDEF";
611
613#define ELLIPSIS_LEN 3
614
621static int hex_write_impl(trace_provider_t *handle, enum trace_level level,
622 const void *data, size_t size, const char *label)
623{
624 char buf[TRACE_MESSAGE_MAX_BYTES];
625 const unsigned char *bytes = (const unsigned char *)data;
626 size_t pos = 0;
627 size_t remaining;
628 size_t max_data_bytes;
629 int truncated = 0;
630 size_t i;
631
632 if (handle == NULL || data == NULL || size == 0)
633 {
634 return 0;
635 }
636
637 /* ラベル付与 */
638 if (label != NULL && label[0] != '\0')
639 {
640 size_t lbl_len = strlen(label);
641 /* ラベル + ": " がバッファに収まるか検査 */
642 if (lbl_len + 2 >= MAX_BODY)
643 {
644 /* ラベルだけで上限超過 — ラベルのみ出力 */
645 size_t copy_len = lbl_len < MAX_BODY ? lbl_len : MAX_BODY;
646 memcpy(buf, label, copy_len);
647 buf[copy_len] = '\0';
648 return write_dual(handle, level, buf);
649 }
650 memcpy(buf, label, lbl_len);
651 buf[lbl_len] = ':';
652 buf[lbl_len + 1] = ' ';
653 pos = lbl_len + 2;
654 }
655
656 /* HEX データ出力可能な残りバイト数 */
657 remaining = MAX_BODY - pos;
658
659 /* 全データが収まるか判定:
660 N バイト → 3*N - 1 文字 (最終バイトはスペースなし) */
661 max_data_bytes = (remaining + 1) / 3;
662
663 if (size > max_data_bytes)
664 {
665 /* 切り詰めが必要: "..." (3文字) の分を確保
666 各バイト "XX " (3文字) + "..." (3文字) → M*3 + 3 ≤ remaining
667 M ≤ (remaining - 3) / 3 */
668 truncated = 1;
669 if (remaining < ELLIPSIS_LEN)
670 {
671 /* "..." すら入らない */
672 buf[pos] = '\0';
673 return write_dual(handle, level, buf);
674 }
675 max_data_bytes = (remaining - ELLIPSIS_LEN) / 3;
676 if (max_data_bytes == 0)
677 {
678 /* HEX 1 バイトも入らない — "..." のみ */
679 memcpy(buf + pos, "...", ELLIPSIS_LEN);
680 pos += ELLIPSIS_LEN;
681 buf[pos] = '\0';
682 return write_dual(handle, level, buf);
683 }
684 size = max_data_bytes;
685 }
686
687 /* HEX 文字列を構築 */
688 for (i = 0; i < size; i++)
689 {
690 if (i > 0)
691 {
692 buf[pos++] = ' ';
693 }
694 buf[pos++] = hex_chars[(bytes[i] >> 4) & 0x0F];
695 buf[pos++] = hex_chars[bytes[i] & 0x0F];
696 }
697
698 /* 切り詰め時は "..." を付与 */
699 if (truncated)
700 {
701 buf[pos++] = ' ';
702 buf[pos++] = '.';
703 buf[pos++] = '.';
704 buf[pos++] = '.';
705 }
706 buf[pos] = '\0';
707
708 return write_dual(handle, level, buf);
709}
710
713 const void *data, size_t size, const char *message)
714{
715 int ret;
716
717 if (handle == NULL || data == NULL || size == 0)
718 {
719 return 0;
720 }
721
722 if (config_lock_shared_timed(handle) != 0)
723 {
724 return -1;
725 }
726
727 if (!handle->running)
728 {
729 config_unlock_shared(handle);
730 return -1;
731 }
732
733 ret = hex_write_impl(handle, level, data, size, message);
734 config_unlock_shared(handle);
735 return ret;
736}
737
740 const void *data, size_t size, const char *format, ...)
741{
742 char label[TRACE_MESSAGE_MAX_BYTES];
743 int ret;
744
745 if (handle == NULL || data == NULL || size == 0)
746 {
747 return 0;
748 }
749
750 if (config_lock_shared_timed(handle) != 0)
751 {
752 return -1;
753 }
754
755 if (!handle->running)
756 {
757 config_unlock_shared(handle);
758 return -1;
759 }
760
761 if (format != NULL)
762 {
763 va_list args;
764 va_start(args, format);
765 vsnprintf(label, sizeof(label), format, args);
766 va_end(args);
767 ret = hex_write_impl(handle, level, data, size, label);
768 }
769 else
770 {
771 ret = hex_write_impl(handle, level, data, size, NULL);
772 }
773
774 config_unlock_shared(handle);
775 return ret;
776}
777
780{
781 if (handle == NULL)
782 {
783 return;
784 }
785
786 /* 排他ロックで running=0 をセットし、進行中の write 完了を待つ。
787 * trace_stop 返却後は新規 write は -1 を返し、write 中の処理は完了している。 */
788 trace_stop(handle);
789
790 /* ファイルトレースプロバイダの解放 */
791 if (handle->file_handle != NULL)
792 {
794 handle->file_handle = NULL;
795 }
796
797#ifdef _WIN32
798 if (InterlockedDecrement(&s_trace_ref) == 0)
799 {
800 etw_provider_dispose(s_etw_handle);
801 s_etw_handle = NULL;
802 }
803 free(handle->service_name);
804 /* SRWLOCK は破棄関数不要 */
805#else /* !_WIN32 */
807 if (handle->config_rwlock_initialized)
808 {
809 pthread_rwlock_destroy(&handle->config_rwlock);
810 }
811#endif /* _WIN32 */
812
813 free(handle);
814}
815
817 trace_modify_name(trace_provider_t *handle, const char *name, int64_t identifier)
818{
819 char *effective;
820
821 if (handle == NULL)
822 {
823 return -1;
824 }
825
826 if (identifier < 0)
827 {
828 return -1;
829 }
830
831 config_lock_exclusive(handle);
832
833 if (handle->running)
834 {
836 return -1;
837 }
838
839 effective = build_effective_name(name, identifier);
840 if (effective == NULL)
841 {
843 return -1;
844 }
845
846#ifdef _WIN32
847 free(handle->service_name);
848 handle->service_name = effective;
849 handle->identifier = identifier;
851 return 0;
852#else /* !_WIN32 */
853 {
854 int rc = syslog_provider_rename(handle->syslog_handle, effective);
855 free(effective);
856 if (rc != 0)
857 {
859 return -1;
860 }
861 handle->identifier = identifier;
863 return 0;
864 }
865#endif /* _WIN32 */
866}
867
870{
871 if (handle == NULL)
872 {
873 return -1;
874 }
875
876 config_lock_exclusive(handle);
877
878 if (handle->running)
879 {
881 return -1;
882 }
883
884 handle->os_level = level;
886 return 0;
887}
888
890 trace_modify_filetrc(trace_provider_t *handle, const char *path,
891 enum trace_level level, size_t max_bytes, int generations)
892{
893 int result = 0;
894
895 if (handle == NULL)
896 {
897 return -1;
898 }
899
900 config_lock_exclusive(handle);
901
902 if (handle->running)
903 {
905 return -1;
906 }
907
908 /* 既存のファイルプロバイダを解放する */
909 if (handle->file_handle != NULL)
910 {
912 handle->file_handle = NULL;
913 }
914
915 handle->file_level = level;
916
917 /* path が NULL の場合はファイルトレースを無効化して終了 */
918 if (path != NULL)
919 {
920 /* 新しいファイルプロバイダを初期化する */
921 handle->file_handle = trace_file_provider_init(path, max_bytes, generations);
922 if (handle->file_handle == NULL)
923 {
924 result = -1;
925 }
926 }
927
929 return result;
930}
931
934{
935 if (handle == NULL)
936 {
937 return -1;
938 }
939
940 config_lock_exclusive(handle);
941
942 if (handle->running)
943 {
945 return -1;
946 }
947
948 handle->stderr_level = level;
950 return 0;
951}
952
955{
956 enum trace_level lv;
957
958 if (handle == NULL)
959 {
960 return TRACE_LV_NONE;
961 }
962 if (config_lock_shared_timed(handle) != 0)
963 {
964 return TRACE_LV_NONE;
965 }
966 lv = handle->os_level;
967 config_unlock_shared(handle);
968 return lv;
969}
970
973{
974 enum trace_level lv;
975
976 if (handle == NULL)
977 {
978 return TRACE_LV_NONE;
979 }
980 if (config_lock_shared_timed(handle) != 0)
981 {
982 return TRACE_LV_NONE;
983 }
984 lv = handle->file_level;
985 config_unlock_shared(handle);
986 return lv;
987}
988
991{
992 enum trace_level lv;
993
994 if (handle == NULL)
995 {
996 return TRACE_LV_NONE;
997 }
998 if (config_lock_shared_timed(handle) != 0)
999 {
1000 return TRACE_LV_NONE;
1001 }
1002 lv = handle->stderr_level;
1003 config_unlock_shared(handle);
1004 return lv;
1005}
トレースプロバイダハンドル構造体 (内部定義)。
int64_t identifier
アプリケーション管理識別番号 (診断用)。0 = 識別番号なし。
int _pad_end
パディング (構造体サイズを 8 バイト境界に揃える)。
int config_rwlock_initialized
config_rwlock が初期化済みかどうかのフラグ。
syslog_provider_t * syslog_handle
syslog プロバイダハンドル (Linux)。
enum trace_level stderr_level
stderr トレースのスレッショルドレベル。デフォルト: TRACE_LV_NONE。
enum trace_level os_level
OS トレース (ETW/syslog) のスレッショルドレベル。デフォルト: TRACE_LV_INFO。
enum trace_level file_level
ファイルトレースのスレッショルドレベル。デフォルト: TRACE_LV_ERROR。
trace_file_provider_t * file_handle
ファイルトレースプロバイダハンドル。NULL = ファイルトレース無効。
volatile int running
実行状態フラグ (0=停止中, 1=実行中)。
pthread_rwlock_t config_rwlock
読み書きロック。write 系は共有ロック、設定変更・stop・dispose は排他ロック。
ファイルベーストレースプロバイダライブラリ。
TRACE_FILE_UTIL_EXPORT int TRACE_FILE_UTIL_API trace_file_provider_write(trace_file_provider_t *handle, int level, const char *message)
ファイルへトレースメッセージを書き込む。
TRACE_FILE_UTIL_EXPORT trace_file_provider_t *TRACE_FILE_UTIL_API trace_file_provider_init(const char *path, size_t max_bytes, int generations)
ファイルトレースプロバイダを初期化する。
TRACE_FILE_UTIL_EXPORT void TRACE_FILE_UTIL_API trace_file_provider_dispose(trace_file_provider_t *handle)
ファイルトレースプロバイダを終了する。
struct trace_file_provider trace_file_provider_t
ファイルトレースプロバイダハンドル (不透明型)。
int TRACE_UTIL_API trace_start(trace_provider_t *handle)
トレースプロバイダを開始する。
static int hex_write_impl(trace_provider_t *handle, enum trace_level level, const void *data, size_t size, const char *label)
HEX ダンプ出力の内部実装。
int TRACE_UTIL_API trace_modify_ostrc(trace_provider_t *handle, enum trace_level level)
OS トレースのスレッショルドレベルを設定する。
#define FALLBACK_NAME
プロセス名取得失敗時のフォールバック名。
static void config_lock_exclusive(trace_provider_t *handle)
設定・状態変更用の排他ロックを取得する。 trace_start / trace_stop / trace_modify_* / trace_dispose で使用する。
static int write_dual(trace_provider_t *handle, enum trace_level level, const char *msg)
OS プロバイダとファイルプロバイダの両方へメッセージを書き込む。
enum trace_level TRACE_UTIL_API trace_get_stderrtrc(trace_provider_t *handle)
stderr トレースの現在のスレッショルドレベルを取得する。
int TRACE_UTIL_API trace_hex_write(trace_provider_t *handle, enum trace_level level, const void *data, size_t size, const char *message)
バイナリデータを HEX テキスト形式でトレースに書き込む。
#define STDERR_TS_BUF_SIZE
stderr タイムスタンプバッファサイズ ("YYYY-MM-DD HH:MM:SS.mmm\0" = 24)。
trace_provider_t *TRACE_UTIL_API trace_init(void)
トレースプロバイダを初期化する。
int TRACE_UTIL_API trace_hex_writef(trace_provider_t *handle, enum trace_level level, const void *data, size_t size, const char *format,...)
バイナリデータを HEX テキスト形式でトレースに書き込む (printf 形式ラベル)。
int TRACE_UTIL_API trace_modify_stderrtrc(trace_provider_t *handle, enum trace_level level)
stderr トレースのスレッショルドレベルを設定する。
int TRACE_UTIL_API trace_write(trace_provider_t *handle, enum trace_level level, const char *message)
トレースメッセージを書き込む。
#define ELLIPSIS_LEN
"..." サフィックスの長さ。
enum trace_level TRACE_UTIL_API trace_get_ostrc(trace_provider_t *handle)
OS トレースの現在のスレッショルドレベルを取得する。
static void config_unlock_exclusive(trace_provider_t *handle)
排他ロックを解放する。
static const char hex_chars[]
HEX 変換用テーブル。
static const char * get_process_basename(char *buf, size_t buf_size)
自プロセスの実行ファイル名 (ベースネーム) を取得する。
int TRACE_UTIL_API trace_modify_filetrc(trace_provider_t *handle, const char *path, enum trace_level level, size_t max_bytes, int generations)
ファイルトレースの出力先と設定を変更する。
int TRACE_UTIL_API trace_modify_name(trace_provider_t *handle, const char *name, int64_t identifier)
トレースプロバイダの識別名と識別番号を設定する。
static int config_lock_shared_timed(trace_provider_t *handle)
書き込み系 API 用の共有ロックをタイムアウト付きで取得する。 複数スレッドが同時に取得できる。 排他ロック保持中はブロックするが、LOCK_TIMEOUT_MS 経過で諦める。
enum trace_level TRACE_UTIL_API trace_get_filetrc(trace_provider_t *handle)
ファイルトレースの現在のスレッショルドレベルを取得する。
static size_t utf8_safe_truncate(const char *s, size_t pos)
UTF-8 安全な切り詰め位置を返す。
static int write_to_provider(trace_provider_t *handle, enum trace_level level, const char *msg)
下層プロバイダに文字列を書き込む (内部ヘルパー)。
int TRACE_UTIL_API trace_writef(trace_provider_t *handle, enum trace_level level, const char *format,...)
printf 形式でトレースメッセージを書き込む。
int TRACE_UTIL_API trace_stop(trace_provider_t *handle)
トレースプロバイダを停止する。
#define MAX_BODY
切り詰め後の本文最大バイト数 (null 終端を除く)。
static void write_stderr_entry(enum trace_level level, const char *msg)
stderr にタイムスタンプ + レベル文字 + メッセージを 1 行書き込む。
static void config_unlock_shared(trace_provider_t *handle)
共有ロックを解放する。
static int to_syslog_level(enum trace_level lv)
enum trace_level を syslog severity に変換する。
#define LOCK_TIMEOUT_MS
共有ロック取得のタイムアウト (ミリ秒)。
static char * build_effective_name(const char *name, int64_t identifier)
name と identifier から有効識別名 (effective name) を生成する。
void TRACE_UTIL_API trace_dispose(trace_provider_t *handle)
トレースプロバイダを終了し、リソースを解放する。
static int should_output(enum trace_level msg_level, enum trace_level threshold)
メッセージレベルがスレッショルド以内かを判定する。
struct syslog_provider syslog_provider_t
syslog プロバイダハンドル (不透明型)。
TRACE_SYSLOG_UTIL_EXPORT int TRACE_SYSLOG_UTIL_API syslog_provider_rename(syslog_provider_t *handle, const char *new_ident)
syslog プロバイダの識別子を変更する。
TRACE_SYSLOG_UTIL_EXPORT void TRACE_SYSLOG_UTIL_API syslog_provider_dispose(syslog_provider_t *handle)
syslog プロバイダを終了する。
TRACE_SYSLOG_UTIL_EXPORT int TRACE_SYSLOG_UTIL_API syslog_provider_write(syslog_provider_t *handle, int level, const char *message)
syslog へ UTF-8 メッセージを書き込む。
TRACE_SYSLOG_UTIL_EXPORT syslog_provider_t *TRACE_SYSLOG_UTIL_API syslog_provider_init(const char *ident, int facility)
syslog プロバイダを初期化する。
クロスプラットフォーム トレーシング API。
trace_level
アプリケーション共通トレースレベル。
Definition trace-util.h:204
@ TRACE_LV_ERROR
エラー。
Definition trace-util.h:206
@ TRACE_LV_WARNING
警告。
Definition trace-util.h:207
@ TRACE_LV_CRITICAL
致命的エラー。
Definition trace-util.h:205
@ TRACE_LV_VERBOSE
詳細 (デバッグ)。
Definition trace-util.h:209
@ TRACE_LV_INFO
情報。
Definition trace-util.h:208
@ TRACE_LV_NONE
出力しない。
Definition trace-util.h:210
#define TRACE_DEFAULT_FILE_LEVEL
trace_init() が設定するファイルトレースのデフォルトレベル。
Definition trace-util.h:229
#define TRACE_UTIL_API
呼び出し規約マクロ。
Definition trace-util.h:133
struct trace_provider trace_provider_t
トレースプロバイダハンドル (不透明型)。
Definition trace-util.h:243
#define TRACE_DEFAULT_STDERR_LEVEL
trace_init() が設定する stderr トレースのデフォルトレベル。
Definition trace-util.h:238
#define TRACE_DEFAULT_OS_LEVEL
trace_init() が設定する OS トレース (ETW / syslog) のデフォルトレベル。
Definition trace-util.h:221
#define TRACE_MESSAGE_MAX_BYTES
trace_write が受け付けるメッセージの最大バイト数 (null 終端含む)。
Definition trace-util.h:172