#14717 Forward cvf logging to RiaLogging

cvf loggers default to LL_WARNING on a console destination and are never
wired to RiaLogging, so cvf's own diagnostics never reach the log file. A
rendering failure is therefore silent, with no artefact a user can send us.

Add RiaToCvfLoggingBridge (cvf::LogDestination) and RiaCvfLoggingManager,
mirroring RiaToCafLoggingBridge, to forward cvf log events into RiaLogging.
Wire initialize/shutdown into RiaApplication.

cee.cvf, cee.cvf.OpenGL and cee.cvf.qt follow the application log level:
LL_INFO normally, LL_DEBUG only when the application itself is set to debug,
so normal runs stay quiet.
This commit is contained in:
Magne Sjaastad committed 2026-09-10 08:22:29 -04:00
1 parent c49f298a7d
commit 4b0e03d7fc
4 files changed
+199

No files matched your search

@@ -44,6 +44,7 @@
#include "RiaSocketServer.h"
#include "RiaTextStringTools.h"
#include "RiaToCafLogging.h"
#include "RiaToCvfLogging.h"
#include "RiaVersionInfo.h"
#include "RiaViewRedrawScheduler.h"
#include "RiaWellNameComparer.h"
@@ -218,6 +219,8 @@ RiaApplication::~RiaApplication()
// Shutdown CAF logging bridge
RiaCafLoggingManager::shutdownCafLogging();
RiaCvfLoggingManager::shutdownCvfLogging();
caf::SelectionManager::instance()->setPdmRootObject( nullptr );
m_project.reset();
@@ -1721,6 +1724,9 @@ void RiaApplication::initialize()
// are reported
initializeLoggers();
// Initialize cvf logging bridge to forward cvf framework messages to ResInsight logging
RiaCvfLoggingManager::initializeCvfLogging();
RiaConnectorTools::configureCloudServices();
// Start with a project
@@ -61,6 +61,7 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RiaAngleUtils.h
${CMAKE_CURRENT_LIST_DIR}/RiaAngleUtils.inl
${CMAKE_CURRENT_LIST_DIR}/RiaToCafLogging.h
${CMAKE_CURRENT_LIST_DIR}/RiaToCvfLogging.h
${CMAKE_CURRENT_LIST_DIR}/RiaZScaleTools.h
)
@@ -117,6 +118,7 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RiaQuantityInfoTools.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaAngleUtils.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaToCafLogging.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaToCvfLogging.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaZScaleTools.cpp
)
@@ -0,0 +1,136 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2026 Equinor ASA
//
// ResInsight 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.
//
// ResInsight 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.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RiaToCvfLogging.h"
#include "RiaLogging.h"
#include "cvfLogEvent.h"
#include "cvfLogManager.h"
#include <algorithm>
#include <format>
namespace
{
// Using setLevelRecursive() with these as base names also affects any child loggers, e.g. the
// per-widget-instance loggers created underneath "cee.cvf.qt".
//
// NOTE: cvf::LogManager::logger() only inherits its parent's level/destination at the moment the
// logger is first created (i.e. the first time CVF_GET_LOGGER() is called for that name). It is not
// a live relationship, so a logger that does not exist yet would silently fall back to the root
// logger's defaults. Force-create them before applying the recursive settings.
const char* cvfLoggerPrefixes[] = { "cee.cvf", "cee.cvf.OpenGL", "cee.cvf.qt" };
// cvf is noisy at debug level, so only go there when the application itself is set to debug,
// e.g. with --loglevel debug.
cvf::Logger::Level cvfLevelFromRiaLogging()
{
int appLevel = static_cast<int>( RILogLevel::RI_LL_DISABLED );
for ( const RiaLogger* logger : RiaLogging::loggerInstances() )
{
appLevel = std::max( appLevel, logger->level() );
}
return appLevel >= static_cast<int>( RILogLevel::RI_LL_DEBUG ) ? cvf::Logger::LL_DEBUG : cvf::Logger::LL_INFO;
}
} // namespace
//--------------------------------------------------------------------------------------------------
// Static member definitions
//--------------------------------------------------------------------------------------------------
bool RiaCvfLoggingManager::s_isInitialized = false;
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaToCvfLoggingBridge::log( const cvf::LogEvent& logEvent )
{
const std::string message = std::format( "cvf[{}]: {}", logEvent.source().toStdString(), logEvent.message().toStdString() );
switch ( logEvent.level() )
{
case cvf::Logger::LL_ERROR:
RiaLogging::error( message );
break;
case cvf::Logger::LL_WARNING:
RiaLogging::warning( message );
break;
case cvf::Logger::LL_INFO:
RiaLogging::info( message );
break;
case cvf::Logger::LL_DEBUG:
default:
RiaLogging::debug( message );
break;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaCvfLoggingManager::initializeCvfLogging()
{
if ( s_isInitialized ) return;
// Route every cvf logger through RiaLogging. cvf defaults to LL_WARNING on a console
// destination, so without this its diagnostics never reach the log file.
cvf::LogManager::instance()->setDestinationRecursive( "", new RiaToCvfLoggingBridge );
const cvf::Logger::Level level = cvfLevelFromRiaLogging();
for ( const char* loggerPrefix : cvfLoggerPrefixes )
{
CVF_GET_LOGGER( loggerPrefix );
}
for ( const char* loggerPrefix : cvfLoggerPrefixes )
{
cvf::LogManager::instance()->setLevelRecursive( loggerPrefix, level );
cvf::LogManager::instance()->setDestinationRecursive( loggerPrefix, new RiaToCvfLoggingBridge );
}
s_isInitialized = true;
RiaLogging::debug( "cvf logging bridge initialized successfully" );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaCvfLoggingManager::shutdownCvfLogging()
{
if ( !s_isInitialized ) return;
for ( const char* loggerPrefix : cvfLoggerPrefixes )
{
cvf::LogManager::instance()->setLevelRecursive( loggerPrefix, cvf::Logger::LL_WARNING );
}
s_isInitialized = false;
RiaLogging::debug( "cvf logging bridge shut down" );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RiaCvfLoggingManager::isCvfLoggingActive()
{
return s_isInitialized;
}
@@ -0,0 +1,55 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2026 Equinor ASA
//
// ResInsight 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.
//
// ResInsight 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.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
// Forwards the cvf framework's own logging (cee.cvf, cee.cvf.qt, cee.cvf.OpenGL) to ResInsight's
// RiaLogging system, so messages end up in the log file and the message panel alongside the rest of
// the application's log output. Without this, cvf logs to a console destination nobody reads.
#include "cvfLogDestination.h"
//==================================================================================================
/// Bridge log destination that connects cvf's logging framework to ResInsight's RiaLogging system
/// This class implements the cvf::LogDestination interface and forwards all messages
/// to ResInsight's logging infrastructure
//==================================================================================================
class RiaToCvfLoggingBridge : public cvf::LogDestination
{
public:
void log( const cvf::LogEvent& logEvent ) override;
};
//==================================================================================================
/// Utility class for managing cvf logging integration lifecycle
//==================================================================================================
class RiaCvfLoggingManager
{
public:
/// Initialize cvf logging integration - should be called during application startup
static void initializeCvfLogging();
/// Cleanup cvf logging integration - should be called during application shutdown
static void shutdownCvfLogging();
/// Check if cvf logging is currently active
static bool isCvfLoggingActive();
private:
static bool s_isInitialized;
};