Copilot commented on code in PR #13262:
URL: https://github.com/apache/trafficserver/pull/13262#discussion_r3408349498
##########
include/tscore/DiagsTypes.h:
##########
@@ -220,26 +559,255 @@ class Diags : public DebugInterface
va_end(ap);
}
+ /**
+ * @brief va_list form of error().
+ *
+ * @param[in] level DiagsLevel for routing and terminal handling.
+ * @param[in] loc Source location, or nullptr.
+ * @param[in] fmt Non-null printf-format string.
+ * @param[in] ap Initialized va_list. Consumed; caller MUST NOT reuse
+ * without va_end + va_start.
+ * @pre fmt is non-null; ap is initialized.
+ * @post Same as error(). For terminal levels, invokes cleanup_func (if
+ * set) then exits the process; does not return.
+ * @par Errors
+ * None signaled; I/O errors absorbed.
+ * @par Thread safety
+ * Safe to call concurrently.
+ */
virtual void error_va(DiagsLevel level, const SourceLocation *loc, const
char *fmt, va_list ap) const;
+ /**
+ * @brief Print the current Diags configuration to fp.
+ *
+ * @param[in] fp Destination FILE *; defaults to stdout.
+ * @pre fp is a valid open stream.
+ * @post Configuration summary written to fp.
+ * @par Errors
+ * I/O errors on fp are not signaled.
+ * @par Thread safety
+ * Not thread-safe. Reads config fields (enable state,
+ * outputs, base_debug_tags, base_action_tags) without holding
+ * tag_table_lock. Concurrent reconfiguration may produce
+ * interleaved or inconsistent output.
+ */
void dump(FILE *fp = stdout) const;
+ /**
+ * @brief Enable tags matching the given PCRE2 pattern for the given mode.
+ *
+ * @param[in] taglist PCRE2 regex string, or nullptr. If nullptr, this call
+ * is a no-op and the previous pattern (if any) is unchanged.
Review Comment:
The activate_taglist() parameter docs say passing nullptr is a "no-op", but
the implementation still triggers a DbgCtl::update() when mode is Debug and
this == diags(). The docs should avoid calling this a no-op (the regex is
unchanged, but there is still a side effect / work).
##########
include/tscore/DiagsTypes.h:
##########
@@ -220,26 +559,255 @@ class Diags : public DebugInterface
va_end(ap);
}
+ /**
+ * @brief va_list form of error().
+ *
+ * @param[in] level DiagsLevel for routing and terminal handling.
+ * @param[in] loc Source location, or nullptr.
+ * @param[in] fmt Non-null printf-format string.
+ * @param[in] ap Initialized va_list. Consumed; caller MUST NOT reuse
+ * without va_end + va_start.
+ * @pre fmt is non-null; ap is initialized.
+ * @post Same as error(). For terminal levels, invokes cleanup_func (if
+ * set) then exits the process; does not return.
+ * @par Errors
+ * None signaled; I/O errors absorbed.
+ * @par Thread safety
+ * Safe to call concurrently.
+ */
virtual void error_va(DiagsLevel level, const SourceLocation *loc, const
char *fmt, va_list ap) const;
+ /**
+ * @brief Print the current Diags configuration to fp.
+ *
+ * @param[in] fp Destination FILE *; defaults to stdout.
+ * @pre fp is a valid open stream.
+ * @post Configuration summary written to fp.
+ * @par Errors
+ * I/O errors on fp are not signaled.
+ * @par Thread safety
+ * Not thread-safe. Reads config fields (enable state,
+ * outputs, base_debug_tags, base_action_tags) without holding
+ * tag_table_lock. Concurrent reconfiguration may produce
+ * interleaved or inconsistent output.
+ */
void dump(FILE *fp = stdout) const;
+ /**
+ * @brief Enable tags matching the given PCRE2 pattern for the given mode.
+ *
+ * @param[in] taglist PCRE2 regex string, or nullptr. If nullptr, this call
+ * is a no-op and the previous pattern (if any) is unchanged.
+ * @param[in] mode DiagsTagType_Debug or DiagsTagType_Action.
+ * @pre taglist is null or a valid PCRE2 pattern string. The regex engine is
+ * PCRE2, not POSIX ERE; PCRE2-specific syntax (lookaheads, named groups,
+ * etc.) is accepted.
+ * @post If taglist is non-null: the new pattern unconditionally replaces the
+ * previous one. If the pattern fails to compile, the previous pattern is
+ * cleared and no tags will match until a valid pattern is installed.
+ * For DiagsTagType_Debug, if this is the process-global Diags instance,
+ * all registered debug controls are updated immediately to reflect the
+ * new pattern.
+ * @par Errors
+ * Invalid regex is silently accepted; compile failure is not
+ * signaled. The previous pattern is NOT retained on compile failure.
+ * @par Thread safety
+ * Acquires tag_table_lock. Safe to call concurrently with
+ * emission, but serialized with other reconfiguration methods.
+ */
void activate_taglist(const char *taglist, DiagsTagType mode =
DiagsTagType_Debug);
+ /**
+ * @brief Disable all tags for the given mode.
+ *
+ * @param[in] mode DiagsTagType_Debug or DiagsTagType_Action.
+ * @pre None.
+ * @post No tag matches for mode; activated_tags[mode] is null.
+ * @par Errors
+ * None.
+ * @par Thread safety
+ * Acquires tag_table_lock. Safe to call concurrently with
+ * emission, but serialized with other reconfiguration methods.
+ */
void deactivate_all(DiagsTagType mode = DiagsTagType_Debug);
+ /**
+ * @brief Open the given BaseLogFile for use as a diagnostic log destination.
+ *
+ * Does NOT assign diags_log; the caller is responsible for that assignment
+ * on success. On failure, blf is deleted before returning.
+ *
+ * @param[in] blf Pointer to a constructed but not-yet-opened BaseLogFile,
+ * or nullptr (null is a no-op that returns true). When non-null, ownership
+ * transfers unconditionally: on success the caller must assign blf to
+ * diags_log; on failure blf has been deleted.
+ * @return True if blf was opened successfully (or blf is nullptr); false if
+ * the open failed (blf is deleted before returning false).
+ * @pre blf is null or points to a BaseLogFile that has not yet been opened.
+ * @post On true return: blf (if non-null) is open; caller must assign it to
+ * diags_log. On false return: blf has been deleted; diags_log is
unchanged.
+ * @par Errors
+ * Open failures cause a false return. A log_log_error diagnostic at
+ * LL_Error is emitted only when BASELOGFILE_DEBUG_MODE is enabled
+ * (off by default).
+ * @par Thread safety
+ * Caller MUST serialize with all other reconfiguration
+ * methods. reseat_diagslog() acquires tag_table_lock only for the
+ * pointer swap that follows this call; setup_diagslog() itself is not
+ * called under the lock. Direct callers must provide equivalent
+ * serialization for the pointer swap.
+ */
bool setup_diagslog(BaseLogFile *blf);
+
+ /**
+ * @brief Configure the rolling policy for diags.log.
+ *
+ * @param[in] re Rolling policy (see RollingEnabledValues).
+ * @param[in] ri Rolling interval in seconds (used by time-based policies).
+ * @param[in] rs Rolling size threshold in bytes (used by size-based
+ * policies).
+ * @pre None.
+ * @post Rolling policy fields are updated in the calling thread.
+ * @par Errors
+ * None.
+ * @par Thread safety
+ * No lock is acquired. The caller must ensure no concurrent
+ * calls to should_roll_diagslog() occur during reconfiguration.
+ */
void config_roll_diagslog(RollingEnabledValues re, int ri, int rs);
+
+ /**
+ * @brief Configure the rolling policy for the output log (traffic.out).
+ *
+ * @param[in] re Rolling policy.
+ * @param[in] ri Rolling interval in seconds.
+ * @param[in] rs Rolling size threshold in bytes.
+ * @pre None.
+ * @post Rolling policy fields are updated in the calling thread.
+ * @par Errors
+ * None.
+ * @par Thread safety
+ * No lock is acquired. The caller must ensure no concurrent
+ * calls to should_roll_outputlog() occur during reconfiguration.
+ */
void config_roll_outputlog(RollingEnabledValues re, int ri, int rs);
+
+ /**
+ * @brief Close the current diags.log and reopen it at the configured path.
+ *
+ * Intended for use after an external log rotation tool has renamed or
+ * removed the active diags.log. The implementation:
+ * 1. Flushes the current file's buffered output.
+ * 2. Captures the configured filename from the active BaseLogFile.
+ * 3. Constructs a new BaseLogFile at that filename. The filename is
+ * passed to the OS verbatim — symlinks are re-resolved at each call.
+ * 4. On success: atomically swaps the new file into place under
+ * tag_table_lock and destroys the previous BaseLogFile (closing its
+ * FILE *).
+ * 5. On failure: leaves the previous file in place.
+ *
+ * @return False if diags_log is null or not yet initialized (safe no-op).
+ * True in all other cases, including when the internal reopen fails —
+ * reopen failures are not reflected in the return value and are
+ * observable only via log_log_trace, which is compiled out unless
+ * BASELOGFILE_DEBUG_MODE is enabled (off by default).
Review Comment:
reseat_diagslog()’s `@return` docs say reopen failures are observable only
via log_log_trace, but the failure path also calls setup_diagslog(), which
reports via log_log_error (when BASELOGFILE_DEBUG_MODE is enabled). The docs
should mention both to avoid misleading readers.
##########
include/tscore/DiagsTypes.h:
##########
@@ -220,26 +559,255 @@ class Diags : public DebugInterface
va_end(ap);
}
+ /**
+ * @brief va_list form of error().
+ *
+ * @param[in] level DiagsLevel for routing and terminal handling.
+ * @param[in] loc Source location, or nullptr.
+ * @param[in] fmt Non-null printf-format string.
+ * @param[in] ap Initialized va_list. Consumed; caller MUST NOT reuse
+ * without va_end + va_start.
+ * @pre fmt is non-null; ap is initialized.
+ * @post Same as error(). For terminal levels, invokes cleanup_func (if
+ * set) then exits the process; does not return.
+ * @par Errors
+ * None signaled; I/O errors absorbed.
+ * @par Thread safety
+ * Safe to call concurrently.
+ */
virtual void error_va(DiagsLevel level, const SourceLocation *loc, const
char *fmt, va_list ap) const;
+ /**
+ * @brief Print the current Diags configuration to fp.
+ *
+ * @param[in] fp Destination FILE *; defaults to stdout.
+ * @pre fp is a valid open stream.
+ * @post Configuration summary written to fp.
+ * @par Errors
+ * I/O errors on fp are not signaled.
+ * @par Thread safety
+ * Not thread-safe. Reads config fields (enable state,
+ * outputs, base_debug_tags, base_action_tags) without holding
+ * tag_table_lock. Concurrent reconfiguration may produce
+ * interleaved or inconsistent output.
+ */
void dump(FILE *fp = stdout) const;
+ /**
+ * @brief Enable tags matching the given PCRE2 pattern for the given mode.
+ *
+ * @param[in] taglist PCRE2 regex string, or nullptr. If nullptr, this call
+ * is a no-op and the previous pattern (if any) is unchanged.
+ * @param[in] mode DiagsTagType_Debug or DiagsTagType_Action.
+ * @pre taglist is null or a valid PCRE2 pattern string. The regex engine is
+ * PCRE2, not POSIX ERE; PCRE2-specific syntax (lookaheads, named groups,
+ * etc.) is accepted.
+ * @post If taglist is non-null: the new pattern unconditionally replaces the
+ * previous one. If the pattern fails to compile, the previous pattern is
+ * cleared and no tags will match until a valid pattern is installed.
+ * For DiagsTagType_Debug, if this is the process-global Diags instance,
+ * all registered debug controls are updated immediately to reflect the
+ * new pattern.
+ * @par Errors
+ * Invalid regex is silently accepted; compile failure is not
+ * signaled. The previous pattern is NOT retained on compile failure.
+ * @par Thread safety
+ * Acquires tag_table_lock. Safe to call concurrently with
+ * emission, but serialized with other reconfiguration methods.
+ */
void activate_taglist(const char *taglist, DiagsTagType mode =
DiagsTagType_Debug);
+ /**
+ * @brief Disable all tags for the given mode.
+ *
+ * @param[in] mode DiagsTagType_Debug or DiagsTagType_Action.
+ * @pre None.
+ * @post No tag matches for mode; activated_tags[mode] is null.
+ * @par Errors
+ * None.
+ * @par Thread safety
+ * Acquires tag_table_lock. Safe to call concurrently with
+ * emission, but serialized with other reconfiguration methods.
+ */
void deactivate_all(DiagsTagType mode = DiagsTagType_Debug);
+ /**
+ * @brief Open the given BaseLogFile for use as a diagnostic log destination.
+ *
+ * Does NOT assign diags_log; the caller is responsible for that assignment
+ * on success. On failure, blf is deleted before returning.
+ *
+ * @param[in] blf Pointer to a constructed but not-yet-opened BaseLogFile,
+ * or nullptr (null is a no-op that returns true). When non-null, ownership
+ * transfers unconditionally: on success the caller must assign blf to
+ * diags_log; on failure blf has been deleted.
+ * @return True if blf was opened successfully (or blf is nullptr); false if
+ * the open failed (blf is deleted before returning false).
+ * @pre blf is null or points to a BaseLogFile that has not yet been opened.
+ * @post On true return: blf (if non-null) is open; caller must assign it to
+ * diags_log. On false return: blf has been deleted; diags_log is
unchanged.
+ * @par Errors
+ * Open failures cause a false return. A log_log_error diagnostic at
+ * LL_Error is emitted only when BASELOGFILE_DEBUG_MODE is enabled
+ * (off by default).
+ * @par Thread safety
+ * Caller MUST serialize with all other reconfiguration
+ * methods. reseat_diagslog() acquires tag_table_lock only for the
+ * pointer swap that follows this call; setup_diagslog() itself is not
+ * called under the lock. Direct callers must provide equivalent
+ * serialization for the pointer swap.
+ */
bool setup_diagslog(BaseLogFile *blf);
+
+ /**
+ * @brief Configure the rolling policy for diags.log.
+ *
+ * @param[in] re Rolling policy (see RollingEnabledValues).
+ * @param[in] ri Rolling interval in seconds (used by time-based policies).
+ * @param[in] rs Rolling size threshold in bytes (used by size-based
+ * policies).
+ * @pre None.
+ * @post Rolling policy fields are updated in the calling thread.
+ * @par Errors
+ * None.
+ * @par Thread safety
+ * No lock is acquired. The caller must ensure no concurrent
+ * calls to should_roll_diagslog() occur during reconfiguration.
+ */
void config_roll_diagslog(RollingEnabledValues re, int ri, int rs);
+
+ /**
+ * @brief Configure the rolling policy for the output log (traffic.out).
+ *
+ * @param[in] re Rolling policy.
+ * @param[in] ri Rolling interval in seconds.
+ * @param[in] rs Rolling size threshold in bytes.
+ * @pre None.
+ * @post Rolling policy fields are updated in the calling thread.
+ * @par Errors
+ * None.
+ * @par Thread safety
+ * No lock is acquired. The caller must ensure no concurrent
+ * calls to should_roll_outputlog() occur during reconfiguration.
+ */
void config_roll_outputlog(RollingEnabledValues re, int ri, int rs);
+
+ /**
+ * @brief Close the current diags.log and reopen it at the configured path.
+ *
+ * Intended for use after an external log rotation tool has renamed or
+ * removed the active diags.log. The implementation:
+ * 1. Flushes the current file's buffered output.
+ * 2. Captures the configured filename from the active BaseLogFile.
+ * 3. Constructs a new BaseLogFile at that filename. The filename is
+ * passed to the OS verbatim — symlinks are re-resolved at each call.
+ * 4. On success: atomically swaps the new file into place under
+ * tag_table_lock and destroys the previous BaseLogFile (closing its
+ * FILE *).
+ * 5. On failure: leaves the previous file in place.
+ *
+ * @return False if diags_log is null or not yet initialized (safe no-op).
+ * True in all other cases, including when the internal reopen fails —
+ * reopen failures are not reflected in the return value and are
+ * observable only via log_log_trace, which is compiled out unless
+ * BASELOGFILE_DEBUG_MODE is enabled (off by default).
+ * @pre A Diags instance is active and diags_log is initialized
+ * (is_init() == true). If this precondition is not met, returns false
+ * without performing a reopen — this is the safe no-op path for calls
+ * that arrive before the diagnostics subsystem is initialized.
+ * @post On success: diags_log is a fresh BaseLogFile at the configured
+ * path; the previous BaseLogFile (and its FILE *) is destroyed; all
+ * subsequent emission goes to the new file.
+ * On failure: diags_log is unchanged; the newly allocated BaseLogFile
+ * is deleted before it returns.
+ * @par Errors
+ * Open failures are not signaled via the return value. They are reported
+ * via log_log_trace only when BASELOGFILE_DEBUG_MODE is enabled (off
+ * by default); in normal builds the failure is completely silent.
+ * @par Thread safety
+ * The swap in step 4 is performed under tag_table_lock.
+ * Concurrent emission either observes the pre-swap or post-swap log;
+ * no message is lost or written to a destroyed FILE *.
+ * @note When diagnostic output is disabled or redirected to a non-file
+ * sink (e.g., syslog), diags_log is null or uninitialized and the
+ * initialization guard causes an early false return.
+ */
bool reseat_diagslog();
+
+ /**
+ * @brief Roll diags.log if the current rolling policy condition is met.
+ *
+ * @return True if the underlying file was renamed (rolled); false if no
+ * roll condition was triggered, or if fstat failed. Note: true is
+ * returned even when the subsequent reopen of the new log file fails.
+ * @pre None.
+ * @post If the rolling condition is met: the current diags.log is flushed,
+ * rolled (renamed), and replaced by a new BaseLogFile at the same path.
+ * If not: no state change. fstat failure causes an early false return
+ * without rolling.
Review Comment:
should_roll_diagslog()’s `@post` currently guarantees the log is "replaced
by a new BaseLogFile", but the implementation only attempts to reopen/swap. If
setup_diagslog() fails after the rename, the old BaseLogFile remains in place
and continues to refer to the rolled (renamed) file. The `@post` should be
softened to match actual behavior.
##########
include/tscore/DiagsTypes.h:
##########
@@ -220,26 +559,255 @@ class Diags : public DebugInterface
va_end(ap);
}
+ /**
+ * @brief va_list form of error().
+ *
+ * @param[in] level DiagsLevel for routing and terminal handling.
+ * @param[in] loc Source location, or nullptr.
+ * @param[in] fmt Non-null printf-format string.
+ * @param[in] ap Initialized va_list. Consumed; caller MUST NOT reuse
+ * without va_end + va_start.
+ * @pre fmt is non-null; ap is initialized.
+ * @post Same as error(). For terminal levels, invokes cleanup_func (if
+ * set) then exits the process; does not return.
+ * @par Errors
+ * None signaled; I/O errors absorbed.
+ * @par Thread safety
+ * Safe to call concurrently.
+ */
virtual void error_va(DiagsLevel level, const SourceLocation *loc, const
char *fmt, va_list ap) const;
+ /**
+ * @brief Print the current Diags configuration to fp.
+ *
+ * @param[in] fp Destination FILE *; defaults to stdout.
+ * @pre fp is a valid open stream.
+ * @post Configuration summary written to fp.
+ * @par Errors
+ * I/O errors on fp are not signaled.
+ * @par Thread safety
+ * Not thread-safe. Reads config fields (enable state,
+ * outputs, base_debug_tags, base_action_tags) without holding
+ * tag_table_lock. Concurrent reconfiguration may produce
+ * interleaved or inconsistent output.
+ */
void dump(FILE *fp = stdout) const;
+ /**
+ * @brief Enable tags matching the given PCRE2 pattern for the given mode.
+ *
+ * @param[in] taglist PCRE2 regex string, or nullptr. If nullptr, this call
+ * is a no-op and the previous pattern (if any) is unchanged.
+ * @param[in] mode DiagsTagType_Debug or DiagsTagType_Action.
+ * @pre taglist is null or a valid PCRE2 pattern string. The regex engine is
+ * PCRE2, not POSIX ERE; PCRE2-specific syntax (lookaheads, named groups,
+ * etc.) is accepted.
+ * @post If taglist is non-null: the new pattern unconditionally replaces the
+ * previous one. If the pattern fails to compile, the previous pattern is
+ * cleared and no tags will match until a valid pattern is installed.
+ * For DiagsTagType_Debug, if this is the process-global Diags instance,
+ * all registered debug controls are updated immediately to reflect the
+ * new pattern.
+ * @par Errors
+ * Invalid regex is silently accepted; compile failure is not
+ * signaled. The previous pattern is NOT retained on compile failure.
+ * @par Thread safety
+ * Acquires tag_table_lock. Safe to call concurrently with
+ * emission, but serialized with other reconfiguration methods.
+ */
void activate_taglist(const char *taglist, DiagsTagType mode =
DiagsTagType_Debug);
+ /**
+ * @brief Disable all tags for the given mode.
+ *
+ * @param[in] mode DiagsTagType_Debug or DiagsTagType_Action.
+ * @pre None.
+ * @post No tag matches for mode; activated_tags[mode] is null.
+ * @par Errors
+ * None.
+ * @par Thread safety
+ * Acquires tag_table_lock. Safe to call concurrently with
+ * emission, but serialized with other reconfiguration methods.
+ */
void deactivate_all(DiagsTagType mode = DiagsTagType_Debug);
+ /**
+ * @brief Open the given BaseLogFile for use as a diagnostic log destination.
+ *
+ * Does NOT assign diags_log; the caller is responsible for that assignment
+ * on success. On failure, blf is deleted before returning.
+ *
+ * @param[in] blf Pointer to a constructed but not-yet-opened BaseLogFile,
+ * or nullptr (null is a no-op that returns true). When non-null, ownership
+ * transfers unconditionally: on success the caller must assign blf to
+ * diags_log; on failure blf has been deleted.
+ * @return True if blf was opened successfully (or blf is nullptr); false if
+ * the open failed (blf is deleted before returning false).
+ * @pre blf is null or points to a BaseLogFile that has not yet been opened.
+ * @post On true return: blf (if non-null) is open; caller must assign it to
+ * diags_log. On false return: blf has been deleted; diags_log is
unchanged.
+ * @par Errors
+ * Open failures cause a false return. A log_log_error diagnostic at
+ * LL_Error is emitted only when BASELOGFILE_DEBUG_MODE is enabled
+ * (off by default).
+ * @par Thread safety
+ * Caller MUST serialize with all other reconfiguration
+ * methods. reseat_diagslog() acquires tag_table_lock only for the
+ * pointer swap that follows this call; setup_diagslog() itself is not
+ * called under the lock. Direct callers must provide equivalent
+ * serialization for the pointer swap.
+ */
bool setup_diagslog(BaseLogFile *blf);
+
+ /**
+ * @brief Configure the rolling policy for diags.log.
+ *
+ * @param[in] re Rolling policy (see RollingEnabledValues).
+ * @param[in] ri Rolling interval in seconds (used by time-based policies).
+ * @param[in] rs Rolling size threshold in bytes (used by size-based
+ * policies).
+ * @pre None.
+ * @post Rolling policy fields are updated in the calling thread.
+ * @par Errors
+ * None.
+ * @par Thread safety
+ * No lock is acquired. The caller must ensure no concurrent
+ * calls to should_roll_diagslog() occur during reconfiguration.
+ */
void config_roll_diagslog(RollingEnabledValues re, int ri, int rs);
+
+ /**
+ * @brief Configure the rolling policy for the output log (traffic.out).
+ *
+ * @param[in] re Rolling policy.
+ * @param[in] ri Rolling interval in seconds.
+ * @param[in] rs Rolling size threshold in bytes.
+ * @pre None.
+ * @post Rolling policy fields are updated in the calling thread.
+ * @par Errors
+ * None.
+ * @par Thread safety
+ * No lock is acquired. The caller must ensure no concurrent
+ * calls to should_roll_outputlog() occur during reconfiguration.
+ */
void config_roll_outputlog(RollingEnabledValues re, int ri, int rs);
+
+ /**
+ * @brief Close the current diags.log and reopen it at the configured path.
+ *
+ * Intended for use after an external log rotation tool has renamed or
+ * removed the active diags.log. The implementation:
+ * 1. Flushes the current file's buffered output.
+ * 2. Captures the configured filename from the active BaseLogFile.
+ * 3. Constructs a new BaseLogFile at that filename. The filename is
+ * passed to the OS verbatim — symlinks are re-resolved at each call.
+ * 4. On success: atomically swaps the new file into place under
+ * tag_table_lock and destroys the previous BaseLogFile (closing its
+ * FILE *).
+ * 5. On failure: leaves the previous file in place.
+ *
+ * @return False if diags_log is null or not yet initialized (safe no-op).
+ * True in all other cases, including when the internal reopen fails —
+ * reopen failures are not reflected in the return value and are
+ * observable only via log_log_trace, which is compiled out unless
+ * BASELOGFILE_DEBUG_MODE is enabled (off by default).
+ * @pre A Diags instance is active and diags_log is initialized
+ * (is_init() == true). If this precondition is not met, returns false
+ * without performing a reopen — this is the safe no-op path for calls
+ * that arrive before the diagnostics subsystem is initialized.
+ * @post On success: diags_log is a fresh BaseLogFile at the configured
+ * path; the previous BaseLogFile (and its FILE *) is destroyed; all
+ * subsequent emission goes to the new file.
+ * On failure: diags_log is unchanged; the newly allocated BaseLogFile
+ * is deleted before it returns.
+ * @par Errors
+ * Open failures are not signaled via the return value. They are reported
+ * via log_log_trace only when BASELOGFILE_DEBUG_MODE is enabled (off
+ * by default); in normal builds the failure is completely silent.
+ * @par Thread safety
+ * The swap in step 4 is performed under tag_table_lock.
+ * Concurrent emission either observes the pre-swap or post-swap log;
+ * no message is lost or written to a destroyed FILE *.
+ * @note When diagnostic output is disabled or redirected to a non-file
+ * sink (e.g., syslog), diags_log is null or uninitialized and the
+ * initialization guard causes an early false return.
+ */
bool reseat_diagslog();
+
+ /**
+ * @brief Roll diags.log if the current rolling policy condition is met.
+ *
+ * @return True if the underlying file was renamed (rolled); false if no
+ * roll condition was triggered, or if fstat failed. Note: true is
+ * returned even when the subsequent reopen of the new log file fails.
+ * @pre None.
+ * @post If the rolling condition is met: the current diags.log is flushed,
+ * rolled (renamed), and replaced by a new BaseLogFile at the same path.
+ * If not: no state change. fstat failure causes an early false return
+ * without rolling.
+ * @par Errors
+ * None signaled. fstat and reopen failures silently suppress the
+ * replacement; the rolled state of the original file is not reversed.
+ * @par Thread safety
+ * tag_table_lock is acquired only during the BaseLogFile
+ * pointer swap. The rolling-condition checks and file operations execute
+ * without a lock; the caller must ensure no concurrent reconfiguration
+ * (see config_roll_diagslog()).
+ */
bool should_roll_diagslog();
+
+ /**
+ * @brief Roll stdout_log and stderr_log if the current rolling policy
+ * condition is met.
+ *
+ * @return True if any output log was rolled; false otherwise.
+ * @pre stdout_log and stderr_log are non-null.
+ * @post If the rolling condition is met: affected logs are flushed, rolled,
+ * and replaced by new BaseLogFile instances at the same paths.
+ * If not: no state change. fstat failure causes an early false return.
Review Comment:
should_roll_outputlog()’s `@post` currently guarantees logs are "replaced by
new BaseLogFile instances", but the implementation only attempts to reopen via
set_std_output(); failures are possible and are not propagated. Update the
`@post` text to avoid promising replacement unconditionally.
##########
include/tscore/DiagsTypes.h:
##########
@@ -220,26 +559,255 @@ class Diags : public DebugInterface
va_end(ap);
}
+ /**
+ * @brief va_list form of error().
+ *
+ * @param[in] level DiagsLevel for routing and terminal handling.
+ * @param[in] loc Source location, or nullptr.
+ * @param[in] fmt Non-null printf-format string.
+ * @param[in] ap Initialized va_list. Consumed; caller MUST NOT reuse
+ * without va_end + va_start.
+ * @pre fmt is non-null; ap is initialized.
+ * @post Same as error(). For terminal levels, invokes cleanup_func (if
+ * set) then exits the process; does not return.
+ * @par Errors
+ * None signaled; I/O errors absorbed.
+ * @par Thread safety
+ * Safe to call concurrently.
+ */
virtual void error_va(DiagsLevel level, const SourceLocation *loc, const
char *fmt, va_list ap) const;
+ /**
+ * @brief Print the current Diags configuration to fp.
+ *
+ * @param[in] fp Destination FILE *; defaults to stdout.
+ * @pre fp is a valid open stream.
+ * @post Configuration summary written to fp.
+ * @par Errors
+ * I/O errors on fp are not signaled.
+ * @par Thread safety
+ * Not thread-safe. Reads config fields (enable state,
+ * outputs, base_debug_tags, base_action_tags) without holding
+ * tag_table_lock. Concurrent reconfiguration may produce
+ * interleaved or inconsistent output.
+ */
void dump(FILE *fp = stdout) const;
+ /**
+ * @brief Enable tags matching the given PCRE2 pattern for the given mode.
+ *
+ * @param[in] taglist PCRE2 regex string, or nullptr. If nullptr, this call
+ * is a no-op and the previous pattern (if any) is unchanged.
+ * @param[in] mode DiagsTagType_Debug or DiagsTagType_Action.
+ * @pre taglist is null or a valid PCRE2 pattern string. The regex engine is
+ * PCRE2, not POSIX ERE; PCRE2-specific syntax (lookaheads, named groups,
+ * etc.) is accepted.
+ * @post If taglist is non-null: the new pattern unconditionally replaces the
+ * previous one. If the pattern fails to compile, the previous pattern is
+ * cleared and no tags will match until a valid pattern is installed.
+ * For DiagsTagType_Debug, if this is the process-global Diags instance,
+ * all registered debug controls are updated immediately to reflect the
+ * new pattern.
+ * @par Errors
+ * Invalid regex is silently accepted; compile failure is not
+ * signaled. The previous pattern is NOT retained on compile failure.
+ * @par Thread safety
+ * Acquires tag_table_lock. Safe to call concurrently with
+ * emission, but serialized with other reconfiguration methods.
+ */
void activate_taglist(const char *taglist, DiagsTagType mode =
DiagsTagType_Debug);
+ /**
+ * @brief Disable all tags for the given mode.
+ *
+ * @param[in] mode DiagsTagType_Debug or DiagsTagType_Action.
+ * @pre None.
+ * @post No tag matches for mode; activated_tags[mode] is null.
+ * @par Errors
+ * None.
+ * @par Thread safety
+ * Acquires tag_table_lock. Safe to call concurrently with
+ * emission, but serialized with other reconfiguration methods.
+ */
void deactivate_all(DiagsTagType mode = DiagsTagType_Debug);
+ /**
+ * @brief Open the given BaseLogFile for use as a diagnostic log destination.
+ *
+ * Does NOT assign diags_log; the caller is responsible for that assignment
+ * on success. On failure, blf is deleted before returning.
+ *
+ * @param[in] blf Pointer to a constructed but not-yet-opened BaseLogFile,
+ * or nullptr (null is a no-op that returns true). When non-null, ownership
+ * transfers unconditionally: on success the caller must assign blf to
+ * diags_log; on failure blf has been deleted.
+ * @return True if blf was opened successfully (or blf is nullptr); false if
+ * the open failed (blf is deleted before returning false).
+ * @pre blf is null or points to a BaseLogFile that has not yet been opened.
+ * @post On true return: blf (if non-null) is open; caller must assign it to
+ * diags_log. On false return: blf has been deleted; diags_log is
unchanged.
+ * @par Errors
+ * Open failures cause a false return. A log_log_error diagnostic at
+ * LL_Error is emitted only when BASELOGFILE_DEBUG_MODE is enabled
+ * (off by default).
+ * @par Thread safety
+ * Caller MUST serialize with all other reconfiguration
+ * methods. reseat_diagslog() acquires tag_table_lock only for the
+ * pointer swap that follows this call; setup_diagslog() itself is not
+ * called under the lock. Direct callers must provide equivalent
+ * serialization for the pointer swap.
+ */
bool setup_diagslog(BaseLogFile *blf);
+
+ /**
+ * @brief Configure the rolling policy for diags.log.
+ *
+ * @param[in] re Rolling policy (see RollingEnabledValues).
+ * @param[in] ri Rolling interval in seconds (used by time-based policies).
+ * @param[in] rs Rolling size threshold in bytes (used by size-based
+ * policies).
+ * @pre None.
+ * @post Rolling policy fields are updated in the calling thread.
+ * @par Errors
+ * None.
+ * @par Thread safety
+ * No lock is acquired. The caller must ensure no concurrent
+ * calls to should_roll_diagslog() occur during reconfiguration.
+ */
void config_roll_diagslog(RollingEnabledValues re, int ri, int rs);
+
+ /**
+ * @brief Configure the rolling policy for the output log (traffic.out).
+ *
+ * @param[in] re Rolling policy.
+ * @param[in] ri Rolling interval in seconds.
+ * @param[in] rs Rolling size threshold in bytes.
+ * @pre None.
+ * @post Rolling policy fields are updated in the calling thread.
+ * @par Errors
+ * None.
+ * @par Thread safety
+ * No lock is acquired. The caller must ensure no concurrent
+ * calls to should_roll_outputlog() occur during reconfiguration.
+ */
void config_roll_outputlog(RollingEnabledValues re, int ri, int rs);
+
+ /**
+ * @brief Close the current diags.log and reopen it at the configured path.
+ *
+ * Intended for use after an external log rotation tool has renamed or
+ * removed the active diags.log. The implementation:
+ * 1. Flushes the current file's buffered output.
+ * 2. Captures the configured filename from the active BaseLogFile.
+ * 3. Constructs a new BaseLogFile at that filename. The filename is
+ * passed to the OS verbatim — symlinks are re-resolved at each call.
+ * 4. On success: atomically swaps the new file into place under
+ * tag_table_lock and destroys the previous BaseLogFile (closing its
+ * FILE *).
+ * 5. On failure: leaves the previous file in place.
+ *
+ * @return False if diags_log is null or not yet initialized (safe no-op).
+ * True in all other cases, including when the internal reopen fails —
+ * reopen failures are not reflected in the return value and are
+ * observable only via log_log_trace, which is compiled out unless
+ * BASELOGFILE_DEBUG_MODE is enabled (off by default).
+ * @pre A Diags instance is active and diags_log is initialized
+ * (is_init() == true). If this precondition is not met, returns false
+ * without performing a reopen — this is the safe no-op path for calls
+ * that arrive before the diagnostics subsystem is initialized.
+ * @post On success: diags_log is a fresh BaseLogFile at the configured
+ * path; the previous BaseLogFile (and its FILE *) is destroyed; all
+ * subsequent emission goes to the new file.
+ * On failure: diags_log is unchanged; the newly allocated BaseLogFile
+ * is deleted before it returns.
+ * @par Errors
+ * Open failures are not signaled via the return value. They are reported
+ * via log_log_trace only when BASELOGFILE_DEBUG_MODE is enabled (off
+ * by default); in normal builds the failure is completely silent.
Review Comment:
The `@par` Errors section for reseat_diagslog() similarly says failures are
reported only via log_log_trace, but setup_diagslog() uses log_log_error as
well (both gated by BASELOGFILE_DEBUG_MODE).
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]