Skip to content
Open
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
10 changes: 10 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,16 @@ AC_CHECK_FUNCS([memset strdup strerror])

PKG_CHECK_MODULES([LOG4C], [log4c >= 1.2.3])


dnl Log suppression feature
AC_ARG_ENABLE([log-suppression],
[AS_HELP_STRING([--enable-log-suppression], [Enable duplicate log suppression (default: no)])],
[enable_log_suppression=$enableval],
[enable_log_suppression=no])
if test "x$enable_log_suppression" = "xyes"; then
AC_DEFINE([HAVE_LOG_SUPPRESSION], [1], [Define to enable log duplicate suppression])
fi
Comment thread
jayasrikadiyal marked this conversation as resolved.
AM_CONDITIONAL([HAVE_LOG_SUPPRESSION], [test "x$enable_log_suppression" = "xyes"])
AC_CONFIG_FILES([Makefile
cfg/Makefile
src/Makefile
Expand Down
119 changes: 119 additions & 0 deletions include/rdk_log_suppression.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/*
* If not stated otherwise in this file or this component's LICENSE file the
* following copyright and licenses apply:
*
* Copyright 2026 RDK Management
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef RDK_LOG_SUPPRESSION_H
#define RDK_LOG_SUPPRESSION_H

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>
#include <stdbool.h>

/** Maximum number of tracked patterns per category */
#define RDK_SUPPRESS_RING_SIZE 8

/** Default suppression time window in seconds */
#define RDK_SUPPRESS_DEFAULT_WINDOW_SEC 30

/** Default number of repeats before suppression activates */
#define RDK_SUPPRESS_DEFAULT_THRESHOLD 3

/** Result of a suppression check */
typedef enum {
RDK_SUPPRESS_PASS = 0, /**< Message should be logged normally */
RDK_SUPPRESS_BLOCK = 1, /**< Message is suppressed (duplicate) */
RDK_SUPPRESS_EMIT_SUMMARY = 2 /**< Emit summary then log current message */
} rdk_SuppressResult;

/** Suppression statistics for a module */
typedef struct {
uint64_t total_suppressed; /**< Total messages suppressed */
uint64_t total_summaries; /**< Total summary messages emitted */
uint32_t current_repeat_count; /**< Current consecutive repeat count */
} rdk_SuppressStats;

/**
* Initialize the log suppression subsystem.
* Must be called after rdk_dbg_priv_config() during logger initialization.
* @return 0 on success, -1 on failure
*/
int rdk_log_suppression_init(void);

/**
* Deinitialize the log suppression subsystem.
* Frees all allocated suppression state.
*/
Comment on lines +60 to +63
void rdk_log_suppression_deinit(void);

/**
* Check if a log message should be suppressed.
* Called from rdk_dbg_priv_log_msg() after priority check.
*
* @param module The log category name (e.g., "LOG.RDK.TR69")
* @param level The log level of the message
* @param fmt The format string (before printf expansion)
* @param[out] repeat_count If result is EMIT_SUMMARY, set to number of suppressed messages
* @return RDK_SUPPRESS_PASS, RDK_SUPPRESS_BLOCK, or RDK_SUPPRESS_EMIT_SUMMARY
*/
rdk_SuppressResult rdk_log_suppression_check(const char *module, int level,
const char *fmt,
uint32_t *repeat_count);

/**
* Configure suppression for a specific module.
*
* @param module Module name (NULL for global default)
* @param enabled true to enable, false to disable
* @param window_sec Time window in seconds (0 = use default)
* @param threshold Messages before suppression kicks in (0 = use default)
* @return 0 on success, -1 on failure
*/
int rdk_log_suppression_configure(const char *module, bool enabled,
uint32_t window_sec, uint32_t threshold);

/**
* Get suppression statistics for a module.
*
* @param module Module name (NULL for global stats)
* @param[out] stats Filled with current statistics
* @return 0 on success, -1 if module not found
*/
int rdk_log_suppression_get_stats(const char *module, rdk_SuppressStats *stats);

/**
* Reset suppression state for a module (or all if module is NULL).
* Useful after configuration changes or for testing.
*
* @param module Module name (NULL to reset all)
*/
void rdk_log_suppression_reset(const char *module);

/**
* Check if suppression is globally enabled.
* @return true if suppression is active
*/
bool rdk_log_suppression_is_enabled(void);

#ifdef __cplusplus
}
#endif

#endif /* RDK_LOG_SUPPRESSION_H */
65 changes: 65 additions & 0 deletions scripts/logDedup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/bin/sh
##########################################################################
# If not stated otherwise in this file or this component's LICENSE
# file the following copyright and licenses apply:
#
# Copyright 2026 RDK Management
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
##########################################################################

# logDedup.sh - Deduplicate log files before upload to reduce bandwidth
# Usage: logDedup.sh [log_directory] [threshold]
#
# Processes all .log and .txt files in the specified directory,
# replacing them with deduplicated versions.

LOG_DIR="${1:-/rdklogs/logs}"
THRESHOLD="${2:-2}"
DEDUP_BIN="${DEDUP_BIN:-/usr/bin/rdkLogDedupSync}"
DEDUP_COUNT=0
Comment on lines +27 to +30

if [ ! -d "$LOG_DIR" ]; then
echo "Error: Log directory not found: $LOG_DIR"
exit 1
fi

if [ ! -x "$DEDUP_BIN" ]; then
echo "Error: Dedup binary not found or not executable: $DEDUP_BIN"
exit 1
fi

for logfile in "$LOG_DIR"/*.log "$LOG_DIR"/*.txt "$LOG_DIR"/*.txt.*; do
[ -f "$logfile" ] || continue

tmpfile="${logfile}.dedup.tmp"

"$DEDUP_BIN" "$logfile" "$tmpfile" "$THRESHOLD"
ret=$?

if [ $ret -eq 0 ]; then
# Dedup was applied - replace original
mv "$tmpfile" "$logfile"
DEDUP_COUNT=$((DEDUP_COUNT + 1))
elif [ $ret -eq 2 ]; then
# No dedup needed - tmp already removed by utility
:
else
# Error
rm -f "$tmpfile" 2>/dev/null
echo "Warning: Dedup failed for $logfile"
fi
done

echo "Log dedup complete: $DEDUP_COUNT files deduplicated in $LOG_DIR"
exit 0
3 changes: 3 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
AM_CFLAGS = -pthread -Wall -Werror
lib_LTLIBRARIES = librdkloggers.la
librdkloggers_la_SOURCES = rdk_debug.c rdk_debug_priv.c rdk_dynamic_logger.c rdk_logger_init.c rdk_logger_milestone.c rdk_logger_onboard.c
if HAVE_LOG_SUPPRESSION
librdkloggers_la_SOURCES += rdk_log_suppression.c
endif
librdkloggers_la_CFLAGS = $(LOG4C_CFLAGS) $(GLIB_CFLAGS) $(SYSTEMD_CFLAGS) -I$(top_srcdir)/include -I$(top_srcdir)/src/include -DDEBUG_CONF_FILE="\"debug.ini\""
librdkloggers_la_LDFLAGS = $(GLIB_LIBS) $(LOG4C_LIBS) $(SYSTEMD_LIBS)

Expand Down
24 changes: 21 additions & 3 deletions src/rdk_debug_priv.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,19 @@
#include "rdk_debug_priv.h"
#include "rdk_dynamic_logger.h"
#include "log4c.h"
#include <log4c/appender_type_rollingfile.h>
#include <log4c/rollingpolicy.h>
#include <log4c/rollingpolicy_type_sizewin.h>

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#ifdef HAVE_LOG_SUPPRESSION
#include "rdk_log_suppression.h"
#endif
Comment on lines +57 to +59

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. HAVE_LOG_SUPPRESSION is coming from config.h, so checking it before including config.h can compile the suppression paths out of the translation unit. This affects both src/rdk_debug_priv.c and src/rdk_logger_init.c. I’ll move the config.h include to the top of both files before any HAVE_LOG_SUPPRESSION guards.

#include <log4c/appender_type_rollingfile.h>
#include <log4c/rollingpolicy.h>
#include <log4c/rollingpolicy_type_sizewin.h>


#ifdef HAVE_SYSTEMD
#include <systemd/sd-journal.h>
#endif //HAVE_SYSTEMD
Expand Down Expand Up @@ -649,6 +654,19 @@ void rdk_dbg_priv_log_msg(rdk_LogLevel level, const char *module_name, const cha
int log4cPriority = rdk_logLevel_to_log4c_priority(level);
if (log4c_category_is_priority_enabled(cat, log4cPriority))
{
#ifdef HAVE_LOG_SUPPRESSION
uint32_t repeat_count = 0;
rdk_SuppressResult suppress_result = rdk_log_suppression_check(module_name, level, format, &repeat_count);
if (suppress_result == RDK_SUPPRESS_BLOCK)
{
pthread_mutex_unlock(&gLoggingMutex);
return;
}
if (suppress_result == RDK_SUPPRESS_EMIT_SUMMARY)
{
log4c_category_log(cat, log4cPriority, "Previous message repeated %u times", repeat_count);
}
#endif
log4c_category_vlog(cat, log4cPriority, format, args);
}
}
Expand Down
Loading
Loading