Coject.Core.Logging
1.1.0
dotnet add package Coject.Core.Logging --version 1.1.0
NuGet\Install-Package Coject.Core.Logging -Version 1.1.0
<PackageReference Include="Coject.Core.Logging" Version="1.1.0" />
<PackageVersion Include="Coject.Core.Logging" Version="1.1.0" />
<PackageReference Include="Coject.Core.Logging" />
paket add Coject.Core.Logging --version 1.1.0
#r "nuget: Coject.Core.Logging, 1.1.0"
#:package Coject.Core.Logging@1.1.0
#addin nuget:?package=Coject.Core.Logging&version=1.1.0
#tool nuget:?package=Coject.Core.Logging&version=1.1.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. Sprint 01 adds a validated, configurable storage layout without changing the Contracts 3.0 records or the existing durability and ownership guarantees.
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.
The Sprint 01 storage contract is documented here as an additive configuration surface. This documentation change does not change project/package version fields, publish a package, upgrade a consumer, or deploy an application. Package publication and application deployment are separate approvals.
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. CSCC is
disabled in this safe example, so endpoint, key, and scope values are omitted.
{
"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
},
"Storage": {
"Instance": {
"Mode": "Generated",
"Id": null,
"ConflictPolicy": "Fail"
},
"Paths": {
"InstanceRoot": "{root}/{service}/{environment}/{instance}",
"LocalRoot": "{instanceRoot}/local",
"ApplicationRoot": "{localRoot}/application",
"AuditRoot": "{localRoot}/audit",
"QuarantineRoot": "{laneRoot}/quarantine",
"SpoolRoot": "{instanceRoot}/spool",
"LogSpoolRoot": "{spoolRoot}/logs",
"AuditSpoolRoot": "{spoolRoot}/audits",
"ProviderOutboxRoot": "{root}/outbox",
"OutboxQuarantineRoot": "{outboxLaneRoot}/quarantine",
"OutboxArchiveRoot": "{outboxLaneRoot}/archive"
},
"Files": {
"ApplicationSegment": "application-{service}-{environment}-{instance}-{segment}.jsonl",
"AuditSegment": "audit-{service}-{environment}-{instance}-{segment}.jsonl",
"WriterLock": ".writer.lock",
"InstanceOwnershipLock": ".ownership.lock",
"OutboxMetadata": "outbox-metadata.json"
}
}
},
"Cscc": {
"Enabled": false
},
"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.
Sprint 01 configurable storage contract
The Local.Storage section is additive. Omitting it produces the exact
existing layout and names; Local.RootPath remains the compatibility alias
for {root}. The resolver is shared by local application/audit providers,
Core spool, provider outbox, retention, health, diagnostics, and recovery so
those components cannot drift to different paths.
Instance identity and ownership
| Mode | Contract |
|---|---|
Generated |
Default. Core generates a new safe instance value for every process start. Existing per-process isolation and restart behavior remain unchanged. |
Stable |
Explicit operator choice. A safe non-empty Instance.Id is required. Restarts using the same root, service, environment, and ID reopen the same instance and continue its valid segments. |
Stable is an exclusive single-owner mode. The local lanes and durable
storage acquire their ownership locks before opening, repairing, rotating,
cleaning, or recovering files. If another process owns the stable instance,
ConflictPolicy: "Fail" (the default) returns a bounded failure and
ConflictPolicy: "Defer" returns a bounded deferred disposition. Both
policies leave the owned storage untouched: the process does not append,
truncate, repair, rotate, or clean it, and it never silently falls back to a
generated ID. Safe health/startup reporting uses the path-free codes
STABLE_OWNERSHIP_CONFLICT or STABLE_OWNERSHIP_CONFLICT_DEFERRED. A stable
instance that is currently owned is not treated as a released predecessor by
previous-instance recovery.
The operator ID is an identity component, not a path. It must pass the same
safe component validation as other resolved identities; do not use a path,
separator, wildcard, control character, or .. segment as an ID.
Closed template grammar
Only these case-sensitive tokens are valid:
| Token | Meaning |
|---|---|
{root} |
The configured Local.RootPath. |
{service} |
The sanitized service identity. |
{environment} |
The sanitized configured environment. |
{instance} |
The generated or explicit stable instance identity. |
{instanceRoot} |
The resolved service/environment/instance root. |
{localRoot} |
The resolved local root. |
{spoolRoot} |
The resolved Core spool root. |
{laneRoot} |
The root of the local lane currently being resolved. |
{outboxLaneRoot} |
The resolved provider/record-type outbox lane. |
{segment} |
The library-controlled monotonically increasing segment number. |
Path templates resolve in dependency order and must stay inside the approved
root. They reject unknown tokens, malformed or cyclic references, absolute
child segments, .., wildcards, control characters, empty required values,
root escapes, collisions, and symlink/reparse-point paths. The closed
contract keeps provider outbox storage under {root}/outbox; an external
outbox root is not part of this recommendation.
File-name templates are names, not paths. They reject directory separators,
wildcards, control characters, reserved device names, and unknown tokens.
ApplicationSegment and AuditSegment must each contain exactly one
{segment} token. The segment number is library-owned and remains an eight
digit sequence (00000001, 00000002, ...). Ready, inflight, temporary,
quarantine, archive, reason, checksum, metadata, and ownership lifecycle
semantics remain library-owned even when an allowed name is configured.
Resulting layout
With RootPath: "logs", service SampleService, environment Production,
and a generated instance generated-01, the default-compatible layout is:
<working-directory>/logs/SampleService/Production/generated-01/
local/application/
application-SampleService-Production-generated-01-00000001.jsonl
.writer.lock
quarantine/
local/audit/
audit-SampleService-Production-generated-01-00000001.jsonl
.writer.lock
quarantine/
spool/
.ownership.lock
logs/
audits/
quarantine/logs/
quarantine/audits/
<working-directory>/logs/outbox/
outbox-metadata.json
<destination>/logs/
<entry>.ready | <entry>.inflight
quarantine/<entry>.quarantine
archive/<entry>.archive
<destination>/audits/
<entry>.ready | <entry>.inflight
quarantine/<entry>.quarantine
archive/<entry>.archive
<destination> is a validated provider component; the CSCC adapter uses
Cscc. The outbox keeps logs and audits isolated by destination and record
type. The internal files shown above are patterns, not application data to
edit manually.
For a fixed application/audit root across restarts, use stable mode with an explicit operator ID and keep the instance component in the path. This is the recommended single-deployment example:
{
"CojectLogging": {
"Local": {
"RootPath": "logs",
"Storage": {
"Instance": {
"Mode": "Stable",
"Id": "primary",
"ConflictPolicy": "Fail"
},
"Paths": {
"InstanceRoot": "{root}/{service}/{environment}/{instance}",
"LocalRoot": "{instanceRoot}/local",
"ApplicationRoot": "{localRoot}/application",
"AuditRoot": "{localRoot}/audit",
"QuarantineRoot": "{laneRoot}/quarantine",
"SpoolRoot": "{instanceRoot}/spool",
"LogSpoolRoot": "{spoolRoot}/logs",
"AuditSpoolRoot": "{spoolRoot}/audits",
"ProviderOutboxRoot": "{root}/outbox",
"OutboxQuarantineRoot": "{outboxLaneRoot}/quarantine",
"OutboxArchiveRoot": "{outboxLaneRoot}/archive"
},
"Files": {
"ApplicationSegment": "application-{service}-{environment}-{instance}-{segment}.jsonl",
"AuditSegment": "audit-{service}-{environment}-{instance}-{segment}.jsonl",
"WriterLock": ".writer.lock",
"InstanceOwnershipLock": ".ownership.lock",
"OutboxMetadata": "outbox-metadata.json"
}
}
}
}
}
Its local roots are fixed at
logs/<service>/<environment>/primary/local/application and
logs/<service>/<environment>/primary/local/audit; a restart reopens the
same highest valid segment. Do not remove {instance} while using
Generated, because that would merge unrelated process histories and create
a concurrent-writer conflict.
Rotation, retention, recovery, and quarantine
- On startup, stable mode discovers the highest valid segment owned by the active template. It appends when that segment is below the configured size, rotates safely when full, and repairs only an incomplete or invalid tail. Valid records are preserved; the invalid tail is quarantined before appending.
- Local retention matches only files owned by the active validated template, never the active segment or an unrelated file. Local invalid records and their bounded reason markers remain under the lane quarantine root until retention removes them.
- Core spool writes durable artifacts through an atomic temporary-to-ready transition, ownership and capability checks, and checksum validation. It recovers only from configured managed roots; malformed, unsafe, or checksum failures are moved to type-specific quarantine with a safe reason.
- Provider outbox entries preserve canonical redacted bytes and delivery metadata. Ready/inflight ownership, restart recovery, retry scheduling, permanent-failure quarantine, archive, and quarantine retention remain separate for each destination and record type. Archive and destructive lifecycle cleanup require the existing administrator authorization boundary.
- A graceful shutdown closes intake, drains within the configured shutdown bound, and spills unresolved ownership. An abrupt stop leaves recoverable artifacts; the next eligible owner reconciles them without importing an active or locked stable instance.
CSCC being disabled does not disable local logging, local auditing, rotation,
retention, quarantine, or Core spool recovery. With Cscc.Enabled: false, no
CSCC HTTP clients or remote calls are created; the local lanes remain the
source of record and provider outbox delivery is not attempted.
Migration and consumer handoff
Treat an instance-mode or template change as a storage migration. Core does not silently reinterpret old files under a new template, merge generated histories, rename existing directories, or delete old data.
- Record the current root, mode, ID (if stable), active segment numbers, and health state. Stop the application gracefully and verify that no process still owns the instance or its lanes.
- Take a recoverable backup of the complete managed root before changing a template or adopting an existing directory. Preserve the original tree until the new layout has been verified; restore rehearsal is recommended when the records are operationally important.
- Validate the new root/templates in a non-production or maintenance run.
Confirm the closed token grammar, root containment, ownership markers,
exact single
{segment}token in each JSONL name, and collision-free application/audit/spool/outbox roots. - For a layout-only cutover, start with the new template and let Core create a new stream. Keep the old tree read-only for historical access. This is the default safe procedure.
- For continuity, use
Stablewith an explicit safe operator ID and migrate only an intentionally selected compatible instance. Copy or move only validated, owned segments and durable artifacts while all writers are stopped; preserve canonical bytes and timestamps, resolve names to the new template, verify segment ordering and quarantine any invalid tail. Never copy an active or locked instance and never merge unrelated generated instances. - Start once, confirm the highest valid segment is discovered and append or rotate behavior is correct, then check local application/audit files, spool/outbox health, quarantine counts, and shutdown/restart continuity. Retain the backup until this verification is complete.
Generated-to-stable migration is therefore explicit: leaving Generated
keeps per-process isolation and starts a new instance on each process start;
changing to Stable with a new ID starts a new stable instance; reusing an
old directory is allowed only after the intentional backup, ownership, and
compatibility checks above. A stable ownership conflict is resolved by
stopping the competing owner or choosing a different reviewed ID; it is never
resolved by automatic identity fallback.
The companion handoff note is
handoff/phase-01/coject-core-logging-v1.01-s01-009-migration-handoff.md.
Publishing the library package and deploying/upgrading an application remain
separate approval decisions, even after the consumer configuration has been
verified.
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 and no Local.Storage section, 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 under the resolved spool quarantine roots. Provider outbox state is separate from the Core spool and uses the resolved provider/record-type roots, with ready, inflight, quarantine, archive, metadata, and ownership lifecycle files. 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.
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.