summaryrefslogtreecommitdiff
path: root/src/ToolBox/superpmi/superpmi-shared/logging.h
blob: dbde4af3fcd52ce699d9c9dda5770d403712f7c4 (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
109
110
111
112
113
114
//
// 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