14#include <TraceLoggingProvider.h>
17TRACELOGGING_DEFINE_PROVIDER(
19 TRACE_DEFAULT_PROVIDER_NAME,
20 TRACE_DEFAULT_PROVIDER_GUID);
23static volatile LONG s_trace_ref = 0;
26static etw_provider_t *s_etw_handle = NULL;
112 default:
return LOG_DEBUG;
119#define FALLBACK_NAME "unknown"
134 len = GetModuleFileNameA(NULL, buf, (DWORD)buf_size);
135 if (len == 0 || len >= (DWORD)buf_size)
140 sep = strrchr(buf,
'\\');
143 sep = strrchr(buf,
'/');
145 return sep ? sep + 1 : buf;
161 len = readlink(
"/proc/self/exe", buf, buf_size - 1);
168 slash = strrchr(buf,
'/');
169 return slash ? slash + 1 : buf;
199#define LOCK_TIMEOUT_MS 100
214 if ((LONG)(GetTickCount() - deadline) >= 0)
222 struct timespec abs_timeout;
223 clock_gettime(CLOCK_REALTIME, &abs_timeout);
225 if (abs_timeout.tv_nsec >= 1000000000L)
227 abs_timeout.tv_sec += 1;
228 abs_timeout.tv_nsec -= 1000000000L;
230 return (pthread_rwlock_timedrdlock(&handle->
config_rwlock, &abs_timeout) == 0) ? 0 : -1;
265 return _strdup(base);
272 int id_len = snprintf(NULL, 0,
"%" PRId64, identifier);
273 size_t base_len = strlen(base);
275 size_t total = base_len + 1 + (size_t)id_len + 1;
277 result = (
char *)malloc(total);
282 snprintf(result, total,
"%s-%" PRId64, base, identifier);
292 const char *effective_name;
300 svc = _strdup(effective_name);
314 handle->service_name = svc;
323 if (InterlockedIncrement(&s_trace_ref) == 1)
325 s_etw_handle = etw_provider_init(s_trace_provider);
326 if (s_etw_handle == NULL)
328 InterlockedDecrement(&s_trace_ref);
329 free(handle->service_name);
416#define MAX_BODY (TRACE_MESSAGE_MAX_BYTES - 1)
426 while (pos > 0 && ((
unsigned char)s[pos] & 0xC0) == 0x80)
440 return etw_provider_write(s_etw_handle, to_etw_level(level),
441 handle->service_name, msg);
457 return (
int)msg_level <= (int)threshold;
461#define STDERR_TS_BUF_SIZE 24
471 static const char lc_table[] = {
'C',
'E',
'W',
'I',
'V'};
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);
485 clock_gettime(CLOCK_REALTIME, &tsp);
486 gmtime_r(&tsp.tv_sec, &tm_val);
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
501 lc = ((int)level < (int)
TRACE_LV_NONE) ? lc_table[(
int)level] :
'V';
502 fprintf(stderr,
"%s %c %s\n", ts, lc, msg);
534 return (os_result != 0 || file_result != 0) ? -1 : 0;
545 if (handle == NULL || message == NULL)
562 len = strlen(message);
567 memcpy(buf, message, safe_len);
568 buf[safe_len] =
'\0';
584 if (handle == NULL || format == NULL)
600 va_start(args, format);
601 vsnprintf(buf,
sizeof(buf), format, args);
613#define ELLIPSIS_LEN 3
622 const void *data,
size_t size,
const char *label)
625 const unsigned char *bytes = (
const unsigned char *)data;
628 size_t max_data_bytes;
632 if (handle == NULL || data == NULL || size == 0)
638 if (label != NULL && label[0] !=
'\0')
640 size_t lbl_len = strlen(label);
646 memcpy(buf, label, copy_len);
647 buf[copy_len] =
'\0';
650 memcpy(buf, label, lbl_len);
652 buf[lbl_len + 1] =
' ';
661 max_data_bytes = (remaining + 1) / 3;
663 if (size > max_data_bytes)
676 if (max_data_bytes == 0)
684 size = max_data_bytes;
688 for (i = 0; i < size; i++)
694 buf[pos++] =
hex_chars[(bytes[i] >> 4) & 0x0F];
713 const void *data,
size_t size,
const char *message)
717 if (handle == NULL || data == NULL || size == 0)
740 const void *data,
size_t size,
const char *format, ...)
745 if (handle == NULL || data == NULL || size == 0)
764 va_start(args, format);
765 vsnprintf(label,
sizeof(label), format, args);
798 if (InterlockedDecrement(&s_trace_ref) == 0)
800 etw_provider_dispose(s_etw_handle);
803 free(handle->service_name);
840 if (effective == NULL)
847 free(handle->service_name);
848 handle->service_name = effective;
891 enum trace_level level,
size_t max_bytes,
int generations)
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 プロバイダを初期化する。
trace_level
アプリケーション共通トレースレベル。
@ TRACE_LV_CRITICAL
致命的エラー。
@ TRACE_LV_VERBOSE
詳細 (デバッグ)。
#define TRACE_DEFAULT_FILE_LEVEL
trace_init() が設定するファイルトレースのデフォルトレベル。
#define TRACE_UTIL_API
呼び出し規約マクロ。
struct trace_provider trace_provider_t
トレースプロバイダハンドル (不透明型)。
#define TRACE_DEFAULT_STDERR_LEVEL
trace_init() が設定する stderr トレースのデフォルトレベル。
#define TRACE_DEFAULT_OS_LEVEL
trace_init() が設定する OS トレース (ETW / syslog) のデフォルトレベル。
#define TRACE_MESSAGE_MAX_BYTES
trace_write が受け付けるメッセージの最大バイト数 (null 終端含む)。