Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,13 @@ source files for evidence.
- If Functions exist, isolate them in a `<name>func/` subpackage with a narrow
`Deps` interface declared there. The Function package MUST NOT import the
collector package or hold `*Collector`.
- If a single-instance collector exposes `AgentWide` module `Methods`, its
`MethodHandler(job)` receives the running canonical runtime job. Use
`job.Collector()` to bind the Function handler to collector-owned state; do
not add a `__job` parameter or introduce a package-global registry to bridge
Function dispatch. During method execution, when the singleton job is not
running, the framework returns an unavailable response before calling
`MethodHandler`.
- `collectorapi.Creator.InstancePolicy` defaults to
`InstancePolicyPerJob`. Use `InstancePolicySingle` only for collectors that
are intentionally one canonical job per agent. Single-instance configs MUST
Expand Down
2 changes: 1 addition & 1 deletion .agents/sow/specs/snmp-traps/netdata.md
Original file line number Diff line number Diff line change
Expand Up @@ -784,7 +784,7 @@ _HOSTNAME=<the source device hostname from enrichment, or source IP when enrichm

`_HOSTNAME` is normally a systemd "trusted field" set by journald; the trap plugin's journal writer writes directly to journal files through the Go-compatible backend selected in SOW-0035 M1 (bypassing journald) and controls every field, including `_HOSTNAME`. The hostname resolution priority is:

1. **Vnode hostname** — when the SNMP polling job has an explicit `vnode.hostname` configured for the source device (available in the in-process `DeviceRegistry` as `VnodeHostname`).
1. **Vnode hostname** — when the SNMP polling job has an explicit `vnode.hostname` configured for the source device (available from the injected SNMP device store as `VnodeHostname`).
2. **SNMP sysName** — the device's self-reported `sysName` from polling state, unless empty or equal to literal `"unknown"` (case-insensitive).
3. **SNMP/topology sysName** — the source device `sysName` from the topology cache when the trap source IP matches topology-managed IP state and the direct SNMP registry lookup missed, for example when the SNMP collector target was configured by DNS name but traps arrive from an IP.
4. **Source IP** — the string form of the validated trap source IP. `_HOSTNAME` is always emitted; the source IP is the mandatory fallback when no enrichment identity exists.
Expand Down
8 changes: 6 additions & 2 deletions src/aclk/aclk.c
Original file line number Diff line number Diff line change
Expand Up @@ -1128,8 +1128,9 @@ char *aclk_state(void)
}

if (aclk_is_online) {
buffer_sprintf(wb, "Received Cloud MQTT Messages: %d\nMQTT Messages Confirmed by Remote Broker (PUBACKs): %d\nPending PUBACKS: %d\n",
aclk_rcvd_cloud_msgs, aclk_pubacks_per_conn, aclk_stats.mqtt.packets_waiting_puback);
buffer_sprintf(wb, "Received Cloud MQTT Messages: %d\nMQTT Messages Confirmed by Remote Broker (PUBACKs): %d\nPending PUBACKS: %d\nServer Receive Maximum: %u\n",
aclk_rcvd_cloud_msgs, aclk_pubacks_per_conn, aclk_stats.mqtt.packets_waiting_puback,
(unsigned)aclk_stats.mqtt.rx_maximum);

RRDHOST *host;
rrd_rdlock();
Expand Down Expand Up @@ -1269,6 +1270,9 @@ char *aclk_state_json(void)
tmp = json_object_new_int((int32_t) aclk_stats.mqtt.packets_waiting_puback);
json_object_object_add(msg, "pending-mqtt-pubacks", tmp);

tmp = json_object_new_int((int32_t) aclk_stats.mqtt.rx_maximum);
json_object_object_add(msg, "server-receive-maximum", tmp);

tmp = json_object_new_int(aclk_connection_counter > 0 ? (aclk_connection_counter - 1) : 0);
json_object_object_add(msg, "reconnect-count", tmp);

Expand Down
2 changes: 2 additions & 0 deletions src/aclk/mqtt_websockets/common_public.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ struct mqtt_ng_stats {
int tx_messages_sent;
int rx_messages_rcvd;
int packets_waiting_puback;
// MQTT 5.0 server Receive Maximum from CONNACK (max concurrent unacked QoS1/2); 65535 if unset
uint16_t rx_maximum;
size_t tx_buffer_used;
size_t tx_buffer_free;
size_t tx_buffer_size;
Expand Down
12 changes: 12 additions & 0 deletions src/aclk/mqtt_websockets/mqtt_ng.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,9 @@ struct mqtt_ng_client {
c_rhash rx_aliases;

size_t max_msg_size;

// MQTT 5.0 server Receive Maximum (CONNACK prop 0x21); absent => 65535 default [MQTT-3.2.2.3.3]
uint16_t rx_maximum;
};

usec_t publish_latency;
Expand Down Expand Up @@ -630,6 +633,9 @@ struct mqtt_ng_client *mqtt_ng_init(struct mqtt_ng_init *settings)
client->tx_topic_aliases.stoi_dict = TX_ALIASES_INITIALIZE();
client->tx_topic_aliases.idx_max = UINT16_MAX;

// MQTT 5.0 default Receive Maximum when the server omits the property [MQTT-3.2.2.3.3]
__atomic_store_n(&client->rx_maximum, UINT16_MAX, __ATOMIC_RELAXED);

// TODO just embed the struct into mqtt_ng_client
client->parser.received_data = settings->data_in;
client->send_fnc_ptr = settings->data_out_fnc;
Expand Down Expand Up @@ -2144,6 +2150,11 @@ int handle_incoming_traffic(struct mqtt_ng_client *client)
client->max_msg_size = prop->data.uint32;
}

if ((prop = get_property_by_id(client->parser.properties_parser.head, MQTT_PROP_RECEIVE_MAX)) != NULL) {
nd_log(NDLS_DAEMON, NDLP_INFO, "ACLK: MQTT server receive maximum is %" PRIu16, prop->data.uint16);
__atomic_store_n(&client->rx_maximum, prop->data.uint16, __ATOMIC_RELAXED);
}

if (client->connack_callback)
client->connack_callback(client->user_ctx, client->parser.mqtt_packet.connack.reason_code);
if (!client->parser.mqtt_packet.connack.reason_code) {
Expand Down Expand Up @@ -2300,6 +2311,7 @@ void mqtt_ng_get_stats(struct mqtt_ng_client *client, struct mqtt_ng_stats *stat
stats->tx_messages_sent = __atomic_load_n(&client->stats.tx_messages_sent, __ATOMIC_RELAXED);
stats->rx_messages_rcvd = __atomic_load_n(&client->stats.rx_messages_rcvd, __ATOMIC_RELAXED);
stats->packets_waiting_puback = __atomic_load_n(&client->stats.packets_waiting_puback, __ATOMIC_RELAXED);
stats->rx_maximum = __atomic_load_n(&client->rx_maximum, __ATOMIC_RELAXED);

stats->tx_bytes_queued = 0;
stats->tx_buffer_reclaimable = 0;
Expand Down
2 changes: 0 additions & 2 deletions src/claim/ui.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
static LPCTSTR szWindowClass = _T("DesktopApp");

static HINSTANCE hInst;
static HWND hToken;
static HWND hRoom;

LRESULT CALLBACK WndProc(HWND hNetdatawnd, UINT message, WPARAM wParam, LPARAM lParam)
{
Expand Down
2 changes: 1 addition & 1 deletion src/collectors/cgroups.plugin/cgroup-discovery.c
Original file line number Diff line number Diff line change
Expand Up @@ -794,7 +794,7 @@ static inline void discovery_update_filenames_all_cgroups() {
static inline void discovery_cleanup_all_cgroups() {
struct cgroup *cg = discovered_cgroup_root, *last = NULL;

for(; cg ;) {
while(cg) {
if(!cg->available) {
// enable the first duplicate cgroup
{
Expand Down
3 changes: 0 additions & 3 deletions src/collectors/freebsd.plugin/freebsd_sysctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -574,9 +574,6 @@ int do_hw_intcnt(int update_every, usec_t dt) {
for (i = 0; i < nintr; i++)
totalintr += intrcnt[i];

static RRDSET *st_intr = NULL;
static RRDDIM *rd_intr = NULL;

common_interrupts(totalintr, update_every, "hw.intrcnt");

size_t size;
Expand Down
14 changes: 10 additions & 4 deletions src/collectors/statsd.plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -517,14 +517,22 @@ Example of a synthetic chart combining multiple metrics:

The `[app]` section defines the application and has these options:

:::warning

The `[app]` section is a **namespace/container** — it groups metrics and sets defaults, but does **not** create any dashboard charts by itself. To see synthetic charts on the dashboard, you **must** add one or more chart definition sections (e.g., `[mychart]`) below the `[app]` section. If you only define an `[app]` section without chart definitions, the only visible charts will be private charts for individual metrics (if `private charts = yes` or the global default is enabled).

Settings like `private charts`, `gaps when not collected`, and `history` configure how the app's metrics and charts behave — they are not chart-level settings. The `memory mode` setting under `[app]` is currently ignored. See [Chart Definitions](#chart-definitions) below for how to create charts.

:::

:::note

- **name** - Defines the application name
- **metrics** - [Simple pattern](https://github.com/netdata/netdata/blob/master/src/libnetdata/simple_pattern/README.md) matching all metrics for this app
- **private charts** - Enable/disable private charts for matched metrics (yes|no)
- **gaps when not collected** - Show gaps when no metrics are collected (yes|no)
- **memory mode** - Sets memory mode for application charts (optional, default is global Netdata setting)
- **history** - Size of round-robin database (optional, only relevant with `memory mode = save`)
- **memory mode** - Ignored in the `[app]` section; application charts use the host's default memory mode
- **history** - Size of round-robin database for application charts (optional, minimum 5)

:::

Expand Down Expand Up @@ -919,7 +927,6 @@ Start with this basic configuration:
metrics = k6*
private charts = yes
gaps when not collected = no
memory mode = dbengine
```

</details>
Expand Down Expand Up @@ -957,7 +964,6 @@ Here's a complete configuration for k6:
metrics = k6*
private charts = yes
gaps when not collected = no
memory mode = dbengine

[dictionary]
http_req_blocked = Blocked HTTP Requests
Expand Down
34 changes: 34 additions & 0 deletions src/daemon/pulse/pulse-network.c
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,40 @@ void pulse_network_do(bool extended __maybe_unused) {

pulse_aclk_time_heatmap();

{
// In-flight QoS1 messages vs the broker's MQTT 5.0 Receive Maximum.
// When "in flight" approaches "receive maximum" the agent is at the
// broker's window limit. Always available (not extended) since it is
// the primary signal for the MQTT 5.0 Receive Maximum behavior.
static RRDSET *st_aclk_inflight = NULL;
static RRDDIM *rd_in_flight = NULL, *rd_receive_max = NULL;

if (unlikely(!st_aclk_inflight)) {
st_aclk_inflight = rrdset_create_localhost(
"netdata",
"aclk_mqtt_inflight",
NULL,
PULSE_NETWORK_CHART_FAMILY,
"netdata.aclk_mqtt_inflight",
"Netdata ACLK MQTT In-Flight QoS1 Window",
"messages",
"netdata",
"pulse",
PULSE_NETWORK_CHART_PRIORITY + 2,
localhost->rrd_update_every,
RRDSET_TYPE_LINE);

rrdlabels_add(st_aclk_inflight->rrdlabels, "endpoint", "aclk", RRDLABEL_SRC_AUTO);

rd_in_flight = rrddim_add(st_aclk_inflight, "in flight", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
rd_receive_max = rrddim_add(st_aclk_inflight, "receive maximum", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
}

rrddim_set_by_pointer(st_aclk_inflight, rd_in_flight, (collected_number)t.mqtt.packets_waiting_puback);
rrddim_set_by_pointer(st_aclk_inflight, rd_receive_max, (collected_number)t.mqtt.rx_maximum);
rrdset_done(st_aclk_inflight);
}

if(extended) {
static RRDSET *st_aclk_queue_size = NULL;
static RRDDIM *rd_messages = NULL;
Expand Down
5 changes: 4 additions & 1 deletion src/database/rrdhost-system-info.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
#include "daemon/win_system-info.h"

// coverity[ +tainted_string_sanitize_content : arg-0 ]
static inline void coverity_remove_taint(char *s __maybe_unused) { }
static inline void coverity_remove_taint(char *s __maybe_unused) {
// intentionally empty: only a marker for the Coverity taint sanitizer
// (see the annotation above); it has no runtime effect.
}

void rrdhost_system_info_swap(struct rrdhost_system_info *a, struct rrdhost_system_info *b) {
if(a && b)
Expand Down
Loading
Loading