Files
rippled/src/xrpld/app/main/Application.h
Pratik Mankawde 4278014ab0 fix(telemetry): order the metrics pipeline by instrument kind
beast::insight instruments are created during ApplicationImp's member-init
list, and opentelemetry-cpp 1.28 never rebinds an already-vended Meter, so an
instrument created before the MeterProvider is published records nothing for
the rest of the process. Observable instruments carry the opposite constraint:
registering one arms the SDK reader thread, and its callbacks run hook handlers
that read services which do not exist that early.

Publish the provider in Telemetry's constructor, ahead of every producer, and
defer only the observables. Collector gains onCollectionReady() and
onCollectionStopping(); OTelCollector arms and disarms its gauges in response.
StatsDCollector starts its polling thread in its own constructor and had the
same hazard, so it uses the pair to gate that thread.

The metrics resource carries service.instance.id and is immutable once built,
so the node public key is resolved in Main.cpp, where a config error can still
be reported, and passed to makeApplication(). getNodeIdentity() remains
authoritative; both paths now share readNodeIdentity(), so telemetry cannot
report a key the node has abandoned.

An explicit ~ApplicationImp stops observing and stops telemetry, covering the
setup() failure paths that never reach run(). Telemetry::stop() is once-only
and no longer clears another instance's global pointer. The histogram view's
meter selector now matches the meter actually in use, so its bucket boundaries
apply for the first time.
2026-08-20 16:36:41 +01:00

193 lines
4.2 KiB
C++

#pragma once
#include <xrpld/core/Config.h>
#include <xrpl/basics/Blob.h>
#include <xrpl/basics/SHAMapHash.h>
#include <xrpl/basics/TaggedCache.h>
#include <xrpl/basics/base_uint.h>
#include <xrpl/beast/utility/PropertyStream.h>
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/protocol/Protocol.h>
#include <boost/asio.hpp>
#include <boost/program_options.hpp>
#include <chrono>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <mutex>
#include <optional>
#include <string>
#include <utility>
namespace xrpl {
namespace perf {
class PerfLog;
} // namespace perf
// VFALCO TODO Fix forward declares required for header dependency loops
class AmendmentTable;
template <
class Key,
class T,
bool IsKeyCache,
class SharedWeakUnionPointer,
class SharedPointerType,
class Hash,
class KeyEqual,
class Mutex>
class TaggedCache;
class STLedgerEntry;
using SLE = STLedgerEntry;
using CachedSLEs = TaggedCache<uint256, SLE const>;
class CollectorManager;
class Family;
class HashRouter;
class Logs;
class LoadFeeTrack;
class JobQueue;
class InboundLedgers;
class InboundTransactions;
class AcceptedLedger;
class Ledger;
class LedgerMaster;
class LedgerCleaner;
class LedgerReplayer;
class LoadManager;
class ManifestCache;
class ValidatorKeys;
class NetworkOPs;
class OpenLedger;
class OrderBookDB;
class Overlay;
class PathRequestManager;
class PendingSaves;
class PublicKey;
class ServerHandler;
class SecretKey;
class STLedgerEntry;
class TimeKeeper;
class TransactionMaster;
class TxQ;
class ValidatorList;
class ValidatorSite;
class Cluster;
class RelationalDatabase;
class DatabaseCon;
class SHAMapStore;
using NodeCache = TaggedCache<SHAMapHash, Blob>;
template <class Adaptor>
class Validations;
class RCLValidationsAdaptor;
using RCLValidations = Validations<RCLValidationsAdaptor>;
class Application : public ServiceRegistry, public beast::PropertyStream::Source
{
public:
/* VFALCO NOTE
The master mutex protects:
- The open ledger
- Server global state
* What the last closed ledger is
* State of the consensus engine
other things
*/
using MutexType = std::recursive_mutex;
virtual MutexType&
getMasterMutex() = 0;
public:
Application();
virtual bool
setup(boost::program_options::variables_map const& options) = 0;
virtual void
start(bool withTimers) = 0;
virtual void
run() = 0;
virtual void
signalStop(std::string const& msg) = 0;
[[nodiscard]] virtual bool
checkSigs() const = 0;
virtual void
checkSigs(bool) = 0;
//
// ---
//
/**
* Returns a 64-bit instance identifier, generated at startup
*/
[[nodiscard]] virtual std::uint64_t
instanceID() const = 0;
virtual Config&
config() = 0;
virtual std::pair<PublicKey, SecretKey> const&
nodeIdentity() = 0;
[[nodiscard]] virtual std::optional<PublicKey const>
getValidationPublicKey() const = 0;
virtual std::chrono::milliseconds
getIOLatency() = 0;
virtual bool
serverOkay(std::string& reason) = 0;
/* Returns the number of file descriptors the application needs */
[[nodiscard]] virtual int
fdRequired() const = 0;
/**
* Ensure that a newly-started validator does not sign proposals older
* than the last ledger it persisted.
*/
virtual LedgerIndex
getMaxDisallowedLedger() = 0;
/**
* Returns the number of io_context (I/O worker) threads used by the application.
*/
[[nodiscard]] virtual size_t
getNumberOfThreads() const = 0;
};
std::unique_ptr<Application>
makeApplication(
std::unique_ptr<Config> config,
std::unique_ptr<Logs> logs,
std::unique_ptr<TimeKeeper> timeKeeper);
/**
* Construct the application with a known node public key.
*
* Telemetry builds its resource attributes during construction and they are
* immutable, so the base58 node public key must be supplied here. Pass
* std::nullopt when it is unknown; that run reports no instance id. See
* resolveNodePublicKey().
*/
std::unique_ptr<Application>
makeApplication(
std::unique_ptr<Config> config,
std::unique_ptr<Logs> logs,
std::unique_ptr<TimeKeeper> timeKeeper,
std::optional<std::string> const& nodePublicKey);
} // namespace xrpl