Skip to main content
Foveus can be used in .NET Worker Service and BackgroundService applications. Worker services do not have an ASP.NET HTTP middleware pipeline, so setup is slightly different from an HTTP API, and a worker has no execution boundary of its own. You mark where each unit of work starts and ends with BeginExecution. Use Foveus in worker services to capture:
  • ILogger logs
  • logged exceptions
  • outbound HTTP telemetry
  • metrics
  • one execution per unit of work, when you mark it with BeginExecution
  • trace propagation on outbound HTTP
  • SDK shutdown flushing
  • MassTransit consumers, when instrumentation is configured

Install the SDK

Install the Foveus SDK package.
If your worker uses Serilog, also install the Serilog integration.
During private beta, your package names or package source may be different. Use the package names and feed URL provided during onboarding.

Basic setup

Add Foveus to your worker host.
Do not call app.UseFoveus() in a worker service. It is ASP.NET Core middleware and only applies to HTTP applications. If the Foveus configuration is invalid (for example a missing or malformed API key), Foveus disables itself, writes a diagnostic to the console and to your application’s logs, and the worker keeps running without Foveus telemetry.

Configure the worker

Add a Foveus section to your configuration.
The key decides the mode: a fov_test_ key sends to Test mode and a fov_live_ key sends to Live mode. There is no separate mode setting. Environment is a label for your deployment. When you do not set it, it is test or live, taken from the key. Source is detected automatically; set it to worker only if detection picks the wrong value.

Execution boundaries for worker jobs

A BackgroundService runs for the whole life of the process, so Foveus cannot tell where one piece of its work ends and the next begins. Mark each unit of work — one loop iteration, one job pass, one batch — with BeginExecution.
BeginExecution requires Foveus.SDK 1.1.0-beta.18 or later.
Each scope is one execution:
  • It gets its own execution id and appears in the dashboard with trigger job, the name you gave it, and its measured duration.
  • Logs, logged exceptions, outbound HttpClient calls and metrics recorded inside the scope belong to it. Outbound calls appear as its child executions.
  • Its status is failed when you call MarkFailed() or log an exception inside it, degraded when you call MarkCancelled(), and success otherwise.
  • Disposing the scope ends the execution and restores the previous context, so the next iteration gets a new execution.
  • A scope started while another execution is active (an HTTP request, or an outer scope) is recorded as that execution’s child.
  • Concurrent workers each get their own execution; scopes do not leak between them.
Enter the scope in the method that does the work (using var execution = ... or a using block), not inside a callback. Then the worker’s own catch block — the line an on-call engineer reads first — still runs inside the execution.

Without a scope

Work done outside any execution is still captured, but it is not grouped:
  • logs are recorded without an execution id;
  • each logged exception becomes its own single-event execution, so an Issue counts every failure;
  • each outbound HTTP call is recorded as its own root execution;
  • custom metrics are recorded without an execution.
Foveus never invents a long-lived execution for a worker.

What works today

Outbound HTTP telemetry

Foveus instruments outbound HttpClient calls created through IHttpClientFactory.
Inside a BeginExecution scope, each call is recorded as a child of that execution and carries trace and execution headers to the service it calls.

MassTransit instrumentation

When configuring MassTransit, call AddFoveusInstrumentation:
Each consumed message then becomes an execution, linked to the request that published it when the publisher is instrumented too.
Message retries are not shown as separate attempts yet: a message that is retried appears as one execution. Consumer executions do not record a duration yet. MassTransit instrumentation is not automatic; the application must call cfg.AddFoveusInstrumentation(context). Verified with MassTransit’s in-memory transport; a RabbitMQ broker has not been tested.

Serilog workers

If your worker uses Serilog, use Foveus.Serilog.
Set EnableFoveusLoggerProvider to false in Serilog-first apps to avoid duplicate logs. BeginExecution works the same way with Serilog.
The Serilog sink sends logs. Exceptions logged through Serilog are not turned into Issues; exceptions logged through ILogger with the Foveus logger provider are.
See Serilog integration.

Troubleshooting

Logs do not appear

Check that:
  • AddFoveus(builder.Configuration) is called
  • the startup log does not say Foveus is disabled: — if it does, fix the reason it gives
  • the dashboard is showing the mode that matches your key (fov_test_ or fov_live_)
  • the worker is actually writing logs, at a level that is enabled
  • the service can reach Foveus

Logs are duplicated

If the worker uses Serilog, disable the built-in Foveus logger provider with "EnableFoveusLoggerProvider": false.

Worker jobs do not show as separate executions

Wrap each unit of work in BeginExecution. Without it, logs have no execution and each outbound call is its own root execution.

Outbound HTTP is not captured

Check that:
  • the worker uses IHttpClientFactory
  • Foveus is registered before clients are created
  • the call is not excluded by configuration

What to do next