Skip to content

Commit

Permalink
Merge pull request #17 from tlm-solutions/prometheus_metrics
Browse files Browse the repository at this point in the history
Implement metrics for the Upper MAC
  • Loading branch information
marenz2569 committed Jun 19, 2024
2 parents c13c61d + 50b3d7c commit 824338d
Show file tree
Hide file tree
Showing 38 changed files with 1,749 additions and 985 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ add_executable(tetra-decoder
src/main.cpp
src/reporter.cpp
src/decoder.cpp
src/streaming_ordered_output_thread_pool_executor.cpp
src/bit_stream_decoder.cpp
src/iq_stream_decoder.cpp
src/prometheus.cpp
Expand All @@ -19,6 +18,7 @@ add_executable(tetra-decoder
src/l2/lower_mac.cpp
src/l2/slot.cpp
src/l2/timebase_counter.cpp
src/l2/upper_mac.cpp
src/l2/upper_mac_packet.cpp
src/l2/upper_mac_packet_builder.cpp
src/l2/upper_mac_packet_formatter.cpp
Expand Down
17 changes: 17 additions & 0 deletions docs/metrics.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Metrics

This TETRA reception stack comes with a lot of usefull metrics for monitoring the health and troughput of a cell.
All metrics are available through a prometheus exposer configurable with the command line arguments `--prometheus-address` and `--prometheus-name`.

Following metrics are supported:

| Metric name | Type | Description | Labels |
|---|---|---|---|
| `burst_received_count` | Counter | Counters for received bursts | `burst_type`: The type of received burst |
| `burst_lower_mac_decode_error_count` | Counter | Counters for decoding errors on received bursts in the lower MAC | `burst_type`: The type of received burst |
| `burst_lower_mac_mismatch_count` | Counter | Counters for mismatched number of bursts in the downlink lower MAC | `mismatch_type`: Any of `Skipped` or `Too many` |
| `lower_mac_time_gauge` | Gauge | Gauges for the network time | `type`: Any of `Synchronization Burst` or `Prediction` |
| `upper_mac_total_slot_count` | Counter | Counters for all received slots | `logical_channel`: The logical channel that is contained in the slot. |
| `upper_mac_slot_error_count` | Counter | Counters for all received slots with errors | `logical_channel`: The logical channel that is contained in the slot. `error_type`: Any of `CRC Error` or `Decode Error`. This includes errors in decoding for the upper mac or any layer on above. Errors in decoding reconstructed fragments are reported in the slot of the last fragment. |
| `upper_mac_fragment_count` | Counter | Counters for all received c-plane fragments | `type`: Any of `Continous` or `Stealing Channel`. `counter_type`: Any of `All` or `Reconstuction Error`. If there was a disallowed state transition in the reconstruction, the counter is incremented. Additional for `Stealing Channel` the counter is incremented if the fragment was not finalized across the stealing channel. |
| `protocol`_`packet_count` | Counter | Counter for all received packets in a protocol layer. | `protocol`: Any of `upper_mac`, `c_plane_signalling` (Before reconstruction. Start fragments are seperated), `logical_link_control`, `mobile_link_entity`, `circuit_mode_control_entity`, `mobile_management` or `short_data_service`. `packet_type`: The packet types of the specific protocol. |
18 changes: 12 additions & 6 deletions include/bit_stream_decoder.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2022 Transit Live Mapping Solutions
* Copyright (C) 2022-2024 Transit Live Mapping Solutions
* All rights reserved.
*
* Authors:
Expand All @@ -9,11 +9,11 @@

#pragma once

#include "l2/lower_mac.hpp"
#include "streaming_ordered_output_thread_pool_executor.hpp"
#include <memory>
#include <vector>

#include <l2/lower_mac.hpp>

/**
* Tetra downlink decoder for PI/4-DQPSK modulation
*
Expand All @@ -34,8 +34,11 @@
*/
class BitStreamDecoder {
public:
BitStreamDecoder(std::shared_ptr<LowerMac> lower_mac, bool is_uplink)
: lower_mac_(std::move(lower_mac))
BitStreamDecoder(
const std::shared_ptr<StreamingOrderedOutputThreadPoolExecutor<LowerMac::return_type>>& lower_mac_worker_queue,
const std::shared_ptr<LowerMac>& lower_mac, bool is_uplink)
: lower_mac_worker_queue_(lower_mac_worker_queue)
, lower_mac_(lower_mac)
, is_uplink_(is_uplink){};
~BitStreamDecoder() = default;

Expand All @@ -53,7 +56,10 @@ class BitStreamDecoder {
void process_bit(uint8_t symbol) noexcept;

private:
std::shared_ptr<LowerMac> lower_mac_{};
/// The pointer to the worker queue
std::shared_ptr<StreamingOrderedOutputThreadPoolExecutor<LowerMac::return_type>> lower_mac_worker_queue_;

std::shared_ptr<LowerMac> lower_mac_;

bool is_synchronized_ = false;
bool is_uplink_{};
Expand Down
19 changes: 12 additions & 7 deletions include/decoder.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2022 Transit Live Mapping Solutions
* Copyright (C) 2022-2024 Transit Live Mapping Solutions
* All rights reserved.
*
* Authors:
Expand All @@ -9,6 +9,7 @@

#pragma once

#include "l2/upper_mac.hpp"
#include <memory>
#include <optional>
#include <string>
Expand Down Expand Up @@ -41,16 +42,20 @@ class Decoder {
Decoder(unsigned int receive_port, unsigned int send_port, bool packed, std::optional<std::string> input_file,
std::optional<std::string> output_file, bool iq_or_bit_stream,
std::optional<unsigned int> uplink_scrambling_code,
std::shared_ptr<PrometheusExporter>& prometheus_exporter);
const std::shared_ptr<PrometheusExporter>& prometheus_exporter);
~Decoder();

void main_loop();

private:
std::shared_ptr<LowerMac> lower_mac_{};
std::shared_ptr<Reporter> reporter_{};
std::shared_ptr<BitStreamDecoder> bit_stream_decoder_{};
std::unique_ptr<IQStreamDecoder> iq_stream_decoder_{};
/// The worker queue for the lower mac
std::shared_ptr<StreamingOrderedOutputThreadPoolExecutor<LowerMac::return_type>> lower_mac_work_queue_;

/// The reference to the upper mac thread class
std::unique_ptr<UpperMac> upper_mac_;

std::shared_ptr<BitStreamDecoder> bit_stream_decoder_;
std::unique_ptr<IQStreamDecoder> iq_stream_decoder_;

bool packed_ = false;

Expand All @@ -67,5 +72,5 @@ class Decoder {
// bit stream -> false
bool iq_or_bit_stream_;

const std::size_t kRX_BUFFER_SIZE = 4096;
static const std::size_t kRX_BUFFER_SIZE = 4096;
};
15 changes: 6 additions & 9 deletions include/iq_stream_decoder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

#include <complex>
#include <memory>
#include <thread>

#include <bit_stream_decoder.hpp>
#include <fixed_queue.hpp>
Expand All @@ -26,17 +25,17 @@
*/
class IQStreamDecoder {
public:
IQStreamDecoder(std::shared_ptr<LowerMac> lower_mac, std::shared_ptr<BitStreamDecoder> bit_stream_decoder,
bool is_uplink);
~IQStreamDecoder();
IQStreamDecoder(
const std::shared_ptr<StreamingOrderedOutputThreadPoolExecutor<LowerMac::return_type>>& lower_mac_worker_queue,
const std::shared_ptr<LowerMac>& lower_mac, const std::shared_ptr<BitStreamDecoder>& bit_stream_decoder,
bool is_uplink);
~IQStreamDecoder() = default;

void process_complex(std::complex<float> symbol) noexcept;

private:
using QueueT = FixedQueue<std::complex<float>, 300>;

void upperMacWorker();

static std::complex<float> hard_decision(std::complex<float> const& symbol);

template <class iterator_type> static void symbols_to_bitstream(iterator_type it, uint8_t* bits, std::size_t len);
Expand Down Expand Up @@ -71,7 +70,5 @@ class IQStreamDecoder {

bool is_uplink_{};

std::shared_ptr<StreamingOrderedOutputThreadPoolExecutor<std::vector<std::function<void()>>>> thread_pool_;

std::thread upper_mac_worker_thread_;
std::shared_ptr<StreamingOrderedOutputThreadPoolExecutor<LowerMac::return_type>> lower_mac_worker_queue_;
};
20 changes: 10 additions & 10 deletions include/l2/logical_channel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,23 @@
#include "utils/bit_vector.hpp"

enum class LogicalChannel {
kSignalingChannelHalfDownlink,
kSignalingChannelHalfUplink,
kSignallingChannelHalfDownlink,
kSignallingChannelHalfUplink,
kTrafficChannel,
kSignalingChannelFull,
kSignallingChannelFull,
kStealingChannel
};

constexpr auto to_string(LogicalChannel channel) noexcept -> const char* {
switch (channel) {
case LogicalChannel::kSignalingChannelHalfDownlink:
return "SignalingChannelHalfDownlink";
case LogicalChannel::kSignalingChannelHalfUplink:
return "SignalingChannelHalfUplink";
case LogicalChannel::kSignallingChannelHalfDownlink:
return "SignallingChannelHalfDownlink";
case LogicalChannel::kSignallingChannelHalfUplink:
return "SignallingChannelHalfUplink";
case LogicalChannel::kTrafficChannel:
return "TrafficChannel";
case LogicalChannel::kSignalingChannelFull:
return "SignalingChannelFull";
case LogicalChannel::kSignallingChannelFull:
return "SignallingChannelFull";
case LogicalChannel::kStealingChannel:
return "StealingChannel";
}
Expand All @@ -38,6 +38,6 @@ struct LogicalChannelDataAndCrc {
LogicalChannel channel;
/// the data on the logical channel
BitVector data;
/// true if the crc of the signaling channels is ok
/// true if the crc of the signalling channels is ok
bool crc_ok;
};
73 changes: 60 additions & 13 deletions include/l2/logical_link_control.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2022 Transit Live Mapping Solutions
* Copyright (C) 2022-2024 Transit Live Mapping Solutions
* All rights reserved.
*
* Authors:
Expand All @@ -8,29 +8,74 @@

#pragma once

#include "l3/mobile_link_entity.hpp"
#include "utils/address.hpp"
#include "utils/bit_vector.hpp"
#include "utils/packet_counter_metrics.hpp"
#include <cstdint>
#include <iostream>
#include <memory>
#include <utility>
#include <vector>

#include <l3/mobile_link_entity.hpp>
#include <reporter.hpp>
#include <utils/address.hpp>
#include <utils/bit_vector.hpp>

class LogicalLinkControl {
public:
LogicalLinkControl(std::shared_ptr<Reporter> reporter, std::shared_ptr<MobileLinkEntity> mle)
: reporter_(std::move(reporter))
, mle_(std::move(mle)){};
LogicalLinkControl() = delete;
LogicalLinkControl(const std::shared_ptr<PrometheusExporter>& prometheus_exporter, Reporter&& reporter,
bool is_downlink)
: mle_(prometheus_exporter, std::move(reporter), is_downlink) {
llc_pdu_description_ = {"BL-ADATA without FCS",
"BL-DATA without FCS",
"BL-UDATA without FCS",
"BL-ACK without FCS",
"BL-ADATA with FCS",
"BL-DATA with FCS",
"BL-UDATA with FCS",
"BL-ACK with FCS",
"AL-SETUP",
"AL-DATA/AL-DATA-AR/AL-FINAL/AL-FINAL-AR",
"AL-UDATA/AL-UFINAL",
"AL-ACK/AL-RNR",
"AL-RECONNECT",
"Supplementary LLC PDU",
"Layer 2 signalling PDU",
"AL-DISC"};
supplementary_llc_pdu_description_ = {"AL-X-DATA/AL-X-DATA-AR/AL-X-FINAL/AL-X-FINAL-AR",
"AL-X-UDATA/AL-X-UFINAL", "AL-X-ACK/AL-X-RNR",
"ReservedSupplementaryLlcPdu"};
layer_2_signalling_pdu_description_ = {"L2-DATA-PRIORITY",
"L2-SCHEDULE-SYNC",
"L2-LINK-FEEDBACK-CONTROL",
"L2-LINK-FEEDBACK-INFO",
"L2-LINK-FEEDBACK-INFO-AND-RESIDUAL-DATA-PRIORITY",
"ReservedLayer2SignallingPdu5",
"ReservedLayer2SignallingPdu6",
"ReservedLayer2SignallingPdu7",
"ReservedLayer2SignallingPdu8",
"ReservedLayer2SignallingPdu9",
"ReservedLayer2SignallingPdu10",
"ReservedLayer2SignallingPdu11",
"ReservedLayer2SignallingPdu12",
"ReservedLayer2SignallingPdu13",
"ReservedLayer2SignallingPdu14",
"ReservedLayer2SignallingPdu15"};
if (prometheus_exporter) {
metrics_ = std::make_unique<PacketCounterMetrics>(prometheus_exporter, "logical_link_control");
}
};
~LogicalLinkControl() noexcept = default;

void process(Address address, BitVector& vec);

friend auto operator<<(std::ostream& stream, const LogicalLinkControl& llc) -> std::ostream&;

private:
static const auto kSupplementaryLlcPdu = 13;
static const auto kLayer2SignallingPdu = 14;

std::array<std::string, 16> llc_pdu_description_;
std::array<std::string, 4> supplementary_llc_pdu_description_;
std::array<std::string, 16> layer_2_signalling_pdu_description_;

// Basic link (acknowledged service in connectionless mode) without Frame Check Sequence
void process_bl_adata_without_fcs(Address address, BitVector& vec);
// Basic link (acknowledged service in connectionless mode) without Frame Check Sequence
Expand All @@ -46,12 +91,14 @@ class LogicalLinkControl {
void process_bl_ack_with_fcs(Address address, BitVector& vec);

void process_supplementary_llc_pdu(Address address, BitVector& vec);
void process_layer_2_signalling_pdu(Address address, BitVector& vec);

static auto compute_fcs(std::vector<uint8_t> const& data) -> uint32_t;
static auto check_fcs(BitVector& vec) -> bool;

std::shared_ptr<Reporter> reporter_{};
std::shared_ptr<MobileLinkEntity> mle_{};
MobileLinkEntity mle_;

std::unique_ptr<PacketCounterMetrics> metrics_;
};

std::ostream& operator<<(std::ostream& stream, const LogicalLinkControl& llc);
auto operator<<(std::ostream& stream, const LogicalLinkControl& llc) -> std::ostream&;
Loading

0 comments on commit 824338d

Please sign in to comment.