X-Git-Url: http://git.iain.cx/?a=blobdiff_plain;f=io.cpp;h=dd2641cf068c693ef4aba9ac42a5246bae2a9991;hb=62f28c55d444d846579159133dbe091809a2c08b;hp=48611b09c57f4719e0d4f43d9f415afa60b0c3c5;hpb=ee9a86c8408feaf173733aea12a80211e5d74483;p=nssm.git diff --git a/io.cpp b/io.cpp index 48611b0..dd2641c 100644 --- a/io.cpp +++ b/io.cpp @@ -3,6 +3,8 @@ #define COMPLAINED_READ (1 << 0) #define COMPLAINED_WRITE (1 << 1) #define COMPLAINED_ROTATE (1 << 2) +#define TIMESTAMP_FORMAT "%04u-%02u-%02u %02u:%02u:%02u.%03u: " +#define TIMESTAMP_LEN 25 static int dup_handle(HANDLE source_handle, HANDLE *dest_handle_ptr, TCHAR *source_description, TCHAR *dest_description, unsigned long flags) { if (! dest_handle_ptr) return 1; @@ -23,7 +25,7 @@ static int dup_handle(HANDLE source_handle, HANDLE *dest_handle_ptr, TCHAR *sour pipe_handle: stdout of application write_handle: to file */ -static HANDLE create_logging_thread(TCHAR *service_name, TCHAR *path, unsigned long sharing, unsigned long disposition, unsigned long flags, HANDLE *read_handle_ptr, HANDLE *pipe_handle_ptr, HANDLE *write_handle_ptr, unsigned long rotate_bytes_low, unsigned long rotate_bytes_high, unsigned long rotate_delay, unsigned long *tid_ptr, unsigned long *rotate_online, bool copy_and_truncate) { +static HANDLE create_logging_thread(TCHAR *service_name, TCHAR *path, unsigned long sharing, unsigned long disposition, unsigned long flags, HANDLE *read_handle_ptr, HANDLE *pipe_handle_ptr, HANDLE *write_handle_ptr, unsigned long rotate_bytes_low, unsigned long rotate_bytes_high, unsigned long rotate_delay, unsigned long *tid_ptr, unsigned long *rotate_online, bool timestamp_log, bool copy_and_truncate) { *tid_ptr = 0; /* Pipe between application's stdout/stderr and our logging handle. */ @@ -58,6 +60,8 @@ static HANDLE create_logging_thread(TCHAR *service_name, TCHAR *path, unsigned l logger->write_handle = *write_handle_ptr; logger->size = (__int64) size.QuadPart; logger->tid_ptr = tid_ptr; + logger->timestamp_log = timestamp_log; + logger->line_length = 0; logger->rotate_online = rotate_online; logger->rotate_delay = rotate_delay; logger->copy_and_truncate = copy_and_truncate; @@ -323,7 +327,7 @@ int get_output_handles(nssm_service_t *service, STARTUPINFO *si) { if (service->use_stdout_pipe) { service->stdout_pipe = si->hStdOutput = 0; - service->stdout_thread = create_logging_thread(service->name, service->stdout_path, service->stdout_sharing, service->stdout_disposition, service->stdout_flags, &service->stdout_pipe, &service->stdout_si, &stdout_handle, service->rotate_bytes_low, service->rotate_bytes_high, service->rotate_delay, &service->stdout_tid, &service->rotate_stdout_online, service->stdout_copy_and_truncate); + service->stdout_thread = create_logging_thread(service->name, service->stdout_path, service->stdout_sharing, service->stdout_disposition, service->stdout_flags, &service->stdout_pipe, &service->stdout_si, &stdout_handle, service->rotate_bytes_low, service->rotate_bytes_high, service->rotate_delay, &service->stdout_tid, &service->rotate_stdout_online, service->timestamp_log, service->stdout_copy_and_truncate); if (! service->stdout_thread) { CloseHandle(service->stdout_pipe); CloseHandle(service->stdout_si); @@ -360,7 +364,7 @@ int get_output_handles(nssm_service_t *service, STARTUPINFO *si) { if (service->use_stderr_pipe) { service->stderr_pipe = si->hStdError = 0; - service->stderr_thread = create_logging_thread(service->name, service->stderr_path, service->stderr_sharing, service->stderr_disposition, service->stderr_flags, &service->stderr_pipe, &service->stderr_si, &stderr_handle, service->rotate_bytes_low, service->rotate_bytes_high, service->rotate_delay, &service->stderr_tid, &service->rotate_stderr_online, service->stderr_copy_and_truncate); + service->stderr_thread = create_logging_thread(service->name, service->stderr_path, service->stderr_sharing, service->stderr_disposition, service->stderr_flags, &service->stderr_pipe, &service->stderr_si, &stderr_handle, service->rotate_bytes_low, service->rotate_bytes_high, service->rotate_delay, &service->stderr_tid, &service->rotate_stderr_online, service->timestamp_log, service->stderr_copy_and_truncate); if (! service->stderr_thread) { CloseHandle(service->stderr_pipe); CloseHandle(service->stderr_si); @@ -533,6 +537,69 @@ complain_write: return ret; } +/* Note that the timestamp is created in UTF-8. */ +static inline int write_timestamp(logger_t *logger, unsigned long charsize, unsigned long *out, int *complained) { + char timestamp[TIMESTAMP_LEN + 1]; + + SYSTEMTIME now; + GetSystemTime(&now); + _snprintf_s(timestamp, _countof(timestamp), _TRUNCATE, TIMESTAMP_FORMAT, now.wYear, now.wMonth, now.wDay, now.wHour, now.wMinute, now.wSecond, now.wMilliseconds); + + if (charsize == sizeof(char)) return try_write(logger, (void *) timestamp, TIMESTAMP_LEN, out, complained); + + wchar_t *utf16; + unsigned long utf16len; + if (to_utf16(timestamp, &utf16, &utf16len)) return -1; + int ret = try_write(logger, (void *) *utf16, utf16len * sizeof(wchar_t), out, complained); + HeapFree(GetProcessHeap(), 0, utf16); + return ret; +} + +static int write_with_timestamp(logger_t *logger, void *address, unsigned long bufsize, unsigned long *out, int *complained, unsigned long charsize) { + if (logger->timestamp_log) { + unsigned long log_out; + int log_complained; + unsigned long timestamp_out = 0; + int timestamp_complained; + if (! logger->line_length) { + write_timestamp(logger, charsize, ×tamp_out, ×tamp_complained); + logger->line_length += (__int64) timestamp_out; + *out += timestamp_out; + *complained |= timestamp_complained; + } + + unsigned long i; + void *line = address; + unsigned long offset = 0; + int ret; + for (i = 0; i < bufsize; i++) { + if (((char *) address)[i] == '\n') { + ret = try_write(logger, line, i - offset + 1, &log_out, &log_complained); + line = (void *) ((char *) line + i - offset + 1); + logger->line_length = 0LL; + *out += log_out; + *complained |= log_complained; + offset = i + 1; + if (offset < bufsize) { + write_timestamp(logger, charsize, ×tamp_out, ×tamp_complained); + logger->line_length += (__int64) timestamp_out; + *out += timestamp_out; + *complained |= timestamp_complained; + } + } + } + + if (offset < bufsize) { + ret = try_write(logger, line, bufsize - offset, &log_out, &log_complained); + *out += log_out; + *complained |= log_complained; + } + + return ret; + } + else return try_write(logger, address, bufsize, out, complained); +} + /* Wrapper to be called in a new thread for logging. */ unsigned long WINAPI log_and_rotate(void *arg) { logger_t *logger = (logger_t *) arg; @@ -650,9 +717,9 @@ unsigned long WINAPI log_and_rotate(void *arg) { } } + if (! size || logger->timestamp_log) if (! charsize) charsize = guess_charsize(address, in); if (! size) { /* Write a BOM to the new file. */ - if (! charsize) charsize = guess_charsize(address, in); if (charsize == sizeof(wchar_t)) write_bom(logger, &out); size += (__int64) out; } @@ -660,7 +727,7 @@ unsigned long WINAPI log_and_rotate(void *arg) { /* Write the data, if any. */ if (! in) continue; - ret = try_write(logger, address, in, &out, &complained); + ret = write_with_timestamp(logger, address, in, &out, &complained, charsize); size += (__int64) out; if (ret < 0) { close_handle(&logger->read_handle);