f078375350
* Updates:
- rocm_smi_logger:
General cleanup &
Aligned to cpplint rules for usage
- rocm_smi_monitor:
Fixed MonitorTypes
from not displaying properly in logs
& Added socket power label + current
socket power MonitorTypes
- rocm_smi API:
Added rsmi_dev_current_socket_power_get API
- rocm_smi CLI:
General cleanup,
Concise info now displays device data
in variable width (see printLogSpacer's
new field),
printLogSpacer now as an adjustable
variable that overrides appWidth,
Added Socket Power to base rocm-smi +
--showpower CLI calls,
--showpower & base rocm-smi CLI defaults
to printing socket power (if not available,
displays average power)
- Cleaned up temp label references
- power_read gtests:
Added current socket power to testing
Change-Id: Ica57e6f98ad96e2584e7c7955e188f68d2dab89d
Signed-off-by: Charis Poag <Charis.Poag@amd.com>
531 lines
15 KiB
C++
531 lines
15 KiB
C++
/*
|
|
* =============================================================================
|
|
* The University of Illinois/NCSA
|
|
* Open Source License (NCSA)
|
|
*
|
|
* Copyright (c) 2023, Advanced Micro Devices, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* Developed by:
|
|
*
|
|
* AMD Research and AMD ROC Software Development
|
|
*
|
|
* Advanced Micro Devices, Inc.
|
|
*
|
|
* www.amd.com
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to
|
|
* deal with the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* - Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimers.
|
|
* - Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimers in
|
|
* the documentation and/or other materials provided with the distribution.
|
|
* - Neither the names of <Name of Development Group, Name of Institution>,
|
|
* nor the names of its contributors may be used to endorse or promote
|
|
* products derived from this Software without specific prior written
|
|
* permission.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS WITH THE SOFTWARE.
|
|
*
|
|
* Detail Description:
|
|
* Implemented complete logging mechanism, supporting multiple logging type
|
|
* like as file based logging, console base logging etc. It also supported
|
|
* for different log types.
|
|
*
|
|
* Thread Safe logging mechanism. Compatible with G++ (Linux platform)
|
|
*
|
|
* Supported Log Type: ERROR, ALARM, ALWAYS, INFO, BUFFER, TRACE, DEBUG
|
|
* No control for ERROR, ALRAM and ALWAYS messages. These type of messages
|
|
* should be always captured -- IF logging is enabled.
|
|
*
|
|
* WARNING: Logging is controlled by users environment variable - RSMI_LOGGING.
|
|
* Enabling RSMI_LOGGING, by export RSMI_LOGGING=<any value>. No logs will
|
|
* be printed, unless RSMI_LOGGING is enabled.
|
|
*
|
|
* BUFFER log type should be use while logging raw buffer or raw messages
|
|
* Having direct interface as well as C++ Singleton iface. Can use
|
|
* whatever interface fits your needs.
|
|
*/
|
|
|
|
// C++ Header File(s)
|
|
#include <cstdlib>
|
|
#include <chrono>
|
|
#include <ctime>
|
|
#include <iomanip>
|
|
#include <iostream>
|
|
#include <sstream>
|
|
|
|
// Code Specific Header Files(s)
|
|
#include "rocm_smi/rocm_smi_logger.h"
|
|
#include "rocm_smi/rocm_smi_main.h"
|
|
|
|
|
|
ROCmLogging::Logger *ROCmLogging::Logger::m_Instance = nullptr;
|
|
|
|
// Log file name
|
|
// WARNING: File name should be changed here and
|
|
// pre/post install/remove/upgrade scripts. Changing
|
|
// in one place will cause a mismatch in these scripts,
|
|
// files may not have proper permissions, and logrotate
|
|
// would not function properly.
|
|
#define LOGPATH "/var/log/rocm_smi_lib/"
|
|
#define LOGBASE_FNAME "ROCm-SMI-lib"
|
|
#define LOGEXTENSION ".log"
|
|
const char *logFileName = LOGPATH LOGBASE_FNAME LOGEXTENSION;
|
|
|
|
ROCmLogging::Logger::Logger() {
|
|
initialize_resources();
|
|
}
|
|
|
|
ROCmLogging::Logger::~Logger() {
|
|
if (m_loggingIsOn) {
|
|
destroy_resources();
|
|
}
|
|
}
|
|
|
|
ROCmLogging::Logger* ROCmLogging::Logger::getInstance() throw() {
|
|
if (m_Instance == nullptr) {
|
|
m_Instance = new ROCmLogging::Logger();
|
|
}
|
|
return m_Instance;
|
|
}
|
|
|
|
void ROCmLogging::Logger::lock() {
|
|
m_Lock.lock();
|
|
}
|
|
|
|
void ROCmLogging::Logger::unlock() {
|
|
m_Lock.unlock();
|
|
}
|
|
|
|
void ROCmLogging::Logger::logIntoFile(std::string& data) {
|
|
lock();
|
|
if (!m_File.is_open()) {
|
|
initialize_resources();
|
|
if (!m_File.is_open()) {
|
|
std::cout << "WARNING: re-initializing resources was unsuccessful."
|
|
<<" Unable to print the following message." << std::endl;
|
|
logOnConsole(data);
|
|
unlock();
|
|
return;
|
|
}
|
|
}
|
|
m_File << getCurrentTime() << " " << data << std::endl;
|
|
unlock();
|
|
}
|
|
|
|
void ROCmLogging::Logger::logOnConsole(std::string& data) {
|
|
std::cout << getCurrentTime() << " " << data << std::endl;
|
|
}
|
|
|
|
// Returns: In string format, YY-MM-DD HH:MM:SS.microseconds
|
|
std::string ROCmLogging::Logger::getCurrentTime(void) {
|
|
std::string currentTime;
|
|
|
|
// get current time
|
|
auto now = std::chrono::system_clock::now();
|
|
|
|
// get number of milliseconds for the current second
|
|
// (remainder after division into seconds)
|
|
auto ms = std::chrono::duration_cast<std::chrono::microseconds>(
|
|
now.time_since_epoch()) % 1000000;
|
|
|
|
// convert to std::time_t in order to convert to std::tm (broken time)
|
|
auto timer = std::chrono::system_clock::to_time_t(now);
|
|
|
|
// convert to broken time
|
|
std::tm bt = *std::localtime(&timer);
|
|
|
|
std::ostringstream oss;
|
|
|
|
// YY-MM-DD HH:MM:SS.microseconds
|
|
oss << std::put_time(&bt, "%F %T");
|
|
oss << '.' << std::setfill('0') << std::setw(4) << ms.count();
|
|
currentTime = oss.str();
|
|
return currentTime;
|
|
}
|
|
|
|
// Interface for Error Log
|
|
void ROCmLogging::Logger::error(const char* text) throw() {
|
|
// By default, logging is disabled
|
|
// The check below allows us to toggle logging through RSMI_LOGGING
|
|
// set or unset
|
|
if (!m_loggingIsOn) {
|
|
return;
|
|
}
|
|
|
|
std::string data;
|
|
data.append("[ERROR]: ");
|
|
data.append(text);
|
|
|
|
// ERROR must be capture
|
|
if (m_LogType == FILE_LOG) {
|
|
logIntoFile(data);
|
|
} else if (m_LogType == CONSOLE) {
|
|
logOnConsole(data);
|
|
} else if (m_LogType == BOTH_FILE_AND_CONSOLE) {
|
|
logOnConsole(data);
|
|
logIntoFile(data);
|
|
}
|
|
}
|
|
|
|
void ROCmLogging::Logger::error(std::string& text) throw() {
|
|
error(text.data());
|
|
}
|
|
|
|
void ROCmLogging::Logger::error(std::ostringstream& stream) throw() {
|
|
std::string text = stream.str();
|
|
error(text.data());
|
|
stream.str("");
|
|
}
|
|
|
|
// Interface for Alarm Log
|
|
void ROCmLogging::Logger::alarm(const char* text) throw() {
|
|
// By default, logging is disabled (ie. no RSMI_LOGGING)
|
|
// The check below allows us to toggle logging through RSMI_LOGGING
|
|
// set or unset
|
|
if (!m_loggingIsOn) {
|
|
return;
|
|
}
|
|
|
|
std::string data;
|
|
data.append("[ALARM]: ");
|
|
data.append(text);
|
|
|
|
// ALARM must be capture
|
|
if (m_LogType == FILE_LOG) {
|
|
logIntoFile(data);
|
|
} else if (m_LogType == CONSOLE) {
|
|
logOnConsole(data);
|
|
} else if (m_LogType == BOTH_FILE_AND_CONSOLE) {
|
|
logOnConsole(data);
|
|
logIntoFile(data);
|
|
}
|
|
}
|
|
|
|
void ROCmLogging::Logger::alarm(std::string& text) throw() {
|
|
alarm(text.data());
|
|
}
|
|
|
|
void ROCmLogging::Logger::alarm(std::ostringstream& stream) throw() {
|
|
std::string text = stream.str();
|
|
alarm(text.data());
|
|
stream.str("");
|
|
}
|
|
|
|
// Interface for Always Log
|
|
void ROCmLogging::Logger::always(const char* text) throw() {
|
|
// By default, logging is disabled (ie. no RSMI_LOGGING)
|
|
// The check below allows us to toggle logging through RSMI_LOGGING
|
|
// set or unset
|
|
if (!m_loggingIsOn) {
|
|
return;
|
|
}
|
|
|
|
std::string data;
|
|
data.append("[ALWAYS]: ");
|
|
data.append(text);
|
|
|
|
// No check for ALWAYS logs
|
|
if (m_LogType == FILE_LOG) {
|
|
logIntoFile(data);
|
|
} else if (m_LogType == CONSOLE) {
|
|
logOnConsole(data);
|
|
} else if (m_LogType == BOTH_FILE_AND_CONSOLE) {
|
|
logOnConsole(data);
|
|
logIntoFile(data);
|
|
}
|
|
}
|
|
|
|
void ROCmLogging::Logger::always(std::string& text) throw() {
|
|
always(text.data());
|
|
}
|
|
|
|
void ROCmLogging::Logger::always(std::ostringstream& stream) throw() {
|
|
std::string text = stream.str();
|
|
always(text.data());
|
|
stream.str("");
|
|
}
|
|
|
|
// Interface for Buffer Log
|
|
void ROCmLogging::Logger::buffer(const char* text) throw() {
|
|
// Buffer is the special case. So don't add log level
|
|
// and timestamp in the buffer message. Just log the raw bytes.
|
|
if ((m_LogType == FILE_LOG) && (m_LogLevel >= LOG_LEVEL_BUFFER)) {
|
|
lock();
|
|
if(!m_File.is_open()) {
|
|
initialize_resources();
|
|
if (!m_File.is_open()) {
|
|
std::cout << "WARNING: re-initializing resources was unsuccessful."
|
|
<<" Unable to print the following message." << std::endl;
|
|
std::string txtStr(text);
|
|
std::cout << txtStr << std::endl;
|
|
unlock();
|
|
return;
|
|
}
|
|
}
|
|
m_File << text << std::endl;
|
|
unlock();
|
|
} else if ((m_LogType == CONSOLE) && (m_LogLevel >= LOG_LEVEL_BUFFER)) {
|
|
std::cout << text << std::endl;
|
|
}
|
|
}
|
|
|
|
void ROCmLogging::Logger::buffer(std::string& text) throw() {
|
|
buffer(text.data());
|
|
}
|
|
|
|
void ROCmLogging::Logger::buffer(std::ostringstream& stream) throw() {
|
|
std::string text = stream.str();
|
|
buffer(text.data());
|
|
stream.str("");
|
|
}
|
|
|
|
// Interface for Info Log
|
|
void ROCmLogging::Logger::info(const char* text) throw() {
|
|
// By default, logging is disabled (ie. no RSMI_LOGGING)
|
|
// The check below allows us to toggle logging through RSMI_LOGGING
|
|
// set or unset
|
|
if (!m_loggingIsOn) {
|
|
return;
|
|
}
|
|
|
|
std::string data;
|
|
data.append("[INFO]: ");
|
|
data.append(text);
|
|
|
|
if ((m_LogType == FILE_LOG) && (m_LogLevel >= LOG_LEVEL_INFO)) {
|
|
logIntoFile(data);
|
|
} else if ((m_LogType == CONSOLE) && (m_LogLevel >= LOG_LEVEL_INFO)) {
|
|
logOnConsole(data);
|
|
} else if ((m_LogType == BOTH_FILE_AND_CONSOLE)
|
|
&& (m_LogLevel >= LOG_LEVEL_INFO)) {
|
|
logOnConsole(data);
|
|
logIntoFile(data);
|
|
}
|
|
}
|
|
|
|
void ROCmLogging::Logger::info(std::string& text) throw() {
|
|
info(text.data());
|
|
}
|
|
|
|
void ROCmLogging::Logger::info(std::ostringstream& stream) throw() {
|
|
std::string text = stream.str();
|
|
info(text.data());
|
|
stream.str("");
|
|
}
|
|
|
|
// Interface for Trace Log
|
|
void ROCmLogging::Logger::trace(const char* text) throw() {
|
|
// By default, logging is disabled (ie. no RSMI_LOGGING)
|
|
// The check below allows us to toggle logging through RSMI_LOGGING
|
|
// set or unset
|
|
if (!m_loggingIsOn) {
|
|
return;
|
|
}
|
|
|
|
std::string data;
|
|
data.append("[TRACE]: ");
|
|
data.append(text);
|
|
|
|
if ((m_LogType == FILE_LOG) && (m_LogLevel >= LOG_LEVEL_TRACE)) {
|
|
logIntoFile(data);
|
|
} else if ((m_LogType == CONSOLE) && (m_LogLevel >= LOG_LEVEL_TRACE)) {
|
|
logOnConsole(data);
|
|
} else if ((m_LogType == BOTH_FILE_AND_CONSOLE)
|
|
&& (m_LogLevel >= LOG_LEVEL_TRACE)) {
|
|
logOnConsole(data);
|
|
logIntoFile(data);
|
|
}
|
|
}
|
|
|
|
void ROCmLogging::Logger::trace(std::string& text) throw() {
|
|
trace(text.data());
|
|
}
|
|
|
|
void ROCmLogging::Logger::trace(std::ostringstream& stream) throw() {
|
|
std::string text = stream.str();
|
|
trace(text.data());
|
|
stream.str("");
|
|
}
|
|
|
|
// Interface for Debug Log
|
|
void ROCmLogging::Logger::debug(const char* text) throw() {
|
|
// By default, logging is disabled (ie. no RSMI_LOGGING)
|
|
// The check below allows us to toggle logging through RSMI_LOGGING
|
|
// set or unset
|
|
if (!m_loggingIsOn) {
|
|
return;
|
|
}
|
|
|
|
std::string data;
|
|
data.append("[DEBUG]: ");
|
|
data.append(text);
|
|
|
|
if ((m_LogType == FILE_LOG) && (m_LogLevel >= LOG_LEVEL_DEBUG)) {
|
|
logIntoFile(data);
|
|
} else if ((m_LogType == CONSOLE) && (m_LogLevel >= LOG_LEVEL_DEBUG)) {
|
|
logOnConsole(data);
|
|
} else if ((m_LogType == BOTH_FILE_AND_CONSOLE)
|
|
&& (m_LogLevel >= LOG_LEVEL_DEBUG)) {
|
|
logOnConsole(data);
|
|
logIntoFile(data);
|
|
}
|
|
}
|
|
|
|
void ROCmLogging::Logger::debug(std::string& text) throw() {
|
|
debug(text.data());
|
|
}
|
|
|
|
void ROCmLogging::Logger::debug(std::ostringstream& stream) throw() {
|
|
std::string text = stream.str();
|
|
debug(text.data());
|
|
stream.str("");
|
|
}
|
|
|
|
// Interfaces to control log levels
|
|
void ROCmLogging::Logger::updateLogLevel(LogLevel logLevel) {
|
|
m_LogLevel = logLevel;
|
|
}
|
|
|
|
void ROCmLogging::Logger::enableAllLogLevels() {
|
|
m_LogLevel = ENABLE_LOG;
|
|
}
|
|
|
|
// Disable all log levels, except error and alarm
|
|
void ROCmLogging::Logger::disableLog() {
|
|
m_LogLevel = DISABLE_LOG;
|
|
}
|
|
|
|
// Interfaces to control log Types
|
|
void ROCmLogging::Logger::updateLogType(LogType logType) {
|
|
m_LogType = logType;
|
|
}
|
|
|
|
void ROCmLogging::Logger::enableConsoleLogging() {
|
|
m_LogType = CONSOLE;
|
|
}
|
|
|
|
void ROCmLogging::Logger::enableFileLogging() {
|
|
m_LogType = FILE_LOG;
|
|
}
|
|
|
|
// Returns a string of details on current log settings
|
|
std::string ROCmLogging::Logger::getLogSettings() {
|
|
std::string logSettings;
|
|
|
|
if (m_File.is_open()) {
|
|
logSettings += "OpenStatus = File (" + std::string(logFileName)
|
|
+ ") is open";
|
|
} else {
|
|
logSettings += "OpenStatus = File (" + std::string(logFileName)
|
|
+ ") is not open";
|
|
}
|
|
logSettings += ", ";
|
|
|
|
switch (m_LogType) {
|
|
case NO_LOG:
|
|
logSettings += "LogType = NO_LOG";
|
|
break;
|
|
case FILE_LOG:
|
|
logSettings += "LogType = FILE_LOG";
|
|
break;
|
|
case CONSOLE:
|
|
logSettings += "LogType = CONSOLE";
|
|
break;
|
|
case BOTH_FILE_AND_CONSOLE:
|
|
logSettings += "LogType = BOTH_FILE_AND_CONSOLE";
|
|
break;
|
|
default:
|
|
logSettings += "LogType = <undefined>";
|
|
}
|
|
logSettings += ", ";
|
|
|
|
switch (m_LogLevel) {
|
|
case DISABLE_LOG:
|
|
logSettings += "LogLevel = DISABLE_LOG";
|
|
break;
|
|
case LOG_LEVEL_INFO:
|
|
logSettings += "LogLevel = LOG_LEVEL_INFO";
|
|
break;
|
|
case LOG_LEVEL_BUFFER:
|
|
logSettings += "LogLevel = LOG_LEVEL_BUFFER";
|
|
break;
|
|
case LOG_LEVEL_TRACE:
|
|
logSettings += "LogLevel = LOG_LEVEL_TRACE";
|
|
break;
|
|
case LOG_LEVEL_DEBUG:
|
|
logSettings += "LogLevel = LOG_LEVEL_DEBUG";
|
|
break;
|
|
case ENABLE_LOG:
|
|
logSettings += "LogLevel = ENABLE_LOG";
|
|
break;
|
|
default:
|
|
logSettings += "LogLevel = <undefined>";
|
|
}
|
|
|
|
return logSettings;
|
|
}
|
|
|
|
// Returns current reported enabled logging state. State is controlled by
|
|
// user's environment variable RSMI_LOGGING.
|
|
bool ROCmLogging::Logger::isLoggerEnabled() {
|
|
return m_loggingIsOn;
|
|
}
|
|
|
|
void ROCmLogging::Logger::initialize_resources() {
|
|
// By default, logging is disabled (ie. no RSMI_LOGGING)
|
|
// The check below allows us to toggle logging through RSMI_LOGGING
|
|
// set or unset
|
|
m_loggingIsOn = amd::smi::RocmSMI::getInstance().isLoggingOn();
|
|
if (!m_loggingIsOn) {
|
|
return;
|
|
}
|
|
m_File.open(logFileName, std::ios::out | std::ios::app);
|
|
m_LogLevel = LOG_LEVEL_TRACE;
|
|
// RSMI_LOGGING = 1, output to logs only
|
|
// RSMI_LOGGING = 2, output to console only
|
|
// RSMI_LOGGING = 3, output to logs and console
|
|
switch (amd::smi::RocmSMI::getInstance().getLogSetting()) {
|
|
case 0:
|
|
m_LogType = NO_LOG;
|
|
break;
|
|
case 1:
|
|
m_LogType = FILE_LOG;
|
|
break;
|
|
case 2:
|
|
m_LogType = CONSOLE;
|
|
break;
|
|
case 3:
|
|
m_LogType = BOTH_FILE_AND_CONSOLE;
|
|
break;
|
|
default:
|
|
m_LogType = NO_LOG;
|
|
break;
|
|
}
|
|
if (!m_File.is_open()) {
|
|
std::cout << "WARNING: Issue opening log file (" << logFileName
|
|
<< ") to write." << std::endl;
|
|
}
|
|
if (m_File.fail()) {
|
|
std::cout << "WARNING: Failed opening log file." << std::endl;
|
|
}
|
|
chmod(logFileName, S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR|S_IWGRP|S_IWOTH);
|
|
}
|
|
|
|
void ROCmLogging::Logger::destroy_resources() {
|
|
m_File.close();
|
|
}
|