Add logging to CAF

This commit is contained in:
Magne Sjaastad committed 2025-09-11 13:42:56 +02:00
1 parent 7a483bdb4e
commit 8251562cd9
4 files changed
+347 -4

No files matched your search

@@ -61,6 +61,8 @@ set(PROJECT_FILES
cafAsyncWorkerManager.cpp
cafPdmObjectHandleTools.h
cafPdmDeprecation.h
cafPdmLogging.h
cafPdmLogging.cpp
)
add_library(${PROJECT_NAME} ${PROJECT_FILES})
@@ -0,0 +1,190 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2025 Ceetron Solutions AS
//
// This library may be used under the terms of either the GNU General Public License or
// the GNU Lesser General Public License as follows:
//
// GNU General Public License Usage
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
// GNU Lesser General Public License Usage
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
// for more details.
//
//##################################################################################################
#include "cafPdmLogging.h"
#include <algorithm>
namespace caf
{
//--------------------------------------------------------------------------------------------------
// Static member definitions
//--------------------------------------------------------------------------------------------------
std::vector<std::shared_ptr<PdmLogger>> PdmLogging::s_loggers;
std::mutex PdmLogging::s_loggerMutex;
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmLogging::registerLogger( std::shared_ptr<PdmLogger> logger )
{
if ( !logger ) return;
std::lock_guard<std::mutex> lock( s_loggerMutex );
// Avoid duplicate registrations
auto it = std::find( s_loggers.begin(), s_loggers.end(), logger );
if ( it == s_loggers.end() )
{
s_loggers.push_back( logger );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmLogging::unregisterLogger( std::shared_ptr<PdmLogger> logger )
{
if ( !logger ) return;
std::lock_guard<std::mutex> lock( s_loggerMutex );
auto it = std::find( s_loggers.begin(), s_loggers.end(), logger );
if ( it != s_loggers.end() )
{
s_loggers.erase( it );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmLogging::clearAllLoggers()
{
std::lock_guard<std::mutex> lock( s_loggerMutex );
s_loggers.clear();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmLogging::error( const QString& message )
{
std::lock_guard<std::mutex> lock( s_loggerMutex );
for ( auto& logger : s_loggers )
{
if ( logger && logger->level() >= static_cast<int>( PdmLogLevel::PDM_LL_ERROR ) )
{
logger->error( message );
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmLogging::warning( const QString& message )
{
std::lock_guard<std::mutex> lock( s_loggerMutex );
for ( auto& logger : s_loggers )
{
if ( logger && logger->level() >= static_cast<int>( PdmLogLevel::PDM_LL_WARNING ) )
{
logger->warning( message );
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmLogging::info( const QString& message )
{
std::lock_guard<std::mutex> lock( s_loggerMutex );
for ( auto& logger : s_loggers )
{
if ( logger && logger->level() >= static_cast<int>( PdmLogLevel::PDM_LL_INFO ) )
{
logger->info( message );
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmLogging::debug( const QString& message )
{
std::lock_guard<std::mutex> lock( s_loggerMutex );
for ( auto& logger : s_loggers )
{
if ( logger && logger->level() >= static_cast<int>( PdmLogLevel::PDM_LL_DEBUG ) )
{
logger->debug( message );
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool PdmLogging::hasLoggers()
{
std::lock_guard<std::mutex> lock( s_loggerMutex );
return !s_loggers.empty();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int PdmLogging::effectiveLogLevel()
{
std::lock_guard<std::mutex> lock( s_loggerMutex );
if ( s_loggers.empty() )
{
return 0; // No logging
}
// Return the highest log level among all registered loggers
int maxLevel = 0;
for ( const auto& logger : s_loggers )
{
if ( logger )
{
maxLevel = std::max( maxLevel, logger->level() );
}
}
return maxLevel;
}
} // namespace caf
@@ -0,0 +1,133 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2025 Ceetron Solutions AS
//
// This library may be used under the terms of either the GNU General Public License or
// the GNU Lesser General Public License as follows:
//
// GNU General Public License Usage
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
// GNU Lesser General Public License Usage
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include <QString>
#include <memory>
#include <mutex>
#include <vector>
namespace caf
{
//==================================================================================================
/// Log levels compatible with application-level logging systems
//==================================================================================================
enum class PdmLogLevel
{
PDM_LL_ERROR = 1,
PDM_LL_WARNING = 2,
PDM_LL_INFO = 3,
PDM_LL_DEBUG = 4
};
//==================================================================================================
/// Abstract interface for logging from CAF PDM Core
//==================================================================================================
class PdmLogger
{
public:
virtual ~PdmLogger() = default;
virtual int level() const = 0;
virtual void setLevel( int logLevel ) = 0;
virtual void error( const QString& message ) = 0;
virtual void warning( const QString& message ) = 0;
virtual void info( const QString& message ) = 0;
virtual void debug( const QString& message ) = 0;
};
//==================================================================================================
/// Static logging manager for the CAF PDM framework
/// Provides a bridge between CAF and application-level logging systems
//==================================================================================================
class PdmLogging
{
public:
// Logger registration
static void registerLogger( std::shared_ptr<PdmLogger> logger );
static void unregisterLogger( std::shared_ptr<PdmLogger> logger );
static void clearAllLoggers();
// Logging methods - these are called from throughout the CAF framework
static void error( const QString& message );
static void warning( const QString& message );
static void info( const QString& message );
static void debug( const QString& message );
// Utility methods
static bool hasLoggers();
static int effectiveLogLevel();
private:
static std::vector<std::shared_ptr<PdmLogger>> s_loggers;
static std::mutex s_loggerMutex;
};
//==================================================================================================
/// Convenience macros for logging from CAF code
//==================================================================================================
#define CAF_PDM_LOG_ERROR( message ) caf::PdmLogging::error( message )
#define CAF_PDM_LOG_WARNING( message ) caf::PdmLogging::warning( message )
#define CAF_PDM_LOG_INFO( message ) caf::PdmLogging::info( message )
#define CAF_PDM_LOG_DEBUG( message ) caf::PdmLogging::debug( message )
// Conditional logging macros that only log if loggers are registered
#define CAF_PDM_LOG_ERROR_IF( message ) \
do \
{ \
if ( caf::PdmLogging::hasLoggers() ) caf::PdmLogging::error( message ); \
} while ( 0 )
#define CAF_PDM_LOG_WARNING_IF( message ) \
do \
{ \
if ( caf::PdmLogging::hasLoggers() ) caf::PdmLogging::warning( message ); \
} while ( 0 )
#define CAF_PDM_LOG_INFO_IF( message ) \
do \
{ \
if ( caf::PdmLogging::hasLoggers() ) caf::PdmLogging::info( message ); \
} while ( 0 )
#define CAF_PDM_LOG_DEBUG_IF( message ) \
do \
{ \
if ( caf::PdmLogging::hasLoggers() ) caf::PdmLogging::debug( message ); \
} while ( 0 )
} // namespace caf