Enabling Tool Invocation Logging in FabrCore
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:
| ActivitySource | What 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:
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.
// 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.Metricscounters 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.
Builder of FabrCore and OpenCaddis.