Skip to content

Commit ca9b155

Browse files
committed
ADD: Add configurable logging to C++ client
1 parent 9aeef86 commit ca9b155

File tree

16 files changed

+271
-78
lines changed

16 files changed

+271
-78
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
- Added `strike_price`, `strike_price_currency`, and `instrument_class` to `InstrumentDefMsg`
77
- Renamed `BatchJob.cost` to `cost_usd` and value now expressed as US dollars
88
- Added `FixedPx` helper class for formatting fixed prices
9+
- Added configurable log receiver `ILogReceiver`
910
- Added `instrument_class`, `strike_price`, and `strike_price_currency` to definition schema
1011
- Added additional `condition` variants for `DatasetConditionDetail` (degraded, pending, missing)
1112
- Added additional member `last_modified_date` to `DatasetConditionDetail` Added `has_mixed_schema`, `has_mixed_stype_in`, and `ts_out` to `Metadata` to support live data

cmake/SourcesAndHeaders.cmake

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ set(headers
1414
include/databento/live.hpp
1515
include/databento/live_blocking.hpp
1616
include/databento/live_threaded.hpp
17+
include/databento/log.hpp
1718
include/databento/metadata.hpp
1819
include/databento/record.hpp
1920
include/databento/symbology.hpp
@@ -42,6 +43,7 @@ set(sources
4243
src/live.cpp
4344
src/live_blocking.cpp
4445
src/live_threaded.cpp
46+
src/log.cpp
4547
src/metadata.cpp
4648
src/record.cpp
4749
src/symbology.cpp

example/live/simple.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,30 @@
11
#include <csignal> // sig_atomic_t
22
#include <cstdint>
33
#include <iostream>
4+
#include <memory>
45
#include <unordered_map>
56

67
#include "databento/constants.hpp"
78
#include "databento/dbn.hpp"
89
#include "databento/enums.hpp"
910
#include "databento/live.hpp"
1011
#include "databento/live_threaded.hpp"
12+
#include "databento/log.hpp"
1113
#include "databento/record.hpp"
1214
#include "databento/with_ts_out.hpp"
1315

1416
static std::sig_atomic_t volatile gSignal;
1517

1618
int main() {
1719
std::unordered_map<std::uint32_t, std::string> symbol_mappings;
20+
std::unique_ptr<databento::ILogReceiver> log_receiver{
21+
new databento::ConsoleLogReceiver{databento::LogLevel::Debug}};
1822

1923
auto client = databento::LiveBuilder{}
24+
.SetLogReceiver(log_receiver.get())
2025
.SetKeyFromEnv()
2126
.SetDataset(databento::dataset::kGlbxMdp3)
2227
.BuildThreaded();
23-
std::cout << "Authenticated successfully\n";
2428

2529
// Set up signal handler for Ctrl+C
2630
std::signal(SIGINT, [](int signal) { gSignal = signal; });

include/databento/flag_set.hpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,20 @@ class FlagSet {
3232
std::uint8_t repr)
3333
: repr_{repr} {}
3434

35-
constexpr FlagSet operator~() const { return FlagSet(~repr_); }
35+
constexpr FlagSet operator~() const {
36+
return FlagSet{static_cast<Repr>(~repr_)};
37+
}
3638

3739
constexpr FlagSet operator|(FlagSet rhs) const {
38-
return FlagSet(repr_ | rhs.repr_);
40+
return FlagSet{static_cast<Repr>(repr_ | rhs.repr_)};
3941
}
4042

4143
constexpr FlagSet operator&(FlagSet rhs) const {
42-
return FlagSet(repr_ & rhs.repr_);
44+
return FlagSet{static_cast<Repr>(repr_ & rhs.repr_)};
4345
}
4446

4547
constexpr FlagSet operator^(FlagSet rhs) const {
46-
return FlagSet(repr_ ^ rhs.repr_);
48+
return FlagSet{static_cast<Repr>(repr_ ^ rhs.repr_)};
4749
}
4850

4951
FlagSet operator|=(FlagSet rhs) {

include/databento/live.hpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#include "databento/live_threaded.hpp"
77

88
namespace databento {
9+
class ILogReceiver;
10+
911
// A helper class for constructing a Live client, either an instance of
1012
// LiveBlocking or LiveThreaded.
1113
class LiveBuilder {
@@ -21,6 +23,8 @@ class LiveBuilder {
2123
LiveBuilder& SetDataset(std::string dataset);
2224
// Whether to append the gateway send timestamp after each DBN message.
2325
LiveBuilder& SetSendTsOut(bool send_ts_out);
26+
// Sets the receiver of the logs to be used by the client.
27+
LiveBuilder& SetLogReceiver(ILogReceiver* log_receiver);
2428
// Attempts to construct an instance of a blocking live client or throws an
2529
// exception.
2630
LiveBlocking BuildBlocking();
@@ -29,8 +33,9 @@ class LiveBuilder {
2933
LiveThreaded BuildThreaded();
3034

3135
private:
32-
void Validate() const;
36+
void Validate();
3337

38+
ILogReceiver* log_receiver_{};
3439
std::string key_;
3540
std::string dataset_;
3641
bool send_ts_out_{true};

include/databento/live_blocking.hpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,18 @@
1414
#include "databento/record.hpp" // Record
1515

1616
namespace databento {
17+
class ILogReceiver;
18+
1719
// A client for interfacing with Databento's real-time and intraday replay
1820
// market data API. This client provides a blocking API for getting the next
1921
// record. Unlike Historical, each instance of LiveBlocking is associated with a
2022
// particular dataset.
2123
class LiveBlocking {
2224
public:
23-
LiveBlocking(std::string key, std::string dataset, bool send_ts_out);
24-
LiveBlocking(std::string key, std::string dataset, std::string gateway,
25-
std::uint16_t port, bool send_ts_out);
25+
LiveBlocking(ILogReceiver* log_receiver, std::string key, std::string dataset,
26+
bool send_ts_out);
27+
LiveBlocking(ILogReceiver* log_receiver, std::string key, std::string dataset,
28+
std::string gateway, std::uint16_t port, bool send_ts_out);
2629
/*
2730
* Getters
2831
*/
@@ -65,16 +68,17 @@ class LiveBlocking {
6568

6669
private:
6770
std::string DetermineGateway() const;
68-
std::string Authenticate();
71+
std::uint64_t Authenticate();
6972
std::string DecodeChallenge();
7073
std::string GenerateCramReply(const std::string& challenge_key);
7174
std::string EncodeAuthReq(const std::string& auth);
72-
void DecodeAuthResp();
75+
std::uint64_t DecodeAuthResp();
7376
detail::TcpClient::Result FillBuffer(std::chrono::milliseconds timeout);
7477
RecordHeader* BufferRecordHeader();
7578

7679
static constexpr std::size_t kMaxStrLen = 24L * 1024;
7780

81+
ILogReceiver* log_receiver_;
7882
std::string key_;
7983
std::string dataset_;
8084
std::string gateway_;
@@ -83,7 +87,7 @@ class LiveBlocking {
8387
std::array<char, kMaxStrLen> buffer_{};
8488
std::size_t buffer_size_{};
8589
std::size_t buffer_idx_{};
86-
std::string session_id_;
90+
std::uint64_t session_id_;
8791
Record current_record_{nullptr};
8892
};
8993
} // namespace databento

include/databento/live_threaded.hpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,18 @@
1313
#include "databento/timeseries.hpp" // MetadataCallback, RecordCallback
1414

1515
namespace databento {
16+
class ILogReceiver;
17+
1618
// A client for interfacing with Databento's real-time and intraday replay
1719
// market data API. This client provides a threaded event-driven API for
1820
// receiving the next record. Unlike Historical, each instance of LiveThreaded
1921
// is associated with a particular dataset.
2022
class LiveThreaded {
2123
public:
22-
LiveThreaded(std::string key, std::string dataset, bool send_ts_out);
23-
LiveThreaded(std::string key, std::string dataset, std::string gateway,
24-
std::uint16_t port, bool send_ts_out);
24+
LiveThreaded(ILogReceiver* log_receiver, std::string key, std::string dataset,
25+
bool send_ts_out);
26+
LiveThreaded(ILogReceiver* log_receiver, std::string key, std::string dataset,
27+
std::string gateway, std::uint16_t port, bool send_ts_out);
2528
LiveThreaded(const LiveThreaded&) = delete;
2629
LiveThreaded& operator=(const LiveThreaded&) = delete;
2730
LiveThreaded(LiveThreaded&& other) noexcept;

include/databento/log.hpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#pragma once
2+
3+
#include <cstdint>
4+
#include <iosfwd> // ostream
5+
#include <string>
6+
7+
namespace databento {
8+
enum class LogLevel : std::uint8_t {
9+
Debug,
10+
Info,
11+
Warning,
12+
Error,
13+
};
14+
15+
class ILogReceiver {
16+
public:
17+
static ILogReceiver* Default();
18+
19+
virtual ~ILogReceiver() = default;
20+
21+
virtual void Receive(databento::LogLevel level, const std::string& msg) = 0;
22+
};
23+
24+
class NullLogReceiver : public ILogReceiver {
25+
public:
26+
void Receive(databento::LogLevel, const std::string&) override {}
27+
};
28+
29+
class ConsoleLogReceiver : public ILogReceiver {
30+
public:
31+
ConsoleLogReceiver();
32+
explicit ConsoleLogReceiver(LogLevel min_level);
33+
explicit ConsoleLogReceiver(std::ostream& stream);
34+
ConsoleLogReceiver(LogLevel min_level, std::ostream& stream);
35+
36+
void Receive(LogLevel level, const std::string& msg) override;
37+
38+
private:
39+
std::ostream& stream_;
40+
const databento::LogLevel min_level_;
41+
};
42+
} // namespace databento

src/live.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "databento/exceptions.hpp" // InvalidArgumentError, LiveApiError
77
#include "databento/live_blocking.hpp" // LiveBlocking
88
#include "databento/live_threaded.hpp" // LiveThreaded
9+
#include "databento/log.hpp"
910

1011
using databento::LiveBuilder;
1112

@@ -38,21 +39,30 @@ LiveBuilder& LiveBuilder::SetSendTsOut(bool send_ts_out) {
3839
return *this;
3940
}
4041

42+
LiveBuilder& LiveBuilder::SetLogReceiver(
43+
databento::ILogReceiver* log_receiver) {
44+
log_receiver_ = log_receiver;
45+
return *this;
46+
}
47+
4148
databento::LiveBlocking LiveBuilder::BuildBlocking() {
4249
Validate();
43-
return databento::LiveBlocking{key_, dataset_, send_ts_out_};
50+
return databento::LiveBlocking{log_receiver_, key_, dataset_, send_ts_out_};
4451
}
4552

4653
databento::LiveThreaded LiveBuilder::BuildThreaded() {
4754
Validate();
48-
return databento::LiveThreaded{key_, dataset_, send_ts_out_};
55+
return databento::LiveThreaded{log_receiver_, key_, dataset_, send_ts_out_};
4956
}
5057

51-
void LiveBuilder::Validate() const {
58+
void LiveBuilder::Validate() {
5259
if (key_.empty()) {
5360
throw Exception{"'key' is unset"};
5461
}
5562
if (dataset_.empty()) {
5663
throw Exception{"'dataset' is unset"};
5764
}
65+
if (log_receiver_ == nullptr) {
66+
log_receiver_ = databento::ILogReceiver::Default();
67+
}
5868
}

0 commit comments

Comments
 (0)