Skip to content

Execution Log Related Changes#4346

Merged
prashelke merged 8 commits into
Releases/Official-Releasefrom
BugFix/MobileAIFineTuneFix
Oct 18, 2025
Merged

Execution Log Related Changes#4346
prashelke merged 8 commits into
Releases/Official-Releasefrom
BugFix/MobileAIFineTuneFix

Conversation

@prashelke

@prashelke prashelke commented Oct 17, 2025

Copy link
Copy Markdown
Contributor

Thank you for your contribution.
Before submitting this PR, please make sure:

  • PR description and commit message should describe the changes done in this PR
  • Verify the PR is pointing to correct branch i.e. Release or Beta branch if the code fix is for specific release , else point it to master
  • Latest Code from master or specific release branch is merged to your branch
  • No unwanted\commented\junk code is included
  • No new warning upon build solution
  • Code Summary\Comments are added to my code which explains what my code is doing
  • Existing unit test cases are passed
  • New Unit tests are added for your development
  • Sanity Tests are successfully executed for New and Existing Functionality
  • Verify that changes are compatible with all relevant browsers and platforms.
  • After creating pull request there should not be any conflicts
  • Resolve all Codacy comments
  • Builds and checks are passed before PR is sent for review
  • Resolve code review comments
  • Update the Help Library document to match any feature changes

Summary by CodeRabbit

  • Bug Fixes

    • HTTP logging appenders are now disposed during CLI shutdown; disposal errors are debug-logged and do not block shutdown.
    • Remaining log queue items are processed during disposal to ensure final reports are sent.
    • Disposal explicitly handles cancellation and individual disposal errors to reduce noisy failures.
  • New Features

    • Run Set context (entity ID, solution ID, name) is included in execution and error reports for richer central reporting.
    • Operation names are extracted into error reports to improve traceability.

@coderabbitai

coderabbitai Bot commented Oct 17, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Disposes HttpLogAppender instances during CLI shutdown and enhances HttpLogAppender with Run Set context tracking, guarded central-DB reporting, synchronous queue draining during disposal, improved error-origin capture, and debug-only logging of disposal/reporting failures.

Changes

Cohort / File(s) Summary
CLI shutdown disposal
Ginger/Ginger/App.xaml.cs
Adds private DisposeHttpLogAppenders() and calls it from RunNewCLI finally block to enumerate log4net appenders, dispose HttpLogAppender instances, and debug-log per-appender disposal errors without throwing.
Http log appender — Run Set, reporting & disposal
Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs
Adds Run Set context fields (EntityId, solutionId, runsetName, isRunSetStarted) with start/end resets; populates identifiers from workspace with guarded try/catch; captures operation name for error origin; updates reporting payload and calls SendRunsetExecutionDataToCentralDBAsync with isUpdate; on Dispose drains remaining queue synchronously, logs TaskCanceledException and other disposal/reporting errors at DEBUG, and avoids throwing on disposal failures.

Sequence Diagram(s)

sequenceDiagram
    participant CLI as CLI
    participant App as App.xaml.cs
    participant Log4Net as log4net repo
    participant Appender as HttpLogAppender
    participant Queue as LocalQueue
    participant API as CentralDB / AccountReportAPI

    CLI->>App: RunNewCLI finally
    App->>Log4Net: GetRepository().GetAppenders()
    Log4Net-->>App: appenders[]
    App->>Appender: DisposeHttpLogAppenders() -> Dispose()

    rect rgb(240,250,240)
      Note over Appender,Queue: Disposal (guarded, sync drain)
      Appender->>Queue: Drain remaining items synchronously
      Queue-->>Appender: pending entries
      Appender->>API: SendRunsetExecutionDataToCentralDBAsync (try/catch)
      API-->>Appender: success / error
      Appender-->>App: disposal complete (errors debug-logged)
    end

    App->>CLI: continue shutdown
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • Maheshkale447

Poem

🐇
I hopped through logs at evening's rim,
Drained every queue till light grew dim.
Run Set names tucked in a careful line,
Errors hushed in debug-sign.
A soft shutdown — carrot time.

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings, 1 inconclusive)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The pull request description is incomplete and consists solely of the template checklist without any actual description of the changes made. The description lacks essential information about what was modified, why the changes were made, and how they address the issue. The first checklist item specifically requires that "PR description and commit message should describe the changes done in this PR," but no such description is provided—only the template checklist items remain unchecked and unfilled. Replace the boilerplate checklist with a meaningful description that explains the changes made in this PR. Include details about the HTTP log appender disposal mechanism added to App.xaml.cs, the Run Set context tracking enhancements to HttpLogAppender.cs, and the rationale behind these modifications. The checklist items can remain as verification steps, but they should not replace the actual PR description.
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title Check ❓ Inconclusive The title "Execution Log Related Changes" is vague and overly generic. While it references a real aspect of the changes (logging and execution), it fails to convey specific information about what was actually modified. The actual changes involve HTTP log appender disposal on CLI shutdown and Run Set context tracking in the HttpLogAppender, which are more specific and distinct changes than what the title suggests. A teammate scanning the pull request history would not gain meaningful understanding of the primary changes from this title alone.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch BugFix/MobileAIFineTuneFix

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs (1)

66-71: AccountReportApiHandler constructed with pre-gateway URL

Setter builds handler before appending gateway, so handler/rest client may target the wrong base. Build final URL first, then construct the handler.

-                if (string.IsNullOrWhiteSpace(_apiUrl) || (!string.IsNullOrWhiteSpace(value) && value != _apiUrl))
-                {
-                    _apiUrl = value;
-                    _accountReportApiHandler = string.IsNullOrWhiteSpace(_apiUrl) ? null : new AccountReportApiHandler(_apiUrl);
-                    _apiUrl = $"{value}{GingerPlayEndPointManager.GetAccountReportServiceGateWay()}"; //Final Url with gateway
-                }
+                if (string.IsNullOrWhiteSpace(_apiUrl) || (!string.IsNullOrWhiteSpace(value) && !string.Equals(value, _apiUrl, StringComparison.Ordinal)))
+                {
+                    var finalUrl = string.IsNullOrWhiteSpace(value)
+                        ? null
+                        : $"{value}{GingerPlayEndPointManager.GetAccountReportServiceGateWay()}";
+                    _apiUrl = finalUrl;
+                    _accountReportApiHandler = string.IsNullOrWhiteSpace(_apiUrl) ? null : new AccountReportApiHandler(_apiUrl);
+                }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 63bfca2 and 0a84f30.

📒 Files selected for processing (2)
  • Ginger/Ginger/App.xaml.cs (1 hunks)
  • Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs (10 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs (4)
Ginger/GingerCoreCommon/ReporterLib/Reporter.cs (1)
  • Reporter (28-357)
Ginger/GingerCoreNET/WorkSpaceLib/WorkSpace.cs (1)
  • WorkSpace (61-1006)
Ginger/GingerCoreNET/Run/RunsetExecutor.cs (1)
  • RunsetExecutor (53-1061)
Ginger/GingerCoreNET/Run/RunListenerLib/CenteralizedExecutionLogger/AccountReportApiHandler.cs (4)
  • AccountReportRunSet (94-119)
  • AccountReportApiHandler (38-809)
  • AccountReportApiHandler (66-89)
  • AccountReportApiHandler (90-93)
Ginger/Ginger/App.xaml.cs (2)
Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs (3)
  • HttpLogAppender (38-605)
  • HttpLogAppender (180-183)
  • Dispose (147-178)
Ginger/GingerCoreCommon/ReporterLib/Reporter.cs (3)
  • Dispose (129-132)
  • Reporter (28-357)
  • ToLog (41-87)
🔇 Additional comments (3)
Ginger/Ginger/App.xaml.cs (1)

516-516: LGTM! Proper placement for cleanup.

The call to DisposeHttpLogAppenders() in the finally block ensures HTTP log appenders are disposed before application shutdown, allowing them to flush remaining logs regardless of whether exceptions occurred during CLI execution.

Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs (2)

295-296: LGTM: drain on queue completion

Including _queue.IsCompleted in the flush condition ensures remaining buffered items are sent during shutdown.


480-481: LGTM: exclude exit-code summary line from ExecutionErrorRequests

The filter avoids duplicating the process-exit error in error aggregation.

Comment thread Ginger/Ginger/App.xaml.cs
Comment thread Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs Outdated
Comment thread Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs Outdated
Comment thread Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs Outdated
Comment thread Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs
Comment thread Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs (1)

405-431: Major: Incomplete run-state flag reset causes state leakage across runs.

isRunSetStarted is set to true on line 408 but never reset to false when the run set ends (line 425-431). Similarly, isPreRunSetOperation and isPostRunSetOperation are not reset. This causes state to leak across multiple run set executions, leading to misclassification of log events.

For example, line 435 checks !isRunSetStarted, which will fail after the first run completes because the flag remains true.

Apply this fix:

 if (evt.RenderedMessage.IndexOf("Run Set Execution Started", StringComparison.OrdinalIgnoreCase) >= 0)
 {
     isExecutionStarted = true;
     isRunSetStarted = true;
+    isPreRunSetOperation = false;
+    isPostRunSetOperation = false;
     EntityId = Guid.Empty;
     solutionId = Guid.Empty;
     runsetName = string.Empty;
 }
 
 ...
 
 if (evt.RenderedMessage.IndexOf("Run Set Execution Ended", StringComparison.OrdinalIgnoreCase) >= 0)
 {
     isExecutionStarted = false;
+    isRunSetStarted = false;
+    isPreRunSetOperation = false;
+    isPostRunSetOperation = false;
     EntityId = Guid.Empty;
     solutionId = Guid.Empty;
     runsetName = string.Empty;
 }
♻️ Duplicate comments (1)
Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs (1)

381-398: Critical: Guid? null-check bug still present; empty catch swallows exceptions.

The issue flagged in previous reviews remains unresolved. When RunSetConfig.Guid or Solution.Guid is nullable (Guid?), comparing Guid? != Guid.Empty returns true when the value is null, then casting (Guid)null throws InvalidOperationException, which is silently swallowed by the empty catch block.

Apply this fix:

-            try
-            {
-                if (EntityId == Guid.Empty && WorkSpace.Instance?.RunsetExecutor?.RunSetConfig?.Guid != Guid.Empty)
-                {
-                    EntityId = (Guid)WorkSpace.Instance?.RunsetExecutor?.RunSetConfig?.Guid;
-                }
-                if (solutionId == Guid.Empty && WorkSpace.Instance?.Solution?.Guid != Guid.Empty)
-                {
-                    solutionId = (Guid)WorkSpace.Instance?.Solution?.Guid;
-                }
-                if (string.IsNullOrEmpty(runsetName) && !string.IsNullOrEmpty(WorkSpace.Instance?.RunsetExecutor?.RunSetConfig?.Name))
-                {
-                    runsetName = WorkSpace.Instance?.RunsetExecutor?.RunSetConfig?.Name;
-                }
-            }
-            catch
-            {
-            }
+            var runsetGuid = WorkSpace.Instance?.RunsetExecutor?.RunSetConfig?.Guid;
+            if (EntityId == Guid.Empty && runsetGuid.HasValue && runsetGuid.Value != Guid.Empty)
+            {
+                EntityId = runsetGuid.Value;
+            }
+            var solGuid = WorkSpace.Instance?.Solution?.Guid;
+            if (solutionId == Guid.Empty && solGuid.HasValue && solGuid.Value != Guid.Empty)
+            {
+                solutionId = solGuid.Value;
+            }
+            var rsName = WorkSpace.Instance?.RunsetExecutor?.RunSetConfig?.Name;
+            if (string.IsNullOrEmpty(runsetName) && !string.IsNullOrWhiteSpace(rsName))
+            {
+                runsetName = rsName;
+            }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0a84f30 and 062efb1.

📒 Files selected for processing (2)
  • Ginger/Ginger/App.xaml.cs (1 hunks)
  • Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs (10 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
Ginger/Ginger/App.xaml.cs (2)
Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs (3)
  • HttpLogAppender (38-610)
  • HttpLogAppender (180-183)
  • Dispose (147-178)
Ginger/GingerCoreCommon/ReporterLib/Reporter.cs (3)
  • Dispose (129-132)
  • Reporter (28-357)
  • ToLog (41-87)
Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs (3)
Ginger/GingerCoreCommon/ReporterLib/Reporter.cs (1)
  • Reporter (28-357)
Ginger/GingerCoreNET/WorkSpaceLib/WorkSpace.cs (1)
  • WorkSpace (61-1006)
Ginger/GingerCoreNET/Run/RunListenerLib/CenteralizedExecutionLogger/AccountReportApiHandler.cs (4)
  • AccountReportApiHandler (38-809)
  • AccountReportApiHandler (66-89)
  • AccountReportApiHandler (90-93)
  • AccountReportRunSet (94-119)
🔇 Additional comments (2)
Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs (1)

171-171: Improved error message for disposal logging.

The updated log message provides clearer context for disposal errors.

Ginger/Ginger/App.xaml.cs (1)

522-557: LGTM! Robust disposal implementation with defensive checks.

The implementation correctly includes all requested defensive measures:

  • Null checks for repository and appenders collection
  • Individual try-catch per appender to ensure all are disposed even if one fails
  • Proper error logging at each level
  • Outer try-catch for unexpected errors

This ensures graceful cleanup during CLI shutdown even in edge cases.

Comment thread Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs Outdated
Comment thread Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs (1)

382-399: CRITICAL: Nullable Guid comparison and cast bug.

When RunSetConfig.Guid or Solution.Guid is Guid? (nullable), comparing Guid? != Guid.Empty returns true when the value is null, then casting (Guid)null throws InvalidOperationException. The empty catch silently swallows this exception, causing context fields to remain unpopulated without any indication of failure.

Apply this fix to properly handle nullable Guids:

 try
 {
-    if (EntityId == Guid.Empty && WorkSpace.Instance?.RunsetExecutor?.RunSetConfig?.Guid != Guid.Empty)
+    var runsetGuid = WorkSpace.Instance?.RunsetExecutor?.RunSetConfig?.Guid;
+    if (EntityId == Guid.Empty && runsetGuid.HasValue && runsetGuid.Value != Guid.Empty)
     {
-        EntityId = (Guid)WorkSpace.Instance?.RunsetExecutor?.RunSetConfig?.Guid;
+        EntityId = runsetGuid.Value;
     }
-    if (solutionId == Guid.Empty && WorkSpace.Instance?.Solution?.Guid != Guid.Empty)
+    var solGuid = WorkSpace.Instance?.Solution?.Guid;
+    if (solutionId == Guid.Empty && solGuid.HasValue && solGuid.Value != Guid.Empty)
     {
-        solutionId = (Guid)WorkSpace.Instance?.Solution?.Guid;
+        solutionId = solGuid.Value;
     }
-    if (string.IsNullOrEmpty(runsetName) && !string.IsNullOrEmpty(WorkSpace.Instance?.RunsetExecutor?.RunSetConfig?.Name))
+    var rsName = WorkSpace.Instance?.RunsetExecutor?.RunSetConfig?.Name;
+    if (string.IsNullOrEmpty(runsetName) && !string.IsNullOrWhiteSpace(rsName))
     {
-        runsetName = WorkSpace.Instance?.RunsetExecutor?.RunSetConfig?.Name;
+        runsetName = rsName;
     }
 }
-catch //Any exceptions that occur in this block should be ignored — they should neither be logged nor cause a return, so that the subsequent code continues to execute
+catch (Exception ex)
 {
+    Reporter.ToLog(eLogLevel.DEBUG, "[HttpLogAppender] Failed to populate context from WorkSpace", ex);
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 062efb1 and 93e7780.

📒 Files selected for processing (1)
  • Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs (11 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs (5)
Ginger/GingerCoreCommon/ReporterLib/Reporter.cs (1)
  • Reporter (28-357)
Ginger/GingerCoreNET/log4netLib/GingerLog.cs (1)
  • ToLog (92-123)
Ginger/GingerCoreNET/WorkSpaceLib/WorkSpace.cs (1)
  • WorkSpace (61-1006)
Ginger/GingerCoreNET/Run/RunsetExecutor.cs (1)
  • RunsetExecutor (53-1061)
Ginger/GingerCoreNET/Run/RunListenerLib/CenteralizedExecutionLogger/AccountReportApiHandler.cs (4)
  • AccountReportApiHandler (38-809)
  • AccountReportApiHandler (66-89)
  • AccountReportApiHandler (90-93)
  • AccountReportRunSet (94-119)
🔇 Additional comments (7)
Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs (7)

368-370: LGTM: Instance-scoped context fields.

The context fields are now properly instance-scoped, preventing state leakage across appender instances and runs as recommended in previous reviews.


409-412: LGTM: Context properly reset on Run Set start.

Resetting EntityId, solutionId, and runsetName at Run Set start correctly prevents state leakage across runs.


429-431: LGTM: Context properly reset on Run Set end.

Resetting context fields at Run Set end completes the lifecycle management, ensuring no stale state persists.


486-489: LGTM: Correctly excludes exit code errors from ExecutionError.

The condition correctly skips adding "Error(s) occurred process exit code" messages to ExecutionError list, as these are handled separately in the block above.


531-536: LGTM: Robust regex pattern for operation name extraction.

The improved regex pattern with word boundary and newline handling correctly extracts operation names even when they contain special characters or appear near line breaks.


545-550: LGTM: Consistent regex pattern for Post RunSet operation.

The same robust regex pattern is correctly applied for Post RunSet operation name extraction, maintaining consistency.


436-463: Incorrect isUpdate flag for early failures.

When sending Run Set execution data for errors that occur before Run Set starts, isUpdate: true is used. However, since the Run Set never started, no initial record was sent to central DB, meaning _isRunSetDataSent would be false. According to SendRunsetExecutionDataToCentralDBAsync logic (from relevant code snippets), when isUpdate=true and _isRunSetDataSent=false, the update is aborted and returns false immediately.

This means early failure data will never be successfully sent.

Change to isUpdate: false for initial send:

-bool response = await AccountReportApiHandler.SendRunsetExecutionDataToCentralDBAsync(accountReportRunSet, isUpdate: true).ConfigureAwait(false);
+bool response = await AccountReportApiHandler.SendRunsetExecutionDataToCentralDBAsync(accountReportRunSet, isUpdate: false).ConfigureAwait(false);
⛔ Skipped due to learnings
Learnt from: Maheshkale447
PR: Ginger-Automation/Ginger#4293
File: Ginger/GingerCoreNET/Run/RunListenerLib/CenteralizedExecutionLogger/AccountReportApiHandler.cs:56-60
Timestamp: 2025-09-05T10:50:57.706Z
Learning: In AccountReportApiHandler.cs, the _isRunSetDataSent flag is correctly initialized to true by default. This flag acts as a circuit breaker where true allows operations to proceed and false blocks downstream operations after a RunSet send failure. The optimistic default (true) is necessary to allow the initial RunSet send attempt.

Comment thread Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs (1)

381-399: Critical: Nullable Guid comparison bug causes silent failures.

The code at lines 383-394 has a critical bug when RunSetConfig.Guid or Solution.Guid is nullable (Guid?):

  1. Faulty comparison: When Guid? is null, the expression Guid? != Guid.Empty returns true (because null != any value).
  2. Cast failure: The subsequent cast (Guid)nullableGuid throws InvalidOperationException when the value is null.
  3. Silent swallow: The empty catch block at lines 396-398 hides the exception, causing EntityId, solutionId, and runsetName to silently fail to populate.

This breaks Run Set context tracking and central-DB reporting. Based on the codebase snippets, RunSetConfig and Solution properties are likely nullable.

Apply this fix to use safe null-checking patterns:

 try
 {
-    if (EntityId == Guid.Empty && WorkSpace.Instance?.RunsetExecutor?.RunSetConfig?.Guid != Guid.Empty)
+    var runsetGuid = WorkSpace.Instance?.RunsetExecutor?.RunSetConfig?.Guid;
+    if (EntityId == Guid.Empty && runsetGuid.HasValue && runsetGuid.Value != Guid.Empty)
     {
-        EntityId = (Guid)WorkSpace.Instance?.RunsetExecutor?.RunSetConfig?.Guid;
+        EntityId = runsetGuid.Value;
     }
-    if (solutionId == Guid.Empty && WorkSpace.Instance?.Solution?.Guid != Guid.Empty)
+    var solGuid = WorkSpace.Instance?.Solution?.Guid;
+    if (solutionId == Guid.Empty && solGuid.HasValue && solGuid.Value != Guid.Empty)
     {
-        solutionId = (Guid)WorkSpace.Instance?.Solution?.Guid;
+        solutionId = solGuid.Value;
     }
-    if (string.IsNullOrEmpty(runsetName) && !string.IsNullOrEmpty(WorkSpace.Instance?.RunsetExecutor?.RunSetConfig?.Name))
+    var rsName = WorkSpace.Instance?.RunsetExecutor?.RunSetConfig?.Name;
+    if (string.IsNullOrEmpty(runsetName) && !string.IsNullOrWhiteSpace(rsName))
     {
-        runsetName = WorkSpace.Instance?.RunsetExecutor?.RunSetConfig?.Name;
+        runsetName = rsName;
     }
 }
-catch //Any exceptions that occur in this block should be ignored — they should neither be logged nor cause a return, so that the subsequent code continues to execute
+catch (Exception ex)
 {
+    Reporter.ToLog(eLogLevel.DEBUG, "[HttpLogAppender] Failed to resolve Run Set context from WorkSpace", ex);
 }

Additionally, log exceptions instead of silently swallowing them so failures are visible during debugging.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 93e7780 and 1f6e2e3.

📒 Files selected for processing (1)
  • Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs (11 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs (4)
Ginger/GingerCoreCommon/ReporterLib/Reporter.cs (1)
  • Reporter (28-357)
Ginger/GingerCoreNET/WorkSpaceLib/WorkSpace.cs (1)
  • WorkSpace (61-1006)
Ginger/GingerCoreNET/Run/RunsetExecutor.cs (1)
  • RunsetExecutor (53-1061)
Ginger/GingerCoreNET/Run/RunListenerLib/CenteralizedExecutionLogger/AccountReportApiHandler.cs (4)
  • AccountReportApiHandler (38-809)
  • AccountReportApiHandler (66-89)
  • AccountReportApiHandler (90-93)
  • AccountReportRunSet (94-119)
🔇 Additional comments (8)
Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs (8)

367-369: LGTM: Instance fields prevent cross-instance state leakage.

The fields EntityId, solutionId, and runsetName are now correctly scoped as instance fields rather than static, which prevents mutable context from bleeding across appender instances and runs. This addresses the concern from the previous review.

Based on learnings


408-411: LGTM: Run Set context is reset on start.

The code correctly resets EntityId, solutionId, and runsetName to empty values when a new Run Set execution starts. This ensures that context from a previous run doesn't leak into the new execution, which is essential for accurate central-DB reporting.


425-431: LGTM: Run Set context is cleared on end.

The code correctly clears isExecutionStarted and resets EntityId, solutionId, and runsetName when the Run Set execution ends. This prevents stale state from persisting after execution completes.


435-462: LGTM: Failure reporting has proper guards and error handling.

The code correctly guards the central-DB update with checks for ExecutionId.HasValue, AccountReportApiHandler != null, and !string.IsNullOrEmpty(ApiUrl) before attempting to send data. The use of ConfigureAwait(false) at line 451 prevents potential deadlocks on background threads, and exceptions are properly logged rather than silently swallowed.

Note: This feature depends on EntityId, solutionId, and runsetName being correctly resolved in lines 381-399. If that resolution fails due to the null-check bug I flagged, these fields may be empty/Guid.Empty in the failure report.


479-523: LGTM: Error tracking logic is comprehensive and correct.

The enhancements to error tracking are well-designed:

  1. Line 481: Guards against setting ErrorSource to an empty value.
  2. Line 485: Correctly excludes "Error(s) occurred process exit code" messages from ExecutionError list since they're handled separately at lines 435-462.
  3. Lines 494-518: Thoroughly extracts error details including ErrorOriginPath, ErrorSource, retry counts, and ActionId from structured log messages.
  4. Line 519: Ensures errors are only reported after all retries are exhausted (TotalRetries == CurrentRetry), preventing duplicate error entries during retry attempts.

528-538: LGTM: Regex pattern is robust for operation name extraction.

The improved regex pattern @"\band Name\s+([^,\r\n]+)" at line 530 properly handles edge cases:

  • \b ensures "Name" is matched as a whole word
  • \s+ handles variable whitespace between "Name" and the value
  • [^,\r\n]+ captures the operation name until a comma or newline, preventing incorrect captures when names contain special characters

This addresses the robustness concerns from the previous review.

Based on learnings


542-552: LGTM: Post-operation regex matches Pre-operation pattern.

The regex pattern at line 544 is identical to the Pre-operation pattern, ensuring consistent operation name extraction across both Pre and Post Run Set operations. This consistency is important for reliable error tracking.


580-609: LGTM: Error extraction is tailored to operation type.

The addition of the isRunsetOperation parameter at line 580 enables appropriate error message extraction:

  • Runset operations (lines 586-596): Extracts errors from the "Errors= (.*?)\n" pattern, which matches Pre/Post Run Set operation log format.
  • Action/Setup errors (lines 599-608): Uses the existing "Error Details=([\s\S]*?)\r?\nExtra Details=" pattern for detailed action failures.

This ensures error messages are correctly captured regardless of their source context.

Comment thread Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs
@prashelke
prashelke enabled auto-merge October 18, 2025 08:29

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs (4)

495-512: Make newline handling OS-agnostic in regex captures.

Use \r?\n to handle Windows/Linux line endings.

-                        var match = Regex.Match(evt.RenderedMessage, @"SourcePath= (.*?)\n");
+                        var match = Regex.Match(evt.RenderedMessage, @"SourcePath=\s*(.*?)\r?\n");
@@
-                        var ActionNamematch = Regex.Match(evt.RenderedMessage, @"Description= (.*?)\n");
+                        var ActionNamematch = Regex.Match(evt.RenderedMessage, @"Description=\s*(.*?)\r?\n");
@@
-                        var TotalRetriesmatch = Regex.Match(evt.RenderedMessage, @"Total Retries Configured= (.*?)\n");
+                        var TotalRetriesmatch = Regex.Match(evt.RenderedMessage, @"Total Retries Configured=\s*(.*?)\r?\n");
@@
-                        var CurrentRetrymatch = Regex.Match(evt.RenderedMessage, @"Current Retry Iteration= (.*?)\n");
+                        var CurrentRetrymatch = Regex.Match(evt.RenderedMessage, @"Current Retry Iteration=\s*(.*?)\r?\n");

573-576: Await with ConfigureAwait(false) on background worker.

Prevents unnecessary context capture and matches surrounding awaits.

-                bool isSuccess = await AccountReportApiHandler.SendExecutionLogToCentralDBAsync(ApiUrl, ExecutionLogRequest);
+                bool isSuccess = await AccountReportApiHandler
+                    .SendExecutionLogToCentralDBAsync(ApiUrl, ExecutionLogRequest)
+                    .ConfigureAwait(false);

261-266: Include exception when logging Append failures for diagnosis.

Current log drops the stack trace.

-                Reporter.ToLog(eLogLevel.DEBUG, $"[HttpLogAppender] Error in Append: {ex.Message}");
+                Reporter.ToLog(eLogLevel.DEBUG, "[HttpLogAppender] Error in Append", ex);

52-73: HttpLogAppender: handler vs ApiUrl gateway mismatch — construct handler from base URL, compute gateway-appended ApiUrl separately.

Confirmed: HttpLogAppender creates AccountReportApiHandler from the raw setter value then overwrites _apiUrl with value+gateway. AccountReportApiHandler.SendExecutionLogToCentralDBAsync builds FinalAPIUrl by appending SEND_EXECUTIONLOG to the passed apiUrl — this can produce duplicated segments like …/api/AccountReport/api/AccountReport/…. Fix: keep a base URL for the handler and build a separate ApiUrlWithGateway for direct calls.

File: Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs (getter/setter around lines ~52–73; similar pattern at ~106–116)

Minimal suggested changes (still relevant):

-                    _apiUrl = value;
-                    _accountReportApiHandler = string.IsNullOrWhiteSpace(_apiUrl) ? null : new AccountReportApiHandler(_apiUrl);
-                    _apiUrl = $"{value}{GingerPlayEndPointManager.GetAccountReportServiceGateWay()}"; //Final Url with gateway
+                    var baseUrl = value?.TrimEnd('/');
+                    var gateway = GingerPlayEndPointManager.GetAccountReportServiceGateWay()?.Trim('/');
+                    // Handler must use the base (no gateway) to avoid double-append with relative endpoints
+                    _accountReportApiHandler = string.IsNullOrWhiteSpace(baseUrl) ? null : new AccountReportApiHandler(baseUrl);
+                    // Final URL for direct calls that require the gateway prefix
+                    _apiUrl = string.IsNullOrWhiteSpace(baseUrl) || string.IsNullOrWhiteSpace(gateway)
+                        ? baseUrl
+                        : $"{baseUrl}/{gateway}";

Guard the getter so the handler is created from a canonical base URL (not from _apiUrl that may include gateway):

-                if (_accountReportApiHandler == null)
-                {
-                    if (!string.IsNullOrEmpty(_apiUrl))
-                    {
-                        _accountReportApiHandler = new AccountReportApiHandler(_apiUrl);
-                    }
-                }
+                if (_accountReportApiHandler == null && !string.IsNullOrWhiteSpace(GingerPlayEndPointManager.GetAccountReportServiceUrl()))
+                {
+                    _accountReportApiHandler = new AccountReportApiHandler(GingerPlayEndPointManager.GetAccountReportServiceUrl());
+                }

Reason: SendExecutionLogToCentralDBAsync builds FinalAPIUrl via $"{apiUrl.TrimEnd('/')}/{SEND_EXECUTIONLOG}" (AccountReportApiHandler.cs) — passing a gateway-appended ApiUrl will duplicate the "/api/AccountReport" segment. The above keeps the handler bound to the base endpoint and ensures ApiUrl used for direct POSTs includes the gateway once.

♻️ Duplicate comments (2)
Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs (2)

406-414: Reset run-state flags on start/end to prevent leakage across runs.

isRunSetStarted is never cleared; pre/post flags aren’t reset at boundaries, leading to misclassification.

                 if (evt.RenderedMessage.IndexOf("Run Set Execution Started", StringComparison.OrdinalIgnoreCase) >= 0)
                 {
                     isExecutionStarted = true;
-                    isRunSetStarted = true;
-                    EntityId = Guid.Empty;
-                    solutionId = Guid.Empty;
-                    runsetName = string.Empty;
+                    isRunSetStarted = true;
+                    isPreRunSetOperation = false;
+                    isPostRunSetOperation = false;
+                    EntityId = Guid.Empty;
+                    solutionId = Guid.Empty;
+                    runsetName = string.Empty;
                 }
@@
                 if (evt.RenderedMessage.IndexOf("Run Set Execution Ended", StringComparison.OrdinalIgnoreCase) >= 0)
                 {
                     isExecutionStarted = false;
+                    isRunSetStarted = false;
+                    isPreRunSetOperation = false;
+                    isPostRunSetOperation = false;
                     EntityId = Guid.Empty;
                     solutionId = Guid.Empty;
                     runsetName = string.Empty;
                 }

Also applies to: 415-424, 426-432


168-173: Filter TaskCanceledException before logging to avoid noise during shutdown.

Log only unexpected exceptions.

-            // Handle TaskCanceledException explicitly
-            Reporter.ToLog(eLogLevel.DEBUG, "Dispose Error disposing HttpLogAppenders", ex);
-            ex.Handle(e => e is TaskCanceledException);
+            // Filter expected cancellations first; log only unexpected ones
+            var hasUnexpected = !ex.Handle(e => e is TaskCanceledException);
+            if (hasUnexpected)
+            {
+                Reporter.ToLog(eLogLevel.DEBUG, "Dispose: unexpected error disposing HttpLogAppenders", ex);
+            }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1f6e2e3 and f2c824b.

📒 Files selected for processing (1)
  • Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs (11 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs (3)
Ginger/GingerCoreCommon/ReporterLib/Reporter.cs (1)
  • Reporter (28-357)
Ginger/GingerCoreNET/WorkSpaceLib/WorkSpace.cs (1)
  • WorkSpace (61-1006)
Ginger/GingerCoreNET/Run/RunListenerLib/CenteralizedExecutionLogger/AccountReportApiHandler.cs (4)
  • AccountReportApiHandler (38-809)
  • AccountReportApiHandler (66-89)
  • AccountReportApiHandler (90-93)
  • AccountReportRunSet (94-119)
🔇 Additional comments (2)
Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs (2)

581-610: Good: extract SetExecutionError and keep it stateless.

Static helper with clean separation of runset vs execution parsing looks fine.


367-370: Refactoring complete and verified—static fields successfully eliminated.

All references to EntityId, solutionId, and runsetName are consistently instance-scoped. The fields are:

  • Declared as private instance members with proper initialization (Guid.Empty, string.Empty)
  • Populated lazily from WorkSpace state without cross-run bleed
  • Reset on execution boundaries (lines 410–412, 429–431) to isolate context per appender instance
  • Used exclusively as instance members in request objects (lines 446–448)

No static qualifiers, class-level access, or lingering references remain. The refactoring eliminates the cross-run state-bleeding risk identified in the review.

Comment thread Ginger/GingerCoreNET/log4netLib/HttpLogAppender.cs
@prashelke
prashelke merged commit b46119a into Releases/Official-Release Oct 18, 2025
16 of 17 checks passed
@prashelke
prashelke deleted the BugFix/MobileAIFineTuneFix branch October 18, 2025 09:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants