182 lines · cpp
1//===- Logging.cpp - General logging class implementation -------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8///9/// \file10/// Implements ompTest-tailored logging.11///12//===----------------------------------------------------------------------===//13 14#include "Logging.h"15 16using namespace omptest;17using namespace logging;18 19Logger::Logger(Level LogLevel, std::ostream &OutStream, bool FormatOutput)20 : LoggingLevel(LogLevel), OutStream(OutStream), FormatOutput(FormatOutput) {21 // Flush any buffered output22 OutStream << std::flush;23}24 25Logger::~Logger() {26 // Flush any buffered output27 OutStream << std::flush;28}29 30std::map<Level, std::set<FormatOption>> AggregatedFormatOptions{31 {Level::Diagnostic, {FormatOption::ColorLightBlue}},32 {Level::Info, {FormatOption::ColorLightGray}},33 {Level::Warning, {FormatOption::ColorLightYellow}},34 {Level::Error, {FormatOption::ColorRed}},35 {Level::Critical, {FormatOption::ColorLightRed}},36 {Level::Default, {FormatOption::None}},37 {Level::ExpectedEvent, {FormatOption::Bold, FormatOption::ColorCyan}},38 {Level::ObservedEvent, {FormatOption::ColorCyan}},39 {Level::OffendingEvent, {FormatOption::ColorYellow}}};40 41const char *logging::to_string(Level LogLevel) {42 switch (LogLevel) {43 case Level::Diagnostic:44 return "Diagnostic";45 case Level::Info:46 return "Info";47 case Level::Warning:48 return "Warning";49 case Level::Error:50 return "Error";51 case Level::Critical:52 return "Critical";53 case Level::Silent:54 return "Silent";55 default:56 assert(false && "Requested string representation for unknown LogLevel");57 return "UNKNOWN";58 }59}60 61std::string logging::getFormatSequence(Level LogLevel) {62 auto Options = AggregatedFormatOptions[LogLevel];63 std::stringstream SS{"\033["};64 SS << "\033[";65 if (!Options.empty()) {66 for (auto &Option : AggregatedFormatOptions[LogLevel])67 SS << int(Option) << ';';68 SS.seekp(-1, SS.cur);69 SS << 'm';70 } else {71 // Fallback to None / reset formatting72 SS << "0m";73 }74 return SS.str();75}76 77std::string logging::format(const std::string &Message, FormatOption Option) {78 std::stringstream SS{"\033["};79 SS << "\033[";80 SS << int(Option) << 'm' << Message << "\033[0m";81 return SS.str();82}83 84std::string logging::format(const std::string &Message,85 std::set<FormatOption> Options) {86 std::stringstream SS{"\033["};87 SS << "\033[";88 for (auto &Option : Options)89 SS << int(Option) << ';';90 SS.seekp(-1, SS.cur);91 SS << 'm' << Message << "\033[0m";92 return SS.str();93}94 95void Logger::log(const std::string &Message, Level LogLevel) const {96 // Serialize logging97 std::lock_guard<std::mutex> Lock(LogMutex);98 99 if (LoggingLevel > LogLevel)100 return;101 102 if (FormatOutput) {103 OutStream << getFormatSequence(LogLevel) << '[' << to_string(LogLevel)104 << "] " << Message << getFormatSequence() << std::endl;105 } else {106 OutStream << '[' << to_string(LogLevel) << "] " << Message << std::endl;107 }108}109 110void Logger::logEventMismatch(const std::string &Message,111 const omptest::OmptAssertEvent &OffendingEvent,112 Level LogLevel) const {113 // Serialize logging114 std::lock_guard<std::mutex> Lock(LogMutex);115 if (LoggingLevel > LogLevel)116 return;117 118 if (FormatOutput) {119 OutStream << getFormatSequence(LogLevel) << '[' << to_string(LogLevel)120 << "] " << getFormatSequence()121 << format(Message, AggregatedFormatOptions[LogLevel])122 << "\n\tOffending event name='"123 << format(OffendingEvent.getEventName(),124 AggregatedFormatOptions[Level::OffendingEvent])125 << "'\n\tOffending='"126 << format(OffendingEvent.toString(),127 AggregatedFormatOptions[Level::OffendingEvent])128 << '\'' << std::endl;129 } else {130 OutStream << '[' << to_string(LogLevel) << "] " << Message131 << "\n\tOffending event name='" << OffendingEvent.getEventName()132 << "'\n\tOffending='" << OffendingEvent.toString() << '\''133 << std::endl;134 }135}136 137void Logger::logEventMismatch(const std::string &Message,138 const omptest::OmptAssertEvent &ExpectedEvent,139 const omptest::OmptAssertEvent &ObservedEvent,140 Level LogLevel) const {141 // Serialize logging142 std::lock_guard<std::mutex> Lock(LogMutex);143 if (LoggingLevel > LogLevel)144 return;145 146 if (FormatOutput) {147 OutStream << getFormatSequence(LogLevel) << '[' << to_string(LogLevel)148 << "] " << Message << getFormatSequence()149 << "\n\tExpected event name='"150 << format(ExpectedEvent.getEventName(),151 AggregatedFormatOptions[Level::ExpectedEvent])152 << "' observe='"153 << format(to_string(ExpectedEvent.getEventExpectedState()),154 AggregatedFormatOptions[Level::ExpectedEvent])155 << "'\n\tObserved event name='"156 << format(ObservedEvent.getEventName(),157 AggregatedFormatOptions[Level::ObservedEvent])158 << "'\n\tExpected='"159 << format(ExpectedEvent.toString(),160 AggregatedFormatOptions[Level::ExpectedEvent])161 << "'\n\tObserved='"162 << format(ObservedEvent.toString(),163 AggregatedFormatOptions[Level::ObservedEvent])164 << '\'' << std::endl;165 } else {166 OutStream << '[' << to_string(LogLevel) << "] " << Message167 << "\n\tExpected event name='" << ExpectedEvent.getEventName()168 << "' observe='"169 << to_string(ExpectedEvent.getEventExpectedState())170 << "'\n\tObserved event name='" << ObservedEvent.getEventName()171 << "'\n\tExpected='" << ExpectedEvent.toString()172 << "'\n\tObserved='" << ObservedEvent.toString() << '\''173 << std::endl;174 }175}176 177void Logger::setFormatOutput(bool Enabled) { FormatOutput = Enabled; }178 179Level Logger::getLoggingLevel() const { return LoggingLevel; }180 181void Logger::setLoggingLevel(Level LogLevel) { LoggingLevel = LogLevel; }182