Files
ResInsight/ApplicationLibCode/Application/Tools/Telemetry/RiaOpenTelemetryManager.h
T
Magne Sjaastad 022d77bef8 macOS: Initial Apple Silicon and x86_64 build support
* Refactor: add MACOSX_BUNDLE option to qt_add_executable in multiple CMakeLists.txt files
* #14045 macOS: Guard std::stacktrace usage and skip ucontext on Apple platforms
* #14045 macOS: Guard std::ispanstream with std::istringstream fallback
* #14045 macOS: Add vcpkg overlay triplets for osx and exclude grpc on osx
* #14045 macOS: CMake macOS build support and openzgy OpenMP-disable patch
* #14045 CI: Add macOS build workflow
* #14045 macOS: Use feature-test macros to detect <stacktrace> and <spanstream>
* #14045 macOS: Make MAX_STIMPLAN_LAYERS constexpr to fix arm64 link error
* #14045 CI: Ship README-macOS.txt with artifact to document Gatekeeper workaround
* #14045 CI: Pin macOS runner to macos-14 and set deployment target to 14.0
* #14045 CI: Move macOS runner to macos-15 and fix README step on configure failure
2026-06-01 12:38:55 +02:00

202 lines
6.6 KiB
C++

/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2025- 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
#include <QObject>
#include <atomic>
#include <chrono>
#include <functional>
#include <map>
#include <memory>
#include <mutex>
#include <queue>
#include <string>
#include <version>
// std::stacktrace is C++23. libc++ shipped with Homebrew llvm@19 (and
// older toolchains) does not provide it yet, so guard the include + the
// reportCrash overload that uses it. Use the feature-test macro from
// <version> rather than __has_include, since the header may be present
// without a usable implementation. See #14045.
#if defined( __cpp_lib_stacktrace ) && __cpp_lib_stacktrace >= 202011L
#include <stacktrace>
#define RIA_HAS_STD_STACKTRACE 1
#else
#define RIA_HAS_STD_STACKTRACE 0
#endif
class QString;
class QNetworkAccessManager;
class QTimer;
//==================================================================================================
//
// OpenTelemetry Manager for ResInsight
// Handles async telemetry reporting with privacy filtering and resilience
//
//==================================================================================================
class RiaOpenTelemetryManager : public QObject
{
public:
// Error handling
enum class TelemetryError
{
ConfigurationError,
NetworkError,
AuthenticationError,
QuotaExceeded,
PrivacyViolation,
InternalError
};
using ErrorCallback = std::function<void( TelemetryError, const QString& details )>;
// Health monitoring
struct HealthSnapshot
{
uint64_t eventsQueued{ 0 };
uint64_t eventsSent{ 0 };
uint64_t eventsDropped{ 0 };
uint64_t networkFailures{ 0 };
std::chrono::steady_clock::time_point lastSuccessfulSend;
std::chrono::steady_clock::time_point systemStartTime;
double getSuccessRate() const;
bool isHealthy() const;
};
struct HealthMetrics
{
std::atomic<uint64_t> eventsQueued{ 0 };
std::atomic<uint64_t> eventsSent{ 0 };
std::atomic<uint64_t> eventsDropped{ 0 };
std::atomic<uint64_t> networkFailures{ 0 };
std::chrono::steady_clock::time_point lastSuccessfulSend;
std::chrono::steady_clock::time_point systemStartTime;
};
static RiaOpenTelemetryManager& instance();
static QString getSystemUsername();
bool initialize();
void shutdown();
bool reinitialize();
// Event reporting
void reportEventAsync( const std::string& eventName, const std::map<std::string, std::string>& attributes );
#if RIA_HAS_STD_STACKTRACE
void reportCrash( int signalCode, const std::stacktrace& trace, const std::map<std::string, std::string>& extraAttributes = {} );
#endif
// Configuration
bool isEnabled() const;
bool isInitialized() const;
void setErrorCallback( ErrorCallback callback );
void setUsername( const std::string& username );
// Performance and memory management
void setMaxQueueSize( size_t maxEvents );
void enableBackpressure( bool enable );
void setMemoryThreshold( size_t maxMemoryMB );
size_t getCurrentQueueSize() const;
// Health monitoring
HealthSnapshot getHealthMetrics() const;
bool isHealthy() const;
void enableHealthMonitoring( bool enable );
private:
RiaOpenTelemetryManager();
~RiaOpenTelemetryManager() override;
RiaOpenTelemetryManager( const RiaOpenTelemetryManager& ) = delete;
RiaOpenTelemetryManager& operator=( const RiaOpenTelemetryManager& ) = delete;
struct Event
{
std::string name;
std::map<std::string, std::string> attributes;
std::chrono::system_clock::time_point timestamp;
Event( const std::string& eventName, const std::map<std::string, std::string>& attrs )
: name( eventName )
, attributes( attrs )
, timestamp( std::chrono::system_clock::now() )
{
}
};
// Initialization
bool initializeProvider();
bool createExporter();
void setupResourceAttributes();
// Event processing
void processEvents();
void processEvent( const Event& event );
void flushPendingEvents();
void onProcessEventTimer();
// Circuit breaker and resilience
void handleError( TelemetryError error, const QString& context );
void attemptReconnection();
bool isCircuitBreakerOpen() const;
void resetCircuitBreaker();
// Event filtering
bool isEventAllowed( const std::string& eventName ) const;
// Health monitoring
void updateHealthMetrics( bool success );
void sendHealthSpan();
// Thread safety
mutable std::mutex m_configMutex;
mutable std::mutex m_queueMutex;
std::queue<Event> m_eventQueue;
// State
std::atomic<bool> m_initialized{ false };
std::atomic<bool> m_enabled{ false };
std::atomic<bool> m_isShuttingDown{ false };
std::atomic<bool> m_circuitBreakerOpen{ false };
// Qt networking and timer
QNetworkAccessManager* m_networkAccessManager{ nullptr };
QTimer* m_processTimer{ nullptr };
QTimer* m_healthTimer{ nullptr };
// Configuration
size_t m_maxQueueSize{ 10000 };
bool m_backpressureEnabled{ true };
size_t m_memoryThresholdMB{ 50 };
std::string m_userHash;
// Error handling
ErrorCallback m_errorCallback;
std::atomic<int> m_consecutiveFailures{ 0 };
std::chrono::steady_clock::time_point m_lastReconnectAttempt;
// Pending network reply tracking (for synchronous crash flush)
std::atomic<int> m_pendingReplies{ 0 };
// Health monitoring
mutable HealthMetrics m_healthMetrics;
bool m_healthMonitoringEnabled{ false };
};