Updated plugin logging.

- The plugin now keeps the log file open for the duration of its lifetime.
 - This greatly improves the performace of the logging component, which was previously a significant bottleneck even at low logging verbosity.
 - The log now prints timestamps to the millisecond.
This commit is contained in:
Jason Watkins
2015-04-30 16:17:30 -07:00
parent aaf25a9933
commit d735e0f3ad
3 changed files with 33 additions and 18 deletions

View File

@@ -4,33 +4,42 @@
#include "XPLMUtilities.h" #include "XPLMUtilities.h"
#include <chrono>
#include <cstdarg> #include <cstdarg>
#include <cstdio> #include <cstdio>
#include <ctime> #include <ctime>
#include <iomanip>
#include <sstream>
// Implementation note: I initial wrote this class using C++ iostreams, but I couldn't find any // Implementation note: I initial wrote this class using C++ iostreams, but I couldn't find any
// way to implement FormatLine without adding in a call to sprintf. It therefore seems more // way to implement FormatLine without adding in a call to sprintf. It therefore seems more
// efficient to me to just use C-style IO and call std::fprintf directly. // efficient to me to just use C-style IO and call std::fprintf directly.
namespace XPC namespace XPC
{ {
static std::FILE* fd;
static void WriteTime(FILE* fd) static void WriteTime(FILE* fd)
{ {
std::time_t rawtime; using namespace std::chrono;
std::tm* timeinfo;
std::time(&rawtime);
timeinfo = std::localtime(&rawtime);
char buffer[16] = { 0 }; system_clock::time_point now = system_clock::now();
// Format is equivalent to [%F %T], but neither of those specifiers is std::time_t now_tt = system_clock::to_time_t(now);
// supported on Windows as of Visual Studio 13 system_clock::time_point now_sec = system_clock::from_time_t(now_tt);
std::strftime(buffer, 16, "[%H:%M:%S] ", timeinfo); milliseconds ms = duration_cast<milliseconds>(now - now_sec);
std::tm * tm = std::localtime(&now_tt);
std::stringstream ss;
ss << std::setfill('0') << "["
<< std::setw(2) << tm->tm_hour << ":"
<< std::setw(2) << tm->tm_min << ":"
<< std::setw(2) << tm->tm_sec << "."
<< std::setw(3) << ms.count() << "]";
std::fprintf(fd, buffer); std::fprintf(fd, ss.str().c_str());
} }
void Log::Initialize(std::string version) void Log::Initialize(std::string version)
{ {
std::FILE* fd = std::fopen("XPCLog.txt", "w"); fd = std::fopen("XPCLog.txt", "w");
if (fd != NULL) if (fd != NULL)
{ {
std::time_t rawtime; std::time_t rawtime;
@@ -39,8 +48,6 @@ namespace XPC
timeinfo = std::localtime(&rawtime); timeinfo = std::localtime(&rawtime);
char timeStr[16] = { 0 }; char timeStr[16] = { 0 };
// Format is equivalent to %F, but neither of those specifiers is
// supported on Windows as of Visual Studio 13
std::strftime(timeStr, 16, "%Y-%m-%d", timeinfo); std::strftime(timeStr, 16, "%Y-%m-%d", timeinfo);
std::fprintf(fd, "X-Plane Connect [Version %s]\n", version.c_str()); std::fprintf(fd, "X-Plane Connect [Version %s]\n", version.c_str());
@@ -62,6 +69,14 @@ namespace XPC
std::fprintf(fd, "Plugin Manager Version: %d\n", xplmVer); std::fprintf(fd, "Plugin Manager Version: %d\n", xplmVer);
std::fprintf(fd, "Host Application ID: %d\n", hostID); std::fprintf(fd, "Host Application ID: %d\n", hostID);
std::fprintf(fd, "Log file generated on %s.\n", timeStr); std::fprintf(fd, "Log file generated on %s.\n", timeStr);
std::fflush(fd);
}
}
void Log::Close()
{
if (fd)
{
std::fclose(fd); std::fclose(fd);
} }
} }
@@ -73,7 +88,6 @@ namespace XPC
void Log::WriteLine(const char* value) void Log::WriteLine(const char* value)
{ {
std::FILE* fd = std::fopen("XPCLog.txt", "a");
if (!fd) if (!fd)
{ {
return; return;
@@ -81,15 +95,13 @@ namespace XPC
WriteTime(fd); WriteTime(fd);
std::fprintf(fd, "%s\n", value); std::fprintf(fd, "%s\n", value);
std::fflush(fd);
std::fclose(fd);
} }
void Log::FormatLine(const char* format, ...) void Log::FormatLine(const char* format, ...)
{ {
va_list args; va_list args;
std::FILE* fd = std::fopen("XPCLog.txt", "a");
if (!fd) if (!fd)
{ {
return; return;
@@ -99,8 +111,7 @@ namespace XPC
WriteTime(fd); WriteTime(fd);
std::vfprintf(fd, format, args); std::vfprintf(fd, format, args);
std::fprintf(fd, "\n"); std::fprintf(fd, "\n");
std::fflush(fd);
std::fclose(fd);
va_end(args); va_end(args);
} }

View File

@@ -34,6 +34,9 @@ namespace XPC
/// writing header information to the log file. /// writing header information to the log file.
static void Initialize(std::string header); static void Initialize(std::string header);
/// Closes the log file.
static void Close();
/// Writes the C string pointed to by format, followed by a line /// Writes the C string pointed to by format, followed by a line
/// terminator to the XPC log file. If format contains format /// terminator to the XPC log file. If format contains format
/// specifiers, additional arguments following format will be formatted /// specifiers, additional arguments following format will be formatted

View File

@@ -119,6 +119,7 @@ PLUGIN_API void XPluginStop(void)
{ {
XPLMUnregisterFlightLoopCallback(XPCFlightLoopCallback, NULL); XPLMUnregisterFlightLoopCallback(XPCFlightLoopCallback, NULL);
XPC::Log::WriteLine("[EXEC] Plugin Shutdown"); XPC::Log::WriteLine("[EXEC] Plugin Shutdown");
XPC::Log::Close();
} }
PLUGIN_API void XPluginDisable(void) PLUGIN_API void XPluginDisable(void)