Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Logging hook #225

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
118 changes: 60 additions & 58 deletions Source/KSCrash/Recording/Tools/KSLogger.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@
/** Where console logs will be written */
static char g_logFilename[1024];

/** Whether logs should be written to stdout */
static bool g_logToStdout = false;

/** Write a formatted string to the log.
*
* @param fmt The format string, followed by its arguments.
Expand Down Expand Up @@ -117,7 +120,10 @@ static void writeToLog(const char* const str)
pos += bytesWritten;
}
}
write(STDOUT_FILENO, str, strlen(str));
if(g_logToStdout)
{
write(STDOUT_FILENO, str, strlen(str));
}
}

static inline void writeFmtArgsToLog(const char* fmt, va_list args)
Expand Down Expand Up @@ -193,23 +199,28 @@ void writeToLog(const char* const str)
{
fprintf(g_file, "%s", str);
}
fprintf(stdout, "%s", str);
if(g_logToStdout)
{
fprintf(stdout, "%s", str);
}
}

static inline void writeFmtArgsToLog(const char* fmt, va_list args)
{
unlikely_if(g_file == NULL)
{
g_file = stdout;
}

if(fmt == NULL)
{
writeToLog("(null)");
}
else
{
vfprintf(g_file, fmt, args);
if(g_file != NULL)
{
vfprintf(g_file, fmt, args);
}
if(g_logToStdout)
{
vfprintf(stdout, fmt, args);
}
}
}

Expand Down Expand Up @@ -252,17 +263,37 @@ bool kslog_clearLogFile()
return kslog_setLogFilename(g_logFilename, true);
}

void kslog_setLogToStdout(bool enabled)
{
g_logToStdout = enabled;
}

// ===========================================================================
#pragma mark - C -
// ===========================================================================

void i_kslog_logCBasic(const char* const fmt, ...)
static KSLogFunction g_logCallback = NULL;

void kslog_setLogCallback(KSLogFunction function)
{
va_list args;
va_start(args,fmt);
g_logCallback = function;
}

static void i_kslog_log(const char* const level,
const char* const file,
const int line,
const char* const function,
const char* const fmt, va_list args)
{
if (g_logCallback)
{
g_logCallback(level, file, line, function, fmt, args);
}
if(level && file && line >= 0 && function)
{
writeFmtToLog("%s: %s (%u): %s: ", level, lastPathEntry(file), line, function);
}
writeFmtArgsToLog(fmt, args);
va_end(args);
writeToLog("\n");
flushLog();
}
Expand All @@ -273,13 +304,10 @@ void i_kslog_logC(const char* const level,
const char* const function,
const char* const fmt, ...)
{
writeFmtToLog("%s: %s (%u): %s: ", level, lastPathEntry(file), line, function);
va_list args;
va_start(args,fmt);
writeFmtArgsToLog(fmt, args);
i_kslog_log(level, file, line, function, fmt, args);
va_end(args);
writeToLog("\n");
flushLog();
}


Expand All @@ -290,59 +318,33 @@ void i_kslog_logC(const char* const level,
#if KSCRASH_HAS_OBJC
#include <CoreFoundation/CoreFoundation.h>

void i_kslog_logObjCBasic(CFStringRef fmt, ...)
{
if(fmt == NULL)
{
writeToLog("(null)");
return;
}

va_list args;
va_start(args,fmt);
CFStringRef entry = CFStringCreateWithFormatAndArguments(NULL, NULL, fmt, args);
va_end(args);

int bufferLength = (int)CFStringGetLength(entry) * 4 + 1;
char* stringBuffer = malloc((unsigned)bufferLength);
if(CFStringGetCString(entry, stringBuffer, (CFIndex)bufferLength, kCFStringEncodingUTF8))
{
writeToLog(stringBuffer);
}
else
{
writeToLog("Could not convert log string to UTF-8. No logging performed.");
}
writeToLog("\n");

free(stringBuffer);
CFRelease(entry);
}

void i_kslog_logObjC(const char* const level,
const char* const file,
const int line,
const char* const function,
CFStringRef fmt, ...)
{
CFStringRef logFmt = NULL;
if(fmt == NULL)
{
logFmt = CFStringCreateWithCString(NULL, "%s: %s (%u): %s: (null)", kCFStringEncodingUTF8);
i_kslog_logObjCBasic(logFmt, level, lastPathEntry(file), line, function);
i_kslog_logC(level, file, line, function, "(null)");
}
else
{
va_list args;
va_start(args,fmt);
CFStringRef entry = CFStringCreateWithFormatAndArguments(NULL, NULL, fmt, args);
va_end(args);

logFmt = CFStringCreateWithCString(NULL, "%s: %s (%u): %s: %@", kCFStringEncodingUTF8);
i_kslog_logObjCBasic(logFmt, level, lastPathEntry(file), line, function, entry);

CFRelease(entry);
int bufferLength = (int)CFStringGetLength(fmt) * 4 + 1;
char* stringBuffer = malloc((unsigned)bufferLength);
if(CFStringGetCString(fmt, stringBuffer, (CFIndex)bufferLength, kCFStringEncodingUTF8))
{
va_list args;
va_start(args,fmt);
i_kslog_log(level, file, line, function, stringBuffer, args);
va_end(args);
}
else
{
i_kslog_logC(level, file, line, function,
"Could not convert log string to UTF-8. No logging performed.");
}
free(stringBuffer);
}
CFRelease(logFmt);
}
#endif // KSCRASH_HAS_OBJC
47 changes: 35 additions & 12 deletions Source/KSCrash/Recording/Tools/KSLogger.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ extern "C" {


#include <stdbool.h>
#include <stdarg.h>


#ifdef __OBJC__
Expand All @@ -165,10 +166,7 @@ void i_kslog_logObjC(const char* level,
const char* function,
CFStringRef fmt, ...);

void i_kslog_logObjCBasic(CFStringRef fmt, ...);

#define i_KSLOG_FULL(LEVEL,FILE,LINE,FUNCTION,FMT,...) i_kslog_logObjC(LEVEL,FILE,LINE,FUNCTION,(__bridge CFStringRef)FMT,##__VA_ARGS__)
#define i_KSLOG_BASIC(FMT, ...) i_kslog_logObjCBasic((__bridge CFStringRef)FMT,##__VA_ARGS__)

#else // __OBJC__

Expand All @@ -178,10 +176,7 @@ void i_kslog_logC(const char* level,
const char* function,
const char* fmt, ...);

void i_kslog_logCBasic(const char* fmt, ...);

#define i_KSLOG_FULL i_kslog_logC
#define i_KSLOG_BASIC i_kslog_logCBasic

#endif // __OBJC__

Expand Down Expand Up @@ -244,6 +239,10 @@ void i_kslog_logCBasic(const char* fmt, ...);
FMT, \
##__VA_ARGS__)

#define a_KSLOG_BASIC(FMT, ...) \
i_KSLOG_FULL(0, 0, -1, 0, \
FMT, \
##__VA_ARGS__)


// ============================================================================
Expand All @@ -261,6 +260,30 @@ bool kslog_setLogFilename(const char* filename, bool overwrite);
/** Clear the log file. */
bool kslog_clearLogFile();

/** Set whether or not to log to stdout.
*
* @param enabled Whether or not stdout logging should be enabled.
*
* By default stdout logging is disabled.
*/
void kslog_setLogToStdout(bool enabled);

typedef void (*KSLogFunction)(const char* level, const char* file,
int line, const char* function,
const char* fmt, va_list args);

/** Set a function responsible for logging.
*
* When set, will deliver logging to this function
* in addition to file and stdout output (if enabled).
*
* WARNING: Only call async-safe functions from this function!
* DO NOT call Objective-C methods!!!
*
* @param function The function that should handle logging.
*/
void kslog_setLogCallback(KSLogFunction function);

/** Tests if the logger would print at the specified level.
*
* @param LEVEL The level to test for. One of:
Expand All @@ -281,7 +304,7 @@ bool kslog_clearLogFile();
* @param FMT The format specifier, followed by its arguments.
*/
#define KSLOG_ALWAYS(FMT, ...) a_KSLOG_FULL("FORCE", FMT, ##__VA_ARGS__)
#define KSLOGBASIC_ALWAYS(FMT, ...) i_KSLOG_BASIC(FMT, ##__VA_ARGS__)
#define KSLOGBASIC_ALWAYS(FMT, ...) a_KSLOG_BASIC(FMT, ##__VA_ARGS__)


/** Log an error.
Expand All @@ -291,7 +314,7 @@ bool kslog_clearLogFile();
*/
#if KSLOG_PRINTS_AT_LEVEL(KSLogger_Level_Error)
#define KSLOG_ERROR(FMT, ...) a_KSLOG_FULL("ERROR", FMT, ##__VA_ARGS__)
#define KSLOGBASIC_ERROR(FMT, ...) i_KSLOG_BASIC(FMT, ##__VA_ARGS__)
#define KSLOGBASIC_ERROR(FMT, ...) a_KSLOG_BASIC(FMT, ##__VA_ARGS__)
#else
#define KSLOG_ERROR(FMT, ...)
#define KSLOGBASIC_ERROR(FMT, ...)
Expand All @@ -304,7 +327,7 @@ bool kslog_clearLogFile();
*/
#if KSLOG_PRINTS_AT_LEVEL(KSLogger_Level_Warn)
#define KSLOG_WARN(FMT, ...) a_KSLOG_FULL("WARN ", FMT, ##__VA_ARGS__)
#define KSLOGBASIC_WARN(FMT, ...) i_KSLOG_BASIC(FMT, ##__VA_ARGS__)
#define KSLOGBASIC_WARN(FMT, ...) a_KSLOG_BASIC(FMT, ##__VA_ARGS__)
#else
#define KSLOG_WARN(FMT, ...)
#define KSLOGBASIC_WARN(FMT, ...)
Expand All @@ -317,7 +340,7 @@ bool kslog_clearLogFile();
*/
#if KSLOG_PRINTS_AT_LEVEL(KSLogger_Level_Info)
#define KSLOG_INFO(FMT, ...) a_KSLOG_FULL("INFO ", FMT, ##__VA_ARGS__)
#define KSLOGBASIC_INFO(FMT, ...) i_KSLOG_BASIC(FMT, ##__VA_ARGS__)
#define KSLOGBASIC_INFO(FMT, ...) a_KSLOG_BASIC(FMT, ##__VA_ARGS__)
#else
#define KSLOG_INFO(FMT, ...)
#define KSLOGBASIC_INFO(FMT, ...)
Expand All @@ -330,7 +353,7 @@ bool kslog_clearLogFile();
*/
#if KSLOG_PRINTS_AT_LEVEL(KSLogger_Level_Debug)
#define KSLOG_DEBUG(FMT, ...) a_KSLOG_FULL("DEBUG", FMT, ##__VA_ARGS__)
#define KSLOGBASIC_DEBUG(FMT, ...) i_KSLOG_BASIC(FMT, ##__VA_ARGS__)
#define KSLOGBASIC_DEBUG(FMT, ...) a_KSLOG_BASIC(FMT, ##__VA_ARGS__)
#else
#define KSLOG_DEBUG(FMT, ...)
#define KSLOGBASIC_DEBUG(FMT, ...)
Expand All @@ -343,7 +366,7 @@ bool kslog_clearLogFile();
*/
#if KSLOG_PRINTS_AT_LEVEL(KSLogger_Level_Trace)
#define KSLOG_TRACE(FMT, ...) a_KSLOG_FULL("TRACE", FMT, ##__VA_ARGS__)
#define KSLOGBASIC_TRACE(FMT, ...) i_KSLOG_BASIC(FMT, ##__VA_ARGS__)
#define KSLOGBASIC_TRACE(FMT, ...) a_KSLOG_BASIC(FMT, ##__VA_ARGS__)
#else
#define KSLOG_TRACE(FMT, ...)
#define KSLOGBASIC_TRACE(FMT, ...)
Expand Down