Skip to content

Add logging to FunctionInvokingChatClient for approval flow, error handling, and loop control#7228

Merged
stephentoub merged 10 commits intomainfrom
copilot/add-logging-to-function-invoking-chat-client
Jan 26, 2026
Merged

Add logging to FunctionInvokingChatClient for approval flow, error handling, and loop control#7228
stephentoub merged 10 commits intomainfrom
copilot/add-logging-to-function-invoking-chat-client

Conversation

Copy link
Contributor

Copilot AI commented Jan 24, 2026

Implementation: Add Logging to FunctionInvokingChatClient ✅

Changes Made

  1. StyleCop Suppression: Added #pragma warning disable SA1204 instead of reordering methods ✅
  2. Logging Implementation:
    • Added 7 new LoggerMessage methods for approval flow, error handling, and loop control ✅
    • Converted 3 static methods to instance methods to enable logging access ✅
    • Added logging calls at critical decision points (including early termination paths) ✅
    • Function names wrapped in single quotes for consistency ✅
    • Removed configuration parameters from call-specific logs ✅
    • Added logging for empty tool list termination scenario ✅
  3. Tests: Added 6 comprehensive tests, all passing ✅
    • LogsFunctionNotFound - Validates logging when unknown functions are requested
    • LogsNonInvocableFunction - Validates logging for declaration-only functions
    • LogsFunctionRequestedTermination - Validates logging when functions request termination
    • LogsFunctionRequiresApproval - Validates logging for approval-required functions
    • LogsProcessingApprovalResponse - Validates logging when processing approval responses
    • LogsFunctionRejected - Validates logging when functions are rejected
    • Note: LogMaxConsecutiveErrorsExceeded covered by existing ContinuesWithFailingCallsUntilMaximumConsecutiveErrors test
  4. Code Quality: Fixed typo in XML documentation (Genreate → Generate) ✅

Test Results

  • ✅ All 85 FunctionInvokingChatClientTests passing (79 existing + 6 new)
  • ✅ Tested on net8.0, net9.0, and net10.0
  • ✅ Build succeeds without errors or warnings
  • ✅ Code review: No issues
  • ✅ CodeQL security: No issues

Logging Coverage

Approval Flow (Debug): approval requests, response processing, rejections
Error Handling (Warning): max consecutive errors exceeded, function not found
Loop Control (Debug): non-invocable functions, termination requests, max iterations

Original prompt

Summary

The FunctionInvokingChatClient class in src/Libraries/Microsoft.Extensions.AI/ChatCompletion/FunctionInvokingChatClient.cs is missing important logging in several areas that would improve observability and debugging.

Missing Logging Areas

1. Function Approval Flow

There's no logging when:

  • A function call is converted to an approval request
  • An approval response is received (approved or rejected)
  • A rejected function call is processed

2. Error Handling Scenarios

Missing logging for:

  • When MaximumConsecutiveErrorsPerRequest is exceeded (before throwing)
  • When an unknown/not-found function is requested
  • When TerminateOnUnknownCalls causes early termination

3. Loop Control Flow

No logging when:

  • The function calling loop terminates due to a non-invocable tool (e.g., AIFunctionDeclaration that isn't an AIFunction)
  • A function requests termination via context.Terminate

4. Streaming-Specific Events

Missing logging for streaming scenarios where approval handling differs from non-streaming.

Suggested Additional Log Methods

// Approval flow logging
[LoggerMessage(LogLevel.Debug, "Function {FunctionName} requires approval. Converting to approval request.")]
private partial void LogFunctionRequiresApproval(string functionName);

[LoggerMessage(LogLevel.Debug, "Processing approval response for {FunctionName}. Approved: {Approved}")]
private partial void LogProcessingApprovalResponse(string functionName, bool approved);

[LoggerMessage(LogLevel.Debug, "Function {FunctionName} was rejected. Reason: {Reason}")]
private partial void LogFunctionRejected(string functionName, string? reason);

// Error handling logging
[LoggerMessage(LogLevel.Warning, "Maximum consecutive errors ({MaxErrors}) exceeded. Throwing aggregated exceptions.")]
private partial void LogMaxConsecutiveErrorsExceeded(int maxErrors);

[LoggerMessage(LogLevel.Warning, "Function {FunctionName} not found. TerminateOnUnknownCalls={Terminate}")]
private partial void LogFunctionNotFound(string functionName, bool terminate);

// Loop control logging
[LoggerMessage(LogLevel.Debug, "Function {FunctionName} is not invocable (declaration only). Terminating loop.")]
private partial void LogNonInvocableFunction(string functionName);

[LoggerMessage(LogLevel.Debug, "Function {FunctionName} requested termination of the processing loop.")]
private partial void LogFunctionRequestedTermination(string functionName);

Implementation Notes

  • Add the new LoggerMessage partial method declarations to the class
  • Call these logging methods at the appropriate points in the code
  • Use appropriate log levels (Debug for normal flow, Warning for error conditions)
  • The most impactful additions are logging around the approval flow and error threshold exceeded scenarios, as these represent significant state changes that are currently silent

This pull request was created from Copilot chat.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Microsoft Reviewers: Open in CodeFlow

Copilot AI and others added 5 commits January 24, 2026 14:28
Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
Copilot AI changed the title [WIP] Add logging for missing areas in FunctionInvokingChatClient Add logging to FunctionInvokingChatClient for approval flow, error handling, and loop control Jan 24, 2026
Copilot AI requested a review from stephentoub January 24, 2026 14:50
@stephentoub
Copy link
Member

@copilot

  1. Don't reorder the methods. Instead just suppress the style top diagnostics at the top of the file after the uaings
  2. Please add tests / implement the todos you left.

…ests

- Suppressed SA1204 StyleCop diagnostic instead of reordering methods
- Reverted FunctionInvokingChatClient to original method order
- Added logging implementation without method reordering
- Added 6 comprehensive tests for logging functionality
- Tests cover: function not found, non-invocable function, termination, approval flow, rejection

Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jan 24, 2026

@copilot

  1. Don't reorder the methods. Instead just suppress the style top diagnostics at the top of the file after the uaings
  2. Please add tests / implement the todos you left.

Done in commit 1d28363:

  1. Reverted method reordering and added #pragma warning disable SA1204 suppression instead
  2. Implemented 6 logging tests - working on fixing remaining failures and adding max consecutive errors test

@stephentoub
Copy link
Member

@copilot fix the test failures

- Added logging for early termination path in ShouldTerminateForFunctionCall method
- Fixed LogsFunctionNotFound test to use correct error message format
- Fixed LogsNonInvocableFunction test with proper expected output
- Fixed LogsFunctionRequestedTermination test to use FunctionInvokingChatClient.CurrentContext
- Simplified LogsProcessingApprovalResponse and LogsFunctionRejected tests to use direct client calls
- Fixed LogsFunctionRequiresApproval test to include user message in expected output
- All 85 FunctionInvokingChatClient tests now passing (79 existing + 6 new)

Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jan 24, 2026

@copilot fix the test failures

Fixed in commit 42b55c4. All 85 FunctionInvokingChatClient tests now passing (79 existing + 6 new logging tests) on net8.0, net9.0, and net10.0.

Copy link
Member

@stephentoub stephentoub left a comment

Choose a reason for hiding this comment

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

@copilot please re-review the whole class... Any other conditions that would be valuable to log?

@stephentoub stephentoub marked this pull request as ready for review January 24, 2026 23:39
Copilot AI review requested due to automatic review settings January 24, 2026 23:39
@stephentoub stephentoub requested a review from a team as a code owner January 24, 2026 23:39
@stephentoub stephentoub requested a review from tarekgh January 24, 2026 23:39
@stephentoub stephentoub requested a review from jozkee January 24, 2026 23:39
This was referenced Feb 16, 2026
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.

3 participants