summaryrefslogtreecommitdiff
path: root/src/ToolBox/superpmi/superpmi-shared/logging.h
blob: a2c388ee3ef3afee28bbb80f86f06f86214bc50d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

//----------------------------------------------------------
// Logging.h - Common logging and console output infrastructure
//----------------------------------------------------------
#ifndef _Logging
#define _Logging

//
// General purpose logging macros
//

#define LogMessage(level, ...) \
    Logger::LogPrintf(__func__, __FILE__, __LINE__, level, __VA_ARGS__)

#define LogError(...)   LogMessage(LOGLEVEL_ERROR,   __VA_ARGS__)
#define LogWarning(...) LogMessage(LOGLEVEL_WARNING, __VA_ARGS__)
#define LogMissing(...) LogMessage(LOGLEVEL_MISSING, __VA_ARGS__)
#define LogInfo(...)    LogMessage(LOGLEVEL_INFO,    __VA_ARGS__)
#define LogVerbose(...) LogMessage(LOGLEVEL_VERBOSE, __VA_ARGS__)
#define LogDebug(...)   LogMessage(LOGLEVEL_DEBUG,   __VA_ARGS__)

#define LogIssue(issue, msg, ...) \
    IssueLogger::LogIssueHelper(__FUNCTION__, __FILE__, __LINE__, issue, msg, __VA_ARGS__)

// Captures the exception message before throwing so we can log it at the point of occurrence
#define LogException(exCode, msg, ...) \
    do { \
        Logger::LogExceptionMessage(__FUNCTION__, __FILE__, __LINE__, exCode, msg, __VA_ARGS__); \
        ThrowException(exCode, msg, __VA_ARGS__); \
    } while (0)

// These are specified as flags so subsets of the logging functionality can be enabled/disabled at once
enum LogLevel : UINT32
{
    LOGLEVEL_ERROR   = 0x00000001,  // Internal fatal errors that are non-recoverable
    LOGLEVEL_WARNING = 0x00000002,  // Internal conditions that are unusual, but not serious
    LOGLEVEL_MISSING = 0x00000004,  // Failures to due to missing JIT-EE details
    LOGLEVEL_ISSUE   = 0x00000008,  // Issues found with the JIT, e.g. asm diffs, asserts
    LOGLEVEL_INFO    = 0x00000010,  // Notifications/summaries, e.g. 'Loaded 5  Jitted 4  FailedCompile 1'
    LOGLEVEL_VERBOSE = 0x00000020,  // Status messages, e.g. 'Jit startup took 151.12ms'
    LOGLEVEL_DEBUG   = 0x00000040   // Detailed output that's only useful for SuperPMI debugging
};

// Preset log level combinations
enum LogLevelMask : UINT32
{
    LOGMASK_NONE    = 0x00000000,
    LOGMASK_DEFAULT = (LOGLEVEL_DEBUG - 1),  // Default is essentially "enable everything except debug"
    LOGMASK_ALL     = 0xffffffff
};

//
// Manages the SuperPMI logging subsystem, including both file-based logging and logging to the console.
//
class Logger
{
private:
    static bool s_initialized;
    static UINT32 s_logLevel;
    static HANDLE s_logFile;
    static char *s_logFilePath;
    static CRITICAL_SECTION s_critSec;

public:
    static void Initialize();
    static void Shutdown();

    static void OpenLogFile(char *logFilePath);
    static void CloseLogFile();

    static UINT32 ParseLogLevelString(const char *specifierStr);
    static void SetLogLevel(UINT32 logLevelMask) { s_logLevel = logLevelMask; }
    static UINT32 GetLogLevel() { return s_logLevel; }

    // Return true if all specified log levels are enabled.
    static bool IsLogLevelEnabled(UINT32 logLevelMask) { return (logLevelMask & GetLogLevel()) == logLevelMask; }

    static void LogPrintf(const char *function, const char *file, int line,
                          LogLevel level, const char *msg, ...);
    static void LogVprintf(const char *function, const char *file, int line,
                           LogLevel level, va_list argList, const char *msg);
    static void LogExceptionMessage(const char *function, const char *file, int line,
                                    DWORD exceptionCode, const char *msg, ...);
};

enum IssueType
{
    ISSUE_ASSERT,
    ISSUE_ASM_DIFF
};

//
// JIT issues have more granularity than other types of log messages. The logging of issues is abstracted
// from the normal logger to reflect this. It also will enable us to track things specific to JIT issues,
// like statistics on issues that were found during a run.
//
class IssueLogger
{
public:
    static void LogIssueHelper(const char *function, const char *file, int line,
                               IssueType issue, const char *msg, ...);
};

#endif