Enabling Tool Invocation Logging in FabrCore

Eric Brasher February 21, 2026 at 10:52 AM 5 min read

FabrCore has extensive observability infrastructure built in. Before building custom logging agents, check what's already available.

One of the most common requests we see is "how do I log tool invocations?" The answer is usually: you already are — you just need to look in the right place. FabrCore ships with OpenTelemetry instrumentation, structured metrics, and integration points for the standard .NET logging pipeline. Here's what's available and how to use it.

Built-in Telemetry

FabrCore emits telemetry through three channels, all using standard .NET infrastructure:

OpenTelemetry ActivitySources

FabrCore defines several ActivitySource instances that emit distributed traces for key operations:

ActivitySourceWhat It Traces
FabrCore.Host.AgentGrain Agent message processing, lifecycle events, grain activation/deactivation
FabrCore.Sdk.AgentProxy Agent proxy operations, model invocations, tool resolution
FabrCore.Host.Extensions Host-level operations, configuration loading, service registration

Each activity carries tags with agent handle, message type, operation name, and duration. If you're already collecting OpenTelemetry traces, these activities show up automatically.

System.Diagnostics.Metrics

FabrCore publishes counters and histograms through the standard .NET metrics API:

  • Messages processed (counter, per agent)
  • Agents configured (gauge)
  • Errors encountered (counter, by error type)
  • Stream messages sent (counter)
  • MCP connections active (gauge)

These feed into any metrics collector that supports System.Diagnostics.Metrics — Prometheus, Application Insights, OTLP exporters.

Standard ILogger

All major operations log through ILogger at appropriate levels. Agent initialization, message routing, tool resolution, MCP connections, compaction, and errors all produce structured log entries with relevant properties.

Microsoft.Extensions.AI Tool Call Logging

For granular tool invocation logging, the UseLogging() middleware from Microsoft.Extensions.AI captures every function call made by the chat client — including tool name, arguments passed, results returned, and call duration:

Adding UseLogging Middleware
var chatClient = new ChatClientBuilder(innerClient)
    .UseLogging(loggerFactory)
    .Build();

This is a single line added to your chat client pipeline. The middleware wraps every GetResponseAsync and GetStreamingResponseAsync call, logging the full request and response cycle including any tool invocations the model triggers.

The logs are emitted through the standard ILogger pipeline at the Debug and Trace levels, so they integrate with whatever logging provider you've already configured.

What Gets Logged

When the UseLogging() middleware is active and your log level includes Debug, you'll see entries for each tool invocation that include:

  • Tool name — the function name the model selected (e.g., SearchDocuments, GetWeather)
  • Arguments — the JSON arguments the model provided to the tool
  • Result — the tool's return value sent back to the model
  • Duration — how long the tool execution took

All of this flows through the standard ILogger pipeline. No custom log infrastructure needed — it's structured logging that works with every .NET log provider out of the box.

Example Log Output
// Debug-level log entries from UseLogging middleware
[DBG] ChatClient.GetResponseAsync invoked. Messages: 3, Tools: 5
[DBG] Tool call: SearchDocuments({"query": "FabrCore compaction", "limit": 10})
[DBG] Tool result: SearchDocuments returned 3 results (42ms)
[DBG] ChatClient.GetResponseAsync completed. Duration: 1847ms

Use Your Existing Observability Stack

The key insight is that FabrCore's telemetry feeds into whatever you already use. There's no proprietary logging format or custom dashboard required:

  • Application Insights — FabrCore's ActivitySources and ILogger output appear as dependencies, traces, and custom events in your Application Insights workspace.
  • Seq — Structured log properties are preserved, so you can filter by agent handle, message type, or tool name directly in the Seq UI.
  • ELK Stack — Log entries serialize as structured JSON, ready for Elasticsearch indexing and Kibana dashboards.
  • Grafana + Prometheus — FabrCore's System.Diagnostics.Metrics counters export via the OpenTelemetry Prometheus exporter for real-time dashboards.

Before building a custom ring-buffer logging agent or writing a tool-invocation interceptor, check whether the data you need is already being emitted. In most cases, it's a matter of configuring your existing observability stack to collect what FabrCore is already producing.

Learn More

For the full telemetry reference — including how to configure OpenTelemetry exporters, set up custom metrics, and integrate with specific observability platforms — see the telemetry documentation.


Eric Brasher

Builder of FabrCore and OpenCaddis.