Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MDAPI-211][C++] Implement logging management. #64

Merged
merged 2 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ set(dxFeedGraalCxxApi_Isolated_Sources
src/isolated/ipf/IsolatedInstrumentProfileReader.cpp
src/isolated/ipf/live/IsolatedInstrumentProfileCollector.cpp
src/isolated/ipf/live/IsolatedInstrumentProfileConnection.cpp
src/isolated/logging/IsolatedLogging.cpp
src/isolated/model/IsolatedTxModelListener.cpp
src/isolated/model/IsolatedIndexedTxModel.cpp
src/isolated/model/IsolatedTimeSeriesTxModel.cpp
Expand Down Expand Up @@ -267,6 +268,10 @@ set(dxFeedGraalCxxApi_Ipf_Sources
src/ipf/live/IterableInstrumentProfile.cpp
)

set(dxFeedGraalCxxApi_Logging_Sources
src/logging/Logging.cpp
)

set(dxFeedGraalCxxApi_Model_Sources
src/model/TxModelListener.cpp
src/model/IndexedTxModel.cpp
Expand Down Expand Up @@ -376,6 +381,7 @@ set(dxFeedGraalCxxApi_Sources
${dxFeedGraalCxxApi_ApiOsub_Sources}
${dxFeedGraalCxxApi_Auth_Sources}
${dxFeedGraalCxxApi_Ipf_Sources}
${dxFeedGraalCxxApi_Logging_Sources}
${dxFeedGraalCxxApi_Model_Sources}
${dxFeedGraalCxxApi_OnDemand_Sources}
${dxFeedGraalCxxApi_Promise_Sources}
Expand Down
2 changes: 2 additions & 0 deletions ReleaseNotes.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
* **\[MDAPI-211]\[C++]** Implement logging management
* Added `Logging` class.
* **\[MDAPI-82]\[C++]** Implement MarketDepthModel
* Added `MarketDepthModel` class.
* Added `MarketDepthModelListener` class.
Expand Down
3 changes: 3 additions & 0 deletions include/dxfeed_graal_cpp_api/api.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251 4996)
#include "isolated/ipf/live/IsolatedInstrumentProfileCollector.hpp"
#include "isolated/ipf/live/IsolatedInstrumentProfileConnection.hpp"
#include "isolated/ipf/IsolatedInstrumentProfileReader.hpp"
#include "isolated/logging/IsolatedLogging.hpp"
#include "isolated/model/IsolatedTxModelListener.hpp"
#include "isolated/model/IsolatedIndexedTxModel.hpp"
#include "isolated/model/IsolatedTimeSeriesTxModel.hpp"
Expand All @@ -84,6 +85,8 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251 4996)
#include "isolated/schedule/IsolatedSession.hpp"
#include "isolated/schedule/IsolatedSchedule.hpp"

#include "logging/Logging.hpp"

#include "ondemand/OnDemandService.hpp"

#include "promise/Promise.hpp"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

#include "../../internal/Common.hpp"

#include <dxfeed_graal_cpp_api/event/EventTypeEnum.hpp>

DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251)

DXFCPP_BEGIN_NAMESPACE
Expand Down
38 changes: 38 additions & 0 deletions include/dxfeed_graal_cpp_api/isolated/logging/IsolatedLogging.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) 2024 Devexperts LLC.
// SPDX-License-Identifier: MPL-2.0

#pragma once

#include "../../internal/Conf.hpp"

#include "../../logging/Logging.hpp"
#include "dxfeed_graal_cpp_api/internal/JavaObjectHandle.hpp"

#include <cstdint>
#include <string>
#include <vector>

DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251)

DXFCPP_BEGIN_NAMESPACE

namespace isolated::logging::IsolatedLogging {

// int32_t dxfg_logging_listener_new(graal_isolatethread_t *thread, dxfg_logging_listener_function_t user_func,
// void *user_data, DXFG_OUT dxfg_logging_listener_t **listener);
JavaObjectHandle<Logging::ListenerTag> createListener(void* userFunc, void* userData);

// int32_t dxfg_logging_set_listener(graal_isolatethread_t *thread, dxfg_logging_listener_t *listener);
void setListener(const JavaObjectHandle<Logging::ListenerTag>& listener);

//int32_t dxfg_logging_set_log_level(graal_isolatethread_t *thread, dxfg_logging_level_t level);
void setLogLevel(Logging::Level level);

//int32_t dxfg_logging_set_err_level(graal_isolatethread_t *thread, dxfg_logging_level_t level);
void setErrFileLevel(Logging::Level level);

}

DXFCPP_END_NAMESPACE

DXFCXX_DISABLE_MSC_WARNINGS_POP()
112 changes: 112 additions & 0 deletions include/dxfeed_graal_cpp_api/logging/Logging.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// Copyright (c) 2024 Devexperts LLC.
// SPDX-License-Identifier: MPL-2.0

#pragma once

#include "../internal/Conf.hpp"
#include "dxfeed_graal_cpp_api/internal/Handler.hpp"

DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251)

#include "../internal/Common.hpp"

DXFCPP_BEGIN_NAMESPACE

/**
*
*/
struct DXFCPP_EXPORT Logging final {
struct ListenerTag {};
/**
* Defines a set of standard logging levels that can be used to control logging output.
*/
enum class Level {
/// Indicates that all messages should be logged.
ALL = 0,

/// Indicates a highly detailed tracing message.
TRACE,

/// Is a message level providing tracing debug information.
DEBUG,

/// Is a message level for informational messages.
INFO,

/// Is a message level indicating a potential problem.
WARN,

/// Is a message level indicating a serious failure.
ERROR,

/// Is a special level that can be used to turn off logging.
OFF,
};

static std::string levelToString(Level level);

private:
static SimpleHandler<void(Level, std::int64_t /*timestamp*/, const std::string & /*threadName*/,
std::int64_t /*threadId*/, const std::string & /*loggerName*/,
const std::string & /*message*/)>
handler_;

struct Impl;

public:
/**
* Initializes logging and sets the logging level.
*
* This is equivalent to the following code:
*
* ```cpp
* System::setProperty("log.className", "com.devexperts.logging.InterceptableLogging");
* System::setProperty("log.level", levelToString(level));
* System::setProperty("err.level", levelToString(level));
* ```
* @param level The logging level.
*/
static void init(Level level = Level::OFF);

/**
* Initializes logging, sets the path to the logging file and the logging level.
*
* This is equivalent to the following code:
*
* ```cpp
* System::setProperty("log.className", "com.devexperts.logging.InterceptableLogging");
* System::setProperty("log.file", logFile);
* System::setProperty("log.level", levelToString(logLevel));
* ```
*
* @param logFile The logging file.
* @param logLevel The logging level.
*/
static void init(const std::string &logFile, Level logLevel = Level::INFO);

/**
* Initializes logging, sets the path to the file for logging, to the file for outputting errors and warnings, and
* sets the logging level for both files.
*
* This is equivalent to the following code:
*
* ```cpp
* System::setProperty("log.className", "com.devexperts.logging.InterceptableLogging");
* System::setProperty("log.file", logFile);
* System::setProperty("log.level", levelToString(logLevel));
* System::setProperty("err.file", errFile);
* System::setProperty("err.level", levelToString(errFileLevel));
* ```
*
* @param logFile The logging file.
* @param errFile The err file.
* @param logLevel The logging level.
* @param errFileLevel The err file logging level.
*/
static void init(const std::string &logFile, const std::string &errFile, Level logLevel = Level::INFO,
Level errFileLevel = Level::WARN);
};

DXFCPP_END_NAMESPACE

DXFCXX_DISABLE_MSC_WARNINGS_POP()
2 changes: 2 additions & 0 deletions src/internal/JavaObjectHandle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,6 @@ template struct JavaObjectHandle<TimeSeriesTxModel::Builder>;

template struct JavaObjectHandle<ExecutorTag>;

template struct JavaObjectHandle<Logging::ListenerTag>;

DXFCPP_END_NAMESPACE
54 changes: 54 additions & 0 deletions src/isolated/logging/IsolatedLogging.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright (c) 2024 Devexperts LLC.
// SPDX-License-Identifier: MPL-2.0

#include <dxfg_api.h>

#include <dxfeed_graal_cpp_api/isolated/IsolatedCommon.hpp>
#include <dxfeed_graal_cpp_api/isolated/internal/IsolatedString.hpp>
#include <dxfeed_graal_cpp_api/isolated/logging/IsolatedLogging.hpp>

DXFCPP_BEGIN_NAMESPACE

namespace isolated::logging::IsolatedLogging {

// int32_t dxfg_logging_listener_new(graal_isolatethread_t *thread, dxfg_logging_listener_function_t user_func,
// void *user_data, DXFG_OUT dxfg_logging_listener_t **listener);
JavaObjectHandle<Logging::ListenerTag> createListener(void *userFunc, void *userData) {
if (!userFunc) {
throw InvalidArgumentException("Unable to execute function `dxfg_logging_listener_new`. The "
"`userFunc` is nullptr");
}

dxfg_logging_listener_t *isolatedListener{};

runGraalFunctionAndThrowIfMinusOne(dxfg_logging_listener_new,
dxfcpp::bit_cast<dxfg_logging_listener_function_t>(userFunc), userData,
&isolatedListener);

return JavaObjectHandle<Logging::ListenerTag>(isolatedListener);
}

// int32_t dxfg_logging_set_listener(graal_isolatethread_t *thread, dxfg_logging_listener_t *listener);
void setListener(const JavaObjectHandle<Logging::ListenerTag> &listener) {
if (!listener) {
throw InvalidArgumentException("Unable to execute function `dxfg_logging_set_listener`. The "
"`listener` handle is invalid");
}

runGraalFunctionAndThrowIfMinusOne(dxfg_logging_set_listener,
dxfcpp::bit_cast<dxfg_logging_listener_t *>(listener.get()));
}

// int32_t dxfg_logging_set_log_level(graal_isolatethread_t *thread, dxfg_logging_level_t level);
void setLogLevel(Logging::Level level) {
runGraalFunctionAndThrowIfMinusOne(dxfg_logging_set_log_level, static_cast<dxfg_logging_level_t>(level));
}

// int32_t dxfg_logging_set_err_level(graal_isolatethread_t *thread, dxfg_logging_level_t level);
void setErrFileLevel(Logging::Level level) {
runGraalFunctionAndThrowIfMinusOne(dxfg_logging_set_err_level, static_cast<dxfg_logging_level_t>(level));
}

} // namespace isolated::logging::IsolatedLogging

DXFCPP_END_NAMESPACE
98 changes: 98 additions & 0 deletions src/logging/Logging.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// Copyright (c) 2024 Devexperts LLC.
// SPDX-License-Identifier: MPL-2.0

#include <dxfeed_graal_cpp_api/logging/Logging.hpp>
#include <dxfeed_graal_cpp_api/system/System.hpp>

#include <dxfg_api.h>

#include <dxfeed_graal_cpp_api/isolated/event/IsolatedEventType.hpp>
#include <dxfeed_graal_cpp_api/isolated/internal/IsolatedObject.hpp>
#include <dxfeed_graal_cpp_api/isolated/logging/IsolatedLogging.hpp>
#include <utility>

DXFCPP_BEGIN_NAMESPACE

std::string Logging::levelToString(Level level) {
switch (level) {
case Level::ALL:
return "ALL";
case Level::TRACE:
return "TRACE";
case Level::DEBUG:
return "DEBUG";
case Level::INFO:
return "INFO";
case Level::WARN:
return "WARN";
case Level::ERROR:
return "ERROR";
case Level::OFF:
return "OFF";
}

return "UNKNOWN";
}

SimpleHandler<void(Logging::Level, std::int64_t /*timestamp*/, const std::string & /*threadName*/,
std::int64_t /*threadId*/, const std::string & /*loggerName*/, const std::string & /*message*/)>
Logging::handler_{};

struct Logging::Impl {
static JavaObjectHandle<Logging::ListenerTag> listenerHandle;

static void onLog(graal_isolatethread_t * /*thread*/, dxfg_logging_level_t level, int64_t timestamp,
const char *threadName, int64_t threadId, const char *loggerName, const char *message,
dxfg_exception_t * /*exception*/, const char * /*formattedMessage*/, void * /*userData*/) {
handler_(static_cast<Level>(level), timestamp, threadName, threadId, loggerName, message);
}
};

JavaObjectHandle<Logging::ListenerTag> Logging::Impl::listenerHandle{};

void Logging::init(Level level) {
System::setProperty("log.className", "com.devexperts.logging.InterceptableLogging");
System::setProperty("log.level", levelToString(level));
System::setProperty("err.level", levelToString(level));
}

void Logging::init(const std::string &logFile, Level logLevel) {
System::setProperty("log.className", "com.devexperts.logging.InterceptableLogging");
System::setProperty("log.file", logFile);
System::setProperty("log.level", levelToString(logLevel));
}

void Logging::init(const std::string &logFile, const std::string &errFile, Level logLevel, Level errFileLevel) {
System::setProperty("log.className", "com.devexperts.logging.InterceptableLogging");
System::setProperty("log.file", logFile);
System::setProperty("log.level", levelToString(logLevel));
System::setProperty("err.file", errFile);
System::setProperty("err.level", levelToString(errFileLevel));
}

// void Logging::setListener(std::function<void(Level, std::int64_t, const std::string &, std::int64_t,
// const std::string &, const std::string &)>
// listener) {
// static auto id = static_cast<std::size_t>(-1);
//
// if (id != static_cast<std::size_t>(-1)) {
// handler_ -= id;
// }
//
// id = handler_ += std::move(listener);
//
// if (!Impl::listenerHandle) {
// Impl::listenerHandle =
// isolated::logging::IsolatedLogging::createListener(dxfcpp::bit_cast<void *>(&Impl::onLog), nullptr);
// }
// }
//
// void Logging::setLogLevel(Level level) {
// isolated::logging::IsolatedLogging::setLogLevel(level);
// }
//
// void Logging::setErrFileLevel(Level level) {
// isolated::logging::IsolatedLogging::setErrFileLevel(level);
// }

DXFCPP_END_NAMESPACE