> ## Documentation Index
> Fetch the complete documentation index at: https://docs.foveus.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Worker services

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.

Use Foveus in worker services to capture:

* `ILogger` logs
* logged exceptions
* outbound HTTP telemetry
* metrics
* trace propagation
* SDK shutdown flushing
* supported messaging instrumentation hooks

<Note>
  Full automatic per-job execution capture for arbitrary `BackgroundService` loops is not yet implemented. Foveus can capture worker telemetry today, but it does not automatically wrap every worker loop, queue message, or scheduled job as a separate execution unless supported instrumentation is used or the app records lifecycle events.
</Note>

## Install the SDK

Install the Foveus SDK package.

```bash theme={null}
dotnet add package Foveus.SDK
```

If your worker uses Serilog, also install the Serilog integration.

```bash theme={null}
dotnet add package Foveus.Serilog
```

<Note>
  During private beta, your package names or package source may be different. Use the package names and feed URL provided during onboarding.
</Note>

## Basic setup

Add Foveus to your worker host.

```csharp theme={null}
var builder = Host.CreateApplicationBuilder(args);

builder.Services.AddFoveus(builder.Configuration);

builder.Services.AddHostedService<Worker>();

var host = builder.Build();

await host.RunAsync();
```

Do not call `app.UseFoveus()` in a worker service.

`app.UseFoveus()` is ASP.NET Core middleware and only applies to HTTP applications.

## Configure the worker

Add a `Foveus` section to your configuration.

```json theme={null}
{
  "Foveus": {
    "ApiKey": "fov_test_...",
    "ServiceName": "billing-worker",
    "Source": "worker"
  }
}
```

Foveus uses Test mode by default.

For production, use a live key and set `Mode` to `live`.

```json theme={null}
{
  "Foveus": {
    "ApiKey": "fov_live_...",
    "ServiceName": "billing-worker",
    "Environment": "production",
    "Mode": "live",
    "Source": "worker"
  }
}
```

## What works today

In worker services, Foveus can capture:

| Capability                                                     | Status                    |
| -------------------------------------------------------------- | ------------------------- |
| `ILogger` logs                                                 | Supported                 |
| Logged exceptions                                              | Supported                 |
| Outbound `HttpClient` telemetry through `IHttpClientFactory`   | Supported                 |
| Trace and execution header propagation on outbound HTTP        | Supported                 |
| SDK shutdown flushing                                          | Supported                 |
| Source classification as `worker`                              | Supported                 |
| MassTransit instrumentation hooks                              | Supported when configured |
| Automatic per-job execution capture for arbitrary worker loops | Not fully supported yet   |

## Logging from workers

If your worker uses `ILogger`, Foveus can capture logs through the SDK logger provider.

```csharp theme={null}
public sealed class Worker : BackgroundService
{
    private readonly ILogger<Worker> _logger;

    public Worker(ILogger<Worker> logger)
    {
        _logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            _logger.LogInformation("Billing worker heartbeat at {Timestamp}", DateTimeOffset.UtcNow);

            await Task.Delay(TimeSpan.FromSeconds(30), stoppingToken);
        }
    }
}
```

Log meaningful lifecycle events so Foveus can show what happened.

Examples:

```csharp theme={null}
_logger.LogInformation("Started processing invoice {InvoiceId}", invoiceId);
_logger.LogInformation("Completed invoice {InvoiceId}", invoiceId);
_logger.LogError(ex, "Failed to process invoice {InvoiceId}", invoiceId);
```

## Exceptions

Logged exceptions can be sent to Foveus.

```csharp theme={null}
try
{
    await ProcessInvoiceAsync(invoiceId, stoppingToken);
}
catch (Exception ex)
{
    _logger.LogError(ex, "Failed to process invoice {InvoiceId}", invoiceId);
}
```

Foveus can capture:

* exception type
* exception message
* stack trace
* structured log properties
* service name
* environment
* source

## Outbound HTTP telemetry

Foveus can instrument outbound `HttpClient` calls created through `IHttpClientFactory`.

```csharp theme={null}
builder.Services.AddHttpClient("billing-provider");
```

Then use the client in your worker:

```csharp theme={null}
public sealed class Worker : BackgroundService
{
    private readonly IHttpClientFactory _httpClientFactory;
    private readonly ILogger<Worker> _logger;

    public Worker(IHttpClientFactory httpClientFactory, ILogger<Worker> logger)
    {
        _httpClientFactory = httpClientFactory;
        _logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        var client = _httpClientFactory.CreateClient("billing-provider");

        var response = await client.GetAsync("/invoices/pending", stoppingToken);

        _logger.LogInformation("Billing provider returned {StatusCode}", response.StatusCode);
    }
}
```

Foveus can propagate trace and execution headers on outbound HTTP calls where supported.

## MassTransit instrumentation

Foveus has MassTransit integration hooks.

When configuring MassTransit, call:

```csharp theme={null}
cfg.AddFoveusInstrumentation(context);
```

Example:

```csharp theme={null}
builder.Services.AddMassTransit(x =>
{
    x.UsingRabbitMq((context, cfg) =>
    {
        cfg.AddFoveusInstrumentation(context);

        cfg.ConfigureEndpoints(context);
    });
});
```

This helps Foveus attach telemetry to supported message-processing flows.

<Note>
  MassTransit instrumentation requires the application to call `cfg.AddFoveusInstrumentation(context)`. It is not automatic unless configured.
</Note>

## Serilog workers

If your worker uses Serilog, use `Foveus.Serilog`.

Install:

```bash theme={null}
dotnet add package Foveus.SDK
dotnet add package Foveus.Serilog
```

Configure Foveus:

```json theme={null}
{
  "Foveus": {
    "ApiKey": "fov_test_...",
    "ServiceName": "billing-worker",
    "Source": "worker",
    "EnableFoveusLoggerProvider": false
  }
}
```

Then configure the Serilog sink:

```csharp theme={null}
using Foveus.Serilog;
using Serilog;

var builder = Host.CreateApplicationBuilder(args);

builder.Services.AddFoveus(builder.Configuration);

builder.Services.AddSerilog((services, loggerConfiguration) =>
{
    loggerConfiguration
        .ReadFrom.Configuration(builder.Configuration)
        .ReadFrom.Services(services)
        .WriteTo.Foveus(services);
});

builder.Services.AddHostedService<Worker>();

var host = builder.Build();

await host.RunAsync();
```

Set `EnableFoveusLoggerProvider` to `false` in Serilog-first apps to avoid duplicate logs.

See [Serilog integration](/sdk/serilog).

## Job lifecycle logging

Because automatic per-job execution capture is not fully implemented for arbitrary workers yet, log the lifecycle of important jobs.

Use structured logs.

```csharp theme={null}
_logger.LogInformation("Started job {JobType} for {ReferenceId}", "InvoiceSync", referenceId);

try
{
    await SyncInvoiceAsync(referenceId, stoppingToken);

    _logger.LogInformation("Completed job {JobType} for {ReferenceId}", "InvoiceSync", referenceId);
}
catch (Exception ex)
{
    _logger.LogError(ex, "Failed job {JobType} for {ReferenceId}", "InvoiceSync", referenceId);
}
```

This gives Foveus useful evidence even before full worker execution boundaries are available.

## What does not work yet

Worker service support is still evolving.

Foveus does not yet automatically:

* wrap every `BackgroundService` loop as a separate execution
* know when an arbitrary worker job starts, succeeds, fails, or completes
* capture inbound request or response bodies in pure workers
* capture queue or job context for every queue library automatically
* create full job execution boundaries for arbitrary worker code

Use logs, structured properties, outbound HTTP instrumentation, and supported messaging hooks to give Foveus useful worker telemetry.

## Recommended worker setup

For a production worker:

```json theme={null}
{
  "Foveus": {
    "ApiKey": "fov_live_...",
    "ServiceName": "billing-worker",
    "Environment": "production",
    "Mode": "live",
    "Source": "worker",
    "CaptureProfile": "Balanced",
    "EnableSelfMonitoring": true
  }
}
```

If the worker uses Serilog:

```json theme={null}
{
  "Foveus": {
    "ApiKey": "fov_live_...",
    "ServiceName": "billing-worker",
    "Environment": "production",
    "Mode": "live",
    "Source": "worker",
    "EnableFoveusLoggerProvider": false
  }
}
```

## Troubleshooting

### Logs do not appear

Check that:

* `AddFoveus(builder.Configuration)` is called
* the API key is valid
* the dashboard is showing the right mode
* the worker is actually writing logs
* the log level allows the event
* the service can reach Foveus

### Logs are duplicated

If the worker uses Serilog, disable the built-in Foveus logger provider.

```json theme={null}
{
  "Foveus": {
    "EnableFoveusLoggerProvider": false
  }
}
```

### Outbound HTTP is not captured

Check that:

* the worker uses `IHttpClientFactory`
* Foveus is registered before clients are used
* the call is not excluded by configuration
* the service can reach the outbound target
* the SDK version supports outbound HTTP instrumentation

### Worker jobs do not show as separate executions

That is expected for arbitrary `BackgroundService` loops today.

Full automatic per-job execution capture is not yet implemented.

Log job lifecycle events or use supported instrumentation hooks such as MassTransit where available.

## What to do next

* Configure the SDK: [SDK configuration](/sdk/configuration)
* Use Serilog: [Serilog integration](/sdk/serilog)
* Review FoveusOptions: [FoveusOptions](/sdk/foveus-options)
* Review performance overhead: [Performance overhead](/sdk/performance-overhead)
