Skip to content

Commit 70aadd7

Browse files
committed
feat: add debug option to consume command
1 parent 3a86b10 commit 70aadd7

3 files changed

Lines changed: 69 additions & 7 deletions

File tree

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,15 @@ Consumed 1000 messages (1000 msg/s), bytes: 1024000, poll errors: 0
200200
...
201201
```
202202
203+
Add `--debug` to print each consumed message's metadata:
204+
205+
```bash
206+
$ snctl-cpp consume my-topic --debug
207+
Started 1 consumer on topic "my-topic" in group "snctl-cpp-my-topic-1234567890". Press Ctrl+C to stop.
208+
consumer[0] message topic=my-topic partition=0 offset=42 timestamp=2026-03-24 10:00:00.123 (create_time)
209+
...
210+
```
211+
203212
If `--group` is not provided, `snctl-cpp` generates one automatically. The
204213
default offset reset policy is `earliest`, which can be changed with
205214
`--offset-reset latest`.

include/snctl-cpp/consume.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ class ConsumeCommand final {
5252
.help("Stats report interval in milliseconds")
5353
.scan<'i', int>()
5454
.default_value(1000);
55+
command_.add_argument("--debug")
56+
.default_value(false)
57+
.implicit_value(true)
58+
.help("Print each consumed message's metadata");
5559

5660
parent.add_subparser(command_);
5761
}
@@ -67,6 +71,7 @@ class ConsumeCommand final {
6771
const auto consumer_count = command_.get<int>("--consumers");
6872
const auto offset_reset = command_.get("--offset-reset");
6973
const auto report_interval_ms = command_.get<int>("--report-interval-ms");
74+
const auto debug = command_.get<bool>("debug");
7075

7176
if (consumer_count <= 0) {
7277
throw std::invalid_argument(
@@ -162,6 +167,14 @@ class ConsumeCommand final {
162167
if (message->err == RD_KAFKA_RESP_ERR_NO_ERROR) {
163168
consumed_messages++;
164169
consumed_bytes += static_cast<uint64_t>(message->len);
170+
if (debug) {
171+
std::lock_guard<std::mutex> lock(output_mu);
172+
logging::out() << "consumer[" << consumer_index
173+
<< "] message topic=" << message_topic(message)
174+
<< " partition=" << message->partition
175+
<< " offset=" << message->offset
176+
<< " timestamp=" << message_timestamp(message);
177+
}
165178
} else if (message->err != RD_KAFKA_RESP_ERR__PARTITION_EOF) {
166179
std::lock_guard<std::mutex> lock(output_mu);
167180
logging::err() << "consumer[" << consumer_index
@@ -283,4 +296,41 @@ class ConsumeCommand final {
283296
GUARD(assignment, rd_kafka_topic_partition_list_destroy);
284297
return format_partitions(assignment);
285298
}
299+
300+
static std::string message_topic(const rd_kafka_message_t *message) {
301+
if (message == nullptr || message->rkt == nullptr) {
302+
return "(unknown)";
303+
}
304+
return rd_kafka_topic_name(message->rkt);
305+
}
306+
307+
static std::string message_timestamp(const rd_kafka_message_t *message) {
308+
if (message == nullptr) {
309+
return "(unknown)";
310+
}
311+
312+
rd_kafka_timestamp_type_t timestamp_type = RD_KAFKA_TIMESTAMP_NOT_AVAILABLE;
313+
const auto timestamp = rd_kafka_message_timestamp(message, &timestamp_type);
314+
if (timestamp < 0 || timestamp_type == RD_KAFKA_TIMESTAMP_NOT_AVAILABLE) {
315+
return "not available";
316+
}
317+
318+
const auto timestamp_time_point = std::chrono::system_clock::time_point(
319+
std::chrono::milliseconds(timestamp));
320+
return logging::format_timestamp(timestamp_time_point) + " (" +
321+
timestamp_type_name(timestamp_type) + ")";
322+
}
323+
324+
static std::string
325+
timestamp_type_name(rd_kafka_timestamp_type_t timestamp_type) {
326+
switch (timestamp_type) {
327+
case RD_KAFKA_TIMESTAMP_CREATE_TIME:
328+
return "create_time";
329+
case RD_KAFKA_TIMESTAMP_LOG_APPEND_TIME:
330+
return "log_append_time";
331+
case RD_KAFKA_TIMESTAMP_NOT_AVAILABLE:
332+
return "not_available";
333+
}
334+
return "unknown";
335+
}
286336
};

include/snctl-cpp/logging.h

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,12 @@ inline std::mutex &mutex() {
3232
return instance;
3333
}
3434

35-
inline std::string timestamp_now() {
36-
const auto now = std::chrono::system_clock::now();
37-
const auto time = std::chrono::system_clock::to_time_t(now);
38-
const auto millis =
39-
std::chrono::duration_cast<std::chrono::milliseconds>(
40-
now.time_since_epoch()) %
41-
1000;
35+
inline std::string
36+
format_timestamp(std::chrono::system_clock::time_point time_point) {
37+
const auto time = std::chrono::system_clock::to_time_t(time_point);
38+
const auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(
39+
time_point.time_since_epoch()) %
40+
1000;
4241

4342
std::tm local_time{};
4443
#if defined(_WIN32)
@@ -53,6 +52,10 @@ inline std::string timestamp_now() {
5352
return oss.str();
5453
}
5554

55+
inline std::string timestamp_now() {
56+
return format_timestamp(std::chrono::system_clock::now());
57+
}
58+
5659
inline void write_line(std::ostream &output, std::string_view message) {
5760
std::lock_guard<std::mutex> lock(mutex());
5861
output << timestamp_now() << ' ' << message << '\n';

0 commit comments

Comments
 (0)