Coject.Core.Logging
1.0.0
dotnet add package Coject.Core.Logging --version 1.0.0
NuGet\Install-Package Coject.Core.Logging -Version 1.0.0
<PackageReference Include="Coject.Core.Logging" Version="1.0.0" />
<PackageVersion Include="Coject.Core.Logging" Version="1.0.0" />
<PackageReference Include="Coject.Core.Logging" />
paket add Coject.Core.Logging --version 1.0.0
#r "nuget: Coject.Core.Logging, 1.0.0"
#:package Coject.Core.Logging@1.0.0
#addin nuget:?package=Coject.Core.Logging&version=1.0.0
#tool nuget:?package=Coject.Core.Logging&version=1.0.0
Coject Core Logging
Coject.Core.Logging is the provider-neutral runtime pipeline for Coject Contracts 3.0 logging and auditing. It accepts typed records, captures trusted server context, redacts sensitive values before ownership, writes application and audit JSONL locally, and optionally fans records out to a provider registered by another package.
This package owns the Core pipeline. The optional CSCC HTTP destination is in Coject.Core.Logging.Cscc. The package does not depend on CojectCore.Controller and does not register MVC controllers, routes, authentication, or database access.
Package and support
- Package:
Coject.Core.Loggingversion1.0.0 - Target framework:
net8.0 - Wire contract: Coject Contracts
3.0fromCoject.Core.Logging.Contracts3.0.0 - Repository: https://github.com/coject/CojectCore
- The package contains portable symbols (
.snupkg) and the packagedREADME.md, license, and icon.
Installation
<PackageReference Include="Coject.Core.Logging" Version="1.0.0" />
The package declares a dependency on Coject.Core.Logging.Contracts 3.0.0 plus the required Microsoft.Extensions abstraction packages. Add Coject.Core.Logging.Cscc separately when CSCC delivery is required.
Registration
The normal host-level boundary is AddCojectLogging. It is idempotent and registers the typed logger, local application and audit providers, durable fallback, health services, and coordinated shutdown.
using Coject.Core.Logging;
var builder = Host.CreateApplicationBuilder(args);
builder.AddCojectLogging();
using var host = builder.Build();
await host.RunAsync();
For an ASP.NET Core application:
using Coject.Core.Logging;
var builder = WebApplication.CreateBuilder(args);
builder.AddCojectLogging();
var app = builder.Build();
app.MapGet("/", () => Results.Ok("running"));
app.Run();
AddCojectLogging() replaces existing ILoggerProvider registrations by default so framework records have one ownership path. During a deliberate coexistence migration only, use:
builder.AddCojectLogging(options =>
options.ReplaceExistingFrameworkProviders = false);
AddCojectLoggingConfiguration(IServiceCollection, IConfiguration) is the lower-level boundary for hosts that need to compose registration manually. Prefer the host-builder method unless the application owns that composition explicitly.
Complete appsettings.json tree
The following is the complete bindable CojectLogging graph. The API key is a placeholder only; do not commit a real key. The CSCC section can remain disabled for a local-only deployment.
{
"CojectLogging": {
"Environment": "Production",
"TrustedContext": {
"KnownProxies": [],
"KnownNetworks": [],
"ForwardLimit": 1,
"PresentationTimeZoneId": "Asia/Riyadh"
},
"Local": {
"RootPath": "logs",
"Application": {
"Enabled": true,
"RetentionDays": 30,
"MaxSegmentSizeBytes": 104857600,
"BatchSize": 100,
"FlushIntervalMilliseconds": 1000
},
"Audit": {
"Enabled": true,
"RetentionDays": 365,
"MaxSegmentSizeBytes": 104857600,
"BatchSize": 20,
"FlushIntervalMilliseconds": 500
}
},
"Cscc": {
"Enabled": false,
"AppId": "sample-service",
"Endpoint": "https://cscc.example.invalid",
"ApiKey": "<YOUR_CSCC_API_KEY>",
"ContractVersion": "3.0",
"Scopes": [
"logging.write",
"audit.write"
],
"Delivery": {
"LogConcurrency": 4,
"AuditConcurrency": 2,
"AttemptTimeoutSeconds": 10
},
"CircuitBreaker": {
"FailureThreshold": 5,
"InitialCooldownSeconds": 30,
"MaxCooldownSeconds": 300,
"JitterRatio": 0.2,
"RateLimitPauseMinimumSeconds": 1,
"RateLimitPauseMaximumSeconds": 3600
}
},
"Queues": {
"Memory": {
"Logs": {
"MaxRecords": 10000,
"MaxBytes": 134217728
},
"Audits": {
"MaxRecords": 1000,
"MaxBytes": 268435456
}
},
"Overflow": {
"Logs": {
"MaxRecords": 25000,
"MaxBytes": 536870912
},
"Audits": {
"MaxRecords": 5000,
"MaxBytes": 1073741824
},
"HighSeverityReservationPercent": 25
},
"HighSeverityBurstLimit": 8,
"EnqueueTimeoutMs": 25,
"HandoffRetryInitialDelaySeconds": 1,
"HandoffRetryMaxDelaySeconds": 60,
"ShutdownDrainTimeoutSeconds": 10
},
"Outbox": {
"Retry": {
"InitialDelaySeconds": 2,
"Multiplier": 2,
"MaxDelaySeconds": 300,
"RetryAfterMinimumSeconds": 1,
"RetryAfterMaximumSeconds": 3600
},
"Logs": {
"MaxRecords": 100000,
"MaxBytes": 2147483648,
"HighSeverityReservationPercent": 25,
"QuarantineRetentionDays": 90
},
"Audits": {
"MaxRecords": 20000,
"MaxBytes": 4294967296,
"HighSeverityReservationPercent": 25,
"QuarantineRetentionDays": 365
}
},
"Redaction": {
"AdditionalSensitiveFields": []
},
"Health": {
"EmergencyDiagnosticMinimumIntervalSeconds": 60,
"Disk": {
"WarningFreeSpacePercent": 10,
"WarningFreeSpaceBytes": 2147483648,
"CriticalFreeSpacePercent": 5,
"CriticalFreeSpaceBytes": 536870912,
"CheckIntervalSeconds": 30
}
},
"Framework": {
"Enabled": true,
"MinimumLevel": "Information"
}
}
}
Property behavior and limits
Environmentdefaults toProduction; it must contain 1–64 printable characters.TrustedContext.KnownProxiescontains canonical proxy IPs;KnownNetworkscontains aligned CIDR networks. Each list has at most 100 unique entries.ForwardLimitis 1–8.PresentationTimeZoneIddefaults toAsia/Riyadhand is display-only.Local.RootPathis required, is resolved relative to the process working directory when relative, and cannot contain control characters, wildcards, or a..path segment. Application and audit JSONL sinks are mandatory in the configuration binding boundary. In this release, a missing orEnabled: falsesink binding is normalized to its enabled default; keep both valuestrueand control global disablement by not registering the package rather than relying on a local sink flag.- Local
RetentionDaysis 1–3650,MaxSegmentSizeBytesis 1–1073741824,BatchSizeis 1–1000, andFlushIntervalMillisecondsis 50–5000. Cscc.Enabledcontrols only the optional provider destination. When false, Core remains local-only and does not require valid endpoint, key, or scopes. When true,AppIdis a non-empty identifier of at most 128 characters,Endpointis an absolute HTTPS URI without user information,ApiKeyis one scalar value of 32–512 non-whitespace characters,ContractVersionis exactly3.0, and scopes are unique supported values containinglogging.write. Supported scopes arelogging.writeandaudit.write.Cscc.Delivery.LogConcurrencyandAuditConcurrencyare 1–32 with a combined maximum of 64.AttemptTimeoutSecondsis 1–60.Cscc.CircuitBreaker.FailureThresholdis positive; cooldown and rate-limit values must be positive finite numbers, maximum cooldown must not be below initial cooldown, maximum rate-limit pause must not be below minimum, andJitterRatiois greater than zero and at most 1.- Memory queue capacities are 1–1000000 records and 1–4294967296 bytes.
HighSeverityBurstLimitis 1–100,EnqueueTimeoutMsis 1–250, handoff retry delays are 1–60 and 1–300 seconds with maximum not below initial, and shutdown drain is 1–30 seconds. Queues.Overflow.HighSeverityReservationPercentis fixed at 25 in v1. Outbox lane reservation percentages are also fixed at 25.- Outbox capacities are 1–10000000 records and 1–17179869184 bytes. Quarantine retention is 1–3650 days. Retry delays and Retry-After bounds are positive finite values no greater than 3600 seconds; multiplier is 1–10; maximums cannot be below minimums.
Redaction.AdditionalSensitiveFieldsaccepts at most 100 non-empty printable field names, each at most 128 characters. Names are normalized for matching.- Health diagnostic interval is 1–3600 seconds. Disk warning/critical percentages are positive and at most 100, critical must be below warning, byte thresholds are positive with critical below warning, and the disk check interval is 5–300 seconds.
Framework.Enabledcontrols the compatibilityILoggerProvideradapter only.Framework.MinimumLevelmust be a defined Microsoft.Extensions.Logging level and does not filter explicitICojectLoggercalls.
Typed logging and auditing
Resolve ICojectLogger from DI. The facade prepares immutable Contracts records, validates them, redacts them, and attempts bounded Core ownership. An accepted record is independent of the caller after the ownership result returns.
using Coject.Core.Logging.Contracts;
using Coject.Core.Logging.Contracts.Payloads;
var logger = host.Services.GetRequiredService<ICojectLogger>();
var result = await logger.LogAsync(
CojectEvents.SystemExecution(new SystemExecutionPayload(stepName: "startup")),
CojectLogLevel.Info,
"Coject logging verification");
Console.WriteLine($"{result.Status}: {result.Reason}");
Audits use closed event/action factories from Contracts. A mutation audit must carry committed-state snapshots and a context provider must supply Module, Resource, and Operation.
using Coject.Core.Logging.Contracts;
using Coject.Core.Logging.Contracts.Payloads;
CojectAuditAction<DataCreationPayload> action =
CojectAuditActions.DataCreation(
new DataCreationPayload(newValues: persistedSnapshot));
var result = await logger.AuditAsync(action);
persistedSnapshot above is an application-created CojectSnapshot; do not pass request DTOs as a substitute for committed state. The Core audit validator rejects missing required context, incomplete snapshots, invalid event/action pairs, and no-change modifications.
Local JSONL and audit behavior
The local providers are always installed by Core. Each service instance gets separate application and audit lanes. With the default RootPath, the layout is:
<working-directory>/logs/<service>/<environment>/<instance>/local/application/
application-<service>-<environment>-<instance>-00000001.jsonl
<working-directory>/logs/<service>/<environment>/<instance>/local/audit/
audit-<service>-<environment>-<instance>-00000001.jsonl
The service segment is derived from the entry assembly, environment is the configured value, and the instance segment is generated by Core. Each lane has a .writer.lock, rotates at MaxSegmentSizeBytes, batches writes, flushes on its interval, and removes files outside retention. Invalid managed records are isolated under that lane’s quarantine directory instead of being mixed into active JSONL.
Application records are operational/framework logs. Audit records are typed Contracts 3.0 records. Their canonical body is a nested envelope plus payload object; no provider-specific routing metadata is added to the body.
Failure, retry, and durable fallback
The enqueue path is intentionally bounded by Queues.EnqueueTimeoutMs. Memory capacity is independent for logs and audits. When a record cannot remain in memory, Core uses its protected overflow spool under the instance root:
<instance-root>/spool/logs/
<instance-root>/spool/audits/
The spool uses ownership and capability checks, preserves canonical bytes, recovers in the background, and quarantines malformed or unsafe entries. Provider outbox state is separate from the Core spool. CSCC delivery (when installed) has independent log/audit queues, concurrency, retry, quota, and quarantine settings.
Transient transport failures, timeouts, HTTP 408/425/429, and HTTP 5xx responses are eligible for bounded retry. A valid Retry-After on HTTP 429 is honored within the configured limits. HTTP 401 and 403 are classified as authentication/scope failures. HTTP 400, 404, 405, 413, 415, 422, and other ordinary 4xx responses are permanent provider failures; they do not open the circuit and are not blindly retried. Uncertain outcomes such as an ingestion conflict are retained for reconciliation rather than treated as confirmed.
On shutdown, the coordinated shutdown service closes intake, drains within ShutdownDrainTimeoutSeconds, and spills unresolved ownership. Application code should still await host.StopAsync() during graceful shutdown.
Redaction and security
- Never put API keys, bearer tokens, passwords, cookies, connection strings, or raw authorization headers in records or README/configuration committed to source control.
- Contracts redaction runs before local persistence and provider handoff.
Redaction.AdditionalSensitiveFieldsadds normalized field names to the built-in sensitive set; it does not disable built-in redaction. - Keep
Cscc.ApiKeyin a secret provider or environment-variable override. The configuration binder requires one scalar value and the validator rejects whitespace/control characters. - Use HTTPS endpoints only. The CSCC adapter sends the key in
X-API-Key, sendsX-Correlation-ID, and does not copy credentials into canonical records or health snapshots. - Keep
KnownProxiesandKnownNetworksnarrow. Forwarded IP values are accepted only when rebuilt by a trusted edge and the connection matches a configured proxy or network. - System actors do not carry an actor IP. User and anonymous actors may carry a trusted normalized originating IP. Do not accept arbitrary client-supplied actor identity as trusted context.
Correlation, actor, and IP behavior
The capture boundary prefers a validated X-Correlation-ID, then an envelope correlation ID, and otherwise generates a safe correlation ID. If both header and envelope values exist they must match; valid IDs are 8–64 ASCII letters, digits, ., _, or -. Canonical occurrence time is UTC at millisecond precision. PresentationTimeZoneId affects display text only.
The trusted context model supports user, system, and anonymous actors. User/system actors require stable IDs; display names are bounded and sanitized. Request context fields are closed to correlationId, module, resource, operation, entityId, and statusCode. Business identifiers are bounded safe values, and status codes must be 100–599.
Minimal verification
- Start the host with
CojectLoggingconfigured andCscc.Enabledset tofalse. - Resolve
ICojectLoggerand run theSystemExecutionexample above. - Confirm an
application-*.jsonlfile appears under the configured local path and contains a Contracts 3.0 record. - For an audit integration, supply a trusted context provider with module/resource/operation, submit a closed
CojectAuditActionsaction after the database commit, and confirm anaudit-*.jsonlfile appears. - Check
ICojectLoggingHealthfor local queue, spool, disk, and lifecycle state rather than parsing credentials or provider response bodies.
Troubleshooting
| Symptom | Check |
|---|---|
| Host fails during startup | Read the safe options validation message. Check HTTPS endpoint, scalar key shape, exact 3.0 contract version, queue bounds, and disk thresholds. |
| No local file | Check the process working directory, safe Local.RootPath, write permissions, disk health, and whether the host was started long enough for the writer loop to flush. |
| Audit is rejected | Confirm the action is from a closed Contracts factory, snapshots represent committed state, and the context contains module, resource, and operation. |
| Framework logs are missing | Check Framework.Enabled and Framework.MinimumLevel; explicit typed records are independent of this filter. |
| CSCC is not called | Install/register Coject.Core.Logging.Cscc, set Cscc.Enabled to true, and verify the validated endpoint and key are supplied through secrets. |
| CSCC returns 401/403 | Verify the API key and the required logging.write/audit.write scope for the lane. |
| CSCC returns 422 | Treat it as a permanent persistence-validation failure. Inspect the provider’s contract validation and the safe diagnostic code; do not add blind retries. |
| Files accumulate in spool/outbox | Check provider reachability, circuit-breaker state, disk capacity, quota limits, and quarantine files. Reconcile only after confirming the provider’s acknowledgement semantics. |
Controller dependency decision
CojectCore.Controller is intentionally not referenced. Core logging is a hosting/infrastructure library and its public contracts do not use Controller types. Applications that use both libraries may reference both independently; adding a Controller dependency here would expand the runtime graph without providing logging functionality.
| 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 was computed. 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. |
-
net8.0
- Coject.Core.Logging.Contracts (>= 3.0.0)
- Microsoft.Extensions.Configuration.Abstractions (>= 9.0.0)
- Microsoft.Extensions.Configuration.Binder (>= 9.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 9.0.0)
- Microsoft.Extensions.Hosting.Abstractions (>= 9.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 9.0.0)
- Microsoft.Extensions.Options (>= 9.0.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Coject.Core.Logging:
| Package | Downloads |
|---|---|
|
Coject.Core.Logging.Cscc
Optional CSCC destination adapter for the provider-neutral Coject Core Logging pipeline, with separate log and audit HTTP lanes, Contracts 3.0 transport, bounded delivery, retry, and circuit-breaker behavior. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 47 | 8/15/2026 |
Initial publishable Coject Core Logging package. Includes the stable IHostApplicationBuilder.AddCojectLogging registration boundary, local JSONL application and audit sinks, durable fallback, and Contracts 3.0.0 support.