Davasorus.Utility.DotNet.SQS
2026.2.2.7
See the version list below for details.
dotnet add package Davasorus.Utility.DotNet.SQS --version 2026.2.2.7
NuGet\Install-Package Davasorus.Utility.DotNet.SQS -Version 2026.2.2.7
<PackageReference Include="Davasorus.Utility.DotNet.SQS" Version="2026.2.2.7" />
<PackageVersion Include="Davasorus.Utility.DotNet.SQS" Version="2026.2.2.7" />
<PackageReference Include="Davasorus.Utility.DotNet.SQS" />
paket add Davasorus.Utility.DotNet.SQS --version 2026.2.2.7
#r "nuget: Davasorus.Utility.DotNet.SQS, 2026.2.2.7"
#:package Davasorus.Utility.DotNet.SQS@2026.2.2.7
#addin nuget:?package=Davasorus.Utility.DotNet.SQS&version=2026.2.2.7
#tool nuget:?package=Davasorus.Utility.DotNet.SQS&version=2026.2.2.7
Davasorus.Utility.DotNet.SQS
Overview
Davasorus.Utility.DotNet.SQS provides utilities for publishing to and consuming from Amazon SQS from .NET applications. It handles message serialization, content-based deduplication, optional anonymization, optional location enrichment, OpenTelemetry tracing, and W3C trace-context propagation through SQS message attributes.
The package multi-targets net8.0 and net10.0.
Features
ISqsPublisher— typed publish,SqsResult<T>returns,CancellationTokeneverywhere, content-based deduplication that actually works (fixes a v1 bug).ISqsConsumer— typedReceiveAsync<T>with partial-batch tolerance,DeleteAsync,ChangeVisibilityAsync,DeleteBatchAsync.- W3C
traceparentinjection on publish, extraction on receive — end-to-end OpenTelemetry traces flow through SQS message attributes automatically. - Three AWS credential modes — decrypted-key (v1 behavior), AWS SDK credential chain (modern default for new apps), or supply your own
IAmazonSQS. - Three location-enrichment modes — off (default),
ipify.org+ipinfo.ioover HTTPS with Polly resilience, or supply your ownILocationProvider. - Owned anonymization & dedup state —
IAnonymizationPolicy+IReportedErrorTrackerreplace v1's reads ofMasterUiObj.AnonErrorReportingandTrelloErrorReportingObjs.Collection. - Singleton
IAmazonSQSwith cached queue URLs — fixes the v1 perf bug of building a new client per request. SqsResult<T>instead of"error"sentinel returns. v1ISqsServiceshim preserves the old sentinel for back-compat.[Obsolete]shims for v1 — existingISqsService/ISqsClient/ILocationService/ILocationClientcallers compile unchanged with migration warnings.
Quick start
// Defaults: decrypted-key credentials, location enrichment OFF, anonymization OFF.
services.AddSqsLogging();
// Inject the publisher in your app code:
public class MyService(ISqsPublisher sqs)
{
public async Task LogAsync(string message, CancellationToken ct)
{
var model = new TrelloMessageQueueModel { Message = message };
var result = await sqs.SendLoggingMessageAsync(model, ct);
if (!result.IsSuccess)
// result.Error has the exception
;
}
}
Configuration
Fluent
services.AddSqsLogging(sqs => sqs
.WithCredentialChain() // AWS SDK default chain
.WithRegion("us-west-2")
.WithQueues(q => q
.Message("myapp-messages.fifo")
.Response("myapp-responses.fifo"))
.WithIpInfoLocation(l => l // opt in to enrichment
.CacheLocation(TimeSpan.FromHours(1))
.CacheIpAddress(TimeSpan.FromHours(4)))
.WithAnonymization(a => a
.Enabled(true)
.MaxErrorCollectionSize(500))
.WithResilience(r => r
.LocationRetryCount(3)));
appsettings.json
services.AddSqsLogging(builder.Configuration.GetSection("SqsOptions"));
{
"SqsOptions": {
"Aws": {
"Region": "us-east-1",
"CredentialMode": "CredentialChain",
"QueueUrlCacheTtl": "00:00:00"
},
"Queues": {
"Message": "myapp-messages.fifo",
"Response": "myapp-responses.fifo"
},
"Location": {
"EnableEnrichment": true,
"ProviderMode": "IpInfo",
"LocationCacheTtl": "01:00:00",
"IpAddressCacheTtl": "04:00:00"
},
"Anonymization": {
"Enabled": true,
"MaxErrorCollectionSize": 500
}
}
}
Hybrid
services.AddSqsLogging(
builder.Configuration.GetSection("SqsOptions"),
sqs => sqs.WithRegion("ap-southeast-2")); // fluent overrides config
Custom IAmazonSQS
services.AddSingleton<IAmazonSQS>(_ => new AmazonSQSClient(creds, myConfig));
services.AddSqsLogging(sqs => sqs.WithCustomClient());
Custom ILocationProvider
services.AddSingleton<ILocationProvider, MyInternalLocationProvider>();
services.AddSqsLogging(sqs => sqs.WithCustomLocationProvider());
Public surface
| Type | Lifetime | Purpose |
|---|---|---|
ISqsPublisher |
Scoped | Publish messages. Returns SqsResult<string> (the SQS message id). |
ISqsConsumer |
Scoped | Receive / delete / change-visibility primitives. |
ILocationProvider |
Singleton | Default NullLocationProvider; opt in to IpInfoLocationProvider. |
IAnonymizationPolicy |
Singleton | Owns the anonymous-reporting flag and username scrubbing. |
IReportedErrorTracker |
Singleton | Process-wide bounded dedup set. |
ISqsTransport |
Singleton | Thin IAmazonSQS wrapper with tracing + traceparent injection. |
IAmazonSQS |
Singleton | DI-owned; lifetime resolved via AwsCredentialMode. |
IQueueUrlCache |
Singleton | Memoizes GetQueueUrlAsync per queue name. |
SqsOptions (and the nested groups Aws, Queues, Location, Resilience, Anonymization) are bindable from IConfiguration and mutable via the fluent SqsOptionsBuilder.
Enabling Location Enrichment (opt-in)
Location enrichment is off by default in v2. Outgoing error reports will have empty UserCity / UserState unless you opt in. When enabled, this feature sends the host's public IP to https://api.ipify.org and https://ipinfo.io to resolve the city and region, and includes that information in error reports published to SQS.
You are responsible for disclosing this to end users in your application's privacy policy. Do not enable this feature in products subject to privacy regulations (GDPR, CCPA, HIPAA) without legal review.
services.AddSqsLogging(sqs => sqs.WithIpInfoLocation());
Telemetry
Activities are emitted on the following sources:
SQS.Transport— raw publish/receive/delete/change-visibility operations.SQS.Publisher— high-level publish methods (PublishAsync,SendLoggingMessageAsync, etc.).SQS.Consumer— high-level receive operations.Location.IpInfo— when location enrichment is opted in.
Metrics
The following metric instruments are emitted via System.Diagnostics.Metrics. All durations are in milliseconds.
| Instrument | Type | Source meter | Tags |
|---|---|---|---|
sqs.publish.duration |
Histogram<double> |
Davasorus.Utility.SQS.Transport |
messaging.destination.name, outcome (ok/fail), error.type (fail only) |
sqs.receive.duration |
Histogram<double> |
Davasorus.Utility.SQS.Transport |
same as above |
sqs.receive.batch_size |
Histogram<int> |
Davasorus.Utility.SQS.Transport |
messaging.destination.name |
sqs.queue_url_cache.hit |
Counter<long> |
Davasorus.Utility.SQS.Transport |
— |
sqs.queue_url_cache.miss |
Counter<long> |
Davasorus.Utility.SQS.Transport |
— |
sqs.dedup.skipped |
Counter<long> |
Davasorus.Utility.SQS.Publisher |
messaging.destination.name |
sqs.deserialize.failed |
Counter<long> |
Davasorus.Utility.SQS.Consumer |
messaging.destination.name, error.type |
error.type carries the fully-qualified exception type name. AWS SDK exception types are bounded, so cardinality stays low even when split per failure mode.
AWS SDK instrumentation parenting
When OpenTelemetry.Instrumentation.AWS is enabled (via TelemetryOptions.Tracing.EnableAws = true in the Davasorus.Utility.DotNet.Telemetry package), the AWS SDK emits its own spans for SQS HTTP calls. These appear as children of the SQS.Transport spans this package emits — package-level spans carry semantic context (queue, dedup id, message group), AWS spans carry wire-level detail (HTTP method, retries, response codes). No configuration is needed; AWS instrumentation parents to Activity.Current automatically.
Log/trace correlation
When TelemetryOptions.Logging.Enabled = true, OpenTelemetry's ILogger provider attaches TraceId, SpanId, and TraceFlags to every LogRecord emitted while an Activity is current. No scope wiring is required — _logger.LogError(...) calls inside SQS publish/receive paths are correlated automatically.
Outbound SQS messages carry traceparent (and tracestate when present) message attributes. On receive, ISqsConsumer.ReceiveAsync<T> parses the producer's traceparent into an ActivityContext and exposes it on ReceivedMessage<T>.ProducerActivityContext. To link your handler's spans to the producer's trace, pass that context as the parent when starting your activity:
foreach (var msg in result.Value!)
{
using var activity = MyActivitySource.StartActivity(
"Handle message",
ActivityKind.Consumer,
msg.ProducerActivityContext ?? default);
// ... process msg.Body, publish follow-ups, etc.
// Spans started inside this `using` block — including any ISqsPublisher.PublishAsync call —
// will be parented to the producer's trace.
await consumer.DeleteAsync(queueName, msg.ReceiptHandle, ct);
}
ReceiveOptions.ContinueTraceContext = false skips the parse and leaves ProducerActivityContext null.
Batch-delete behavior
DeleteBatchAsync accepts any number of receipt handles and chunks them internally to SQS's 10-entry-per-request limit. Per-handle outcomes are aggregated into a single BatchDeleteOutcome with Successful and Failed lists that preserve the caller's input order.
Migration from v1
Mapping table
| v1 | v2 |
|---|---|
ISqsService.SendLoggingMessage(msg) |
ISqsPublisher.SendLoggingMessageAsync(msg, ct) |
ISqsService.PublishMessage(msg, groupId) |
ISqsPublisher.PublishMessageAsync(msg, new SqsPublishOptions { MessageGroupId = groupId }, ct) |
ISqsClient.PublishAsync(q, msg, groupId) |
ISqsPublisher.PublishAsync(q, msg, new SqsPublishOptions { MessageGroupId = groupId }, ct) |
ILocationService.GetLocationInformation("city") |
ILocationProvider.GetAsync(LocationField.City, ct).ValueOrEmpty() |
MasterUiObj.AnonErrorReporting = true |
SqsOptions.Anonymization.Enabled = true (or register a custom IAnonymizationPolicy) |
new SqsOptionsBuilder().WithLocationCache(ts) |
new SqsOptionsBuilder().WithIpInfoLocation(l => l.CacheLocation(ts)) |
Check return == "error" |
Check result.IsSuccess, inspect result.Error |
Behavior changes to verify after upgrade
- Location enrichment defaults to off. If error reports need
UserCity/UserStatepopulated, call.WithIpInfoLocation()during DI setup. "error"sentinel preserved on the v1ISqsServiceshim — old call sites compile and behave exactly as before. New code should useISqsPublisherandSqsResult<T>.- Scrubbed username replacement changed from
" "to"[user]". Any log parsers searching for the single-space pattern need updating. - The
messaging.urltag is no longer emitted onSQS.Sendspans. Dashboards that read queue URLs from spans must derive them frommessaging.destination.nameplus AWS region. - The
messaging.message_group_idtag is renamed tomessaging.aws_sqs.message_group_id. This aligns with OTel v1.28's vendor-specific attribute prefix convention. Dashboards keying off the old name need updating.
Continuing to use the v1 surface
Every v1 interface is preserved as an [Obsolete] shim over the new API, declared in its v1 namespace. Existing using statements compile unchanged with deprecation warnings pointing at the v2 replacements. Migrate at your own pace.
Future work
A hosted-service consumer (long-poll loop, IMessageHandler<T> dispatch, automatic ack/nack with optional DLQ routing) will sit on top of the ISqsConsumer primitives in a future release. The current primitives are designed to be stable under that addition.
Dependencies
- AWSSDK.SQS
- Davasorus.Utility.DotNet.Contracts.Types / .Collections
- Davasorus.Utility.DotNet.Encryption (only used by
AwsCredentialMode.DecryptedKeys) - Davasorus.Utility.DotNet.Telemetry
- Microsoft.Extensions.{Caching.Memory, Http, Http.Resilience, Logging.Abstractions, Options}
License
MIT.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- AWSSDK.SQS (>= 4.0.2.32)
- Davasorus.Utility.Dotnet.Contracts.Collections (>= 2026.2.2.2)
- Davasorus.Utility.DotNet.Contracts.Types (>= 2026.2.2.2)
- Davasorus.Utility.DotNet.Encryption (>= 2026.2.2.13)
- Davasorus.Utility.DotNet.Telemetry (>= 2026.2.2.9)
- Microsoft.Extensions.Caching.Memory (>= 10.0.8)
- Microsoft.Extensions.Http (>= 10.0.8)
- Microsoft.Extensions.Http.Resilience (>= 10.6.0)
- Microsoft.Extensions.Logging (>= 10.0.8)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.8)
- Microsoft.Extensions.Options (>= 10.0.8)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 10.0.8)
-
net8.0
- AWSSDK.SQS (>= 4.0.2.32)
- Davasorus.Utility.Dotnet.Contracts.Collections (>= 2026.2.2.2)
- Davasorus.Utility.DotNet.Contracts.Types (>= 2026.2.2.2)
- Davasorus.Utility.DotNet.Encryption (>= 2026.2.2.13)
- Davasorus.Utility.DotNet.Telemetry (>= 2026.2.2.9)
- Microsoft.Extensions.Caching.Memory (>= 10.0.8)
- Microsoft.Extensions.Http (>= 10.0.8)
- Microsoft.Extensions.Http.Resilience (>= 10.6.0)
- Microsoft.Extensions.Logging (>= 10.0.8)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.8)
- Microsoft.Extensions.Options (>= 10.0.8)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 10.0.8)
NuGet packages (6)
Showing the top 5 NuGet packages that depend on Davasorus.Utility.DotNet.SQS:
| Package | Downloads |
|---|---|
|
Davasorus.Utility.DotNet.Api
API Interaction for TEPS Utilities with generic deserialization, configurable error reporting, and improved DI configuration. Supports REST, GraphQL, gRPC, WebSocket, SignalR, and SSE protocols. |
|
|
Davasorus.Utility.DotNet.SQL
SQL interaction code for TEPS Utilities |
|
|
Davasorus.Utility.DotNet.Services
Windows Service management (start, stop, enable, disable, enumerate) for TEPS Utilities, with OpenTelemetry tracing and DI-based wiring. Targets .NET 8 and .NET 10. |
|
|
Davasorus.Utility.DotNet.Config
Manipulating config file for TEPS Utilities |
|
|
Davasorus.Utility.DotNet.Caching
UCaching for TEPS Utilities |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2026.2.2.9 | 0 | 5/31/2026 |
| 2026.2.2.8 | 163 | 5/29/2026 |
| 2026.2.2.7 | 395 | 5/25/2026 |
| 2026.2.2.6 | 1,014 | 5/23/2026 |
| 2026.2.2.4 | 1,336 | 5/15/2026 |
| 2026.2.2.3 | 952 | 5/5/2026 |
| 2026.2.2.2 | 1,049 | 5/1/2026 |
| 2026.2.2.1 | 110 | 5/1/2026 |
| 2026.2.1.4 | 146 | 4/30/2026 |
| 2026.2.1.3 | 198 | 4/16/2026 |
| 2026.2.1.2 | 4,653 | 4/9/2026 |
| 2026.2.1.1 | 1,246 | 4/1/2026 |
| 2026.1.3.6 | 687 | 3/29/2026 |
| 2026.1.3.5 | 859 | 3/24/2026 |
| 2026.1.3.4 | 229 | 3/18/2026 |
| 2026.1.3.3 | 1,330 | 3/12/2026 |
| 2026.1.3.2 | 109 | 3/12/2026 |
| 2026.1.3.1 | 595 | 3/10/2026 |
| 2026.1.2.4 | 1,630 | 2/17/2026 |
| 2026.1.2.2 | 743 | 2/13/2026 |