AuditSettings Class
Assembly: CodeEffects.Rule.Audit.dll
Namespace: CodeEffects.Rule.Audit
Summary
Specifies how an AuditRecorder gets what it records into the Rule Repository database, and what a record holds.
Syntax
public class AuditSettings
Every property has a default, so you set only what you want otherwise. Pass the settings to the constructor of the recorder. The recorder reads them when it is made: changing a property afterwards changes nothing, except Enabled and OnProblem, which are read every time they are used. A property that has a number that delivery cannot work with, such as a batch size under 1, makes the constructor of the recorder throw a RuleException with control number CE20008.
How a record reaches the database. Mode and Resilience decide it:
| Mode and resilience |
On the evaluating thread |
A process crash or kill loses |
A power loss loses |
Asynchronous with Journal (the default) |
The record is built and appended to the journal, handed to the operating system |
Nothing |
The last moment, as with any file; nothing with JournalFlush set to ToDisk |
Asynchronous with Drain |
The record is put on an in-memory queue |
What was queued, except at a normal exit or an unhandled exception, which move it for up to DrainTimeoutSeconds |
What was queued |
Asynchronous with Volatile |
The record is put on an in-memory queue |
What was queued, unless you called Flush or Dispose first |
What was queued |
Synchronous |
The record is built and written to the database before Evaluate returns |
Nothing, because nothing is held |
Nothing |
With a queue, a background thread builds the input of each record from the values that the engine read. It never reads your objects, and it lets go of them when the evaluation ends, so changing your object after an evaluation changes nothing in its record.
The journal. With Journal, every record is appended to a file in JournalFolder before the evaluation returns, and a background thread of the recorder moves the records into the database in batches of up to BatchSize. Each record carries its own ID and the database stores only IDs that it does not have yet, so a batch that is sent again after a crash is never stored twice. The files are deleted as soon as every record in them is in the database. A record that is cut short by a crash or damaged by the disk is skipped and reported as JournalDamaged, and the rest of the file is moved.
Each recorder writes its own files, and one recorder at a time moves a folder. A process that starts and finds files that a process that is gone left in the folder moves them at once, so several processes may share one folder, and a restarted container recovers what the crashed one left, if the folder is on a volume that survives. On a throwaway disk, mount a volume for the folder, or what was not yet moved is lost with the disk. To keep all database traffic out of your application, move the folder from another process with AuditJournal.
If the database cannot take a batch, the batch stays where it is and is tried again after RetryDelayMilliseconds, with the wait doubling on each failure up to MaxRetryDelaySeconds. Each failure is reported to OnProblem as DrainFailed. A batch is also tried again at once after a deadlock or a lost connection.
What WhenFull does. While the database is out of reach for long, the queue (QueueCapacity) or the journal (JournalCapMegabytes) fills up. WhenFull then decides: Drop the record and go on, Block the evaluation until there is room, or block it for up to BlockTimeoutMilliseconds and then drop the record. It does not apply in Synchronous mode, where nothing is held.
What Mode and Resilience do not change. What a record holds is the same in every mode, and is decided by RecordValues, ExcludedMembers, MaxCollectionItems and AnalyticsFields.
Constructors
Properties
AnalyticsFields
Type: System.Collections.Generic.IList<System.String>
Gets or sets the members to keep as analytics values, each by its path from the evaluated object, such as "Segment", "Customer.Region" or "QuotedPrice". A value is read when the evaluation ends, so a value that a setter of the rule set is the one that is kept, and it is written to a table of its own, indexed, which the analytics of the MCP server read. A text, the name of an enumeration member, a date and a true or false value are kept as text of up to 256 characters, and a number is kept as a number. A null, an object and a collection are not kept. To keep a value that no rule reads, pass it as a tag to AuditRecorder.Scope(..). A name is up to 128 characters long, with no spaces around it, otherwise the constructor of the recorder throws a RuleException with control number CE20006. The default is an empty list.
BatchSize
Type: System.Int32
Gets or sets the most records that are inserted in one transaction. The background thread takes whatever is waiting, up to this many, so batches grow by themselves while the database is the slower side. It must be at least 1. The default is 500.
BlockTimeoutMilliseconds
Type: System.Int32
Gets or sets how long an evaluation waits for room, in milliseconds, when WhenFull is BlockWithTimeout. It must not be negative. The default is 100.
DrainTimeoutSeconds
Type: System.Int32
Gets or sets how long AuditRecorder.Dispose(), AuditRecorder.Flush() and, with Drain, the process exiting wait for what is held to be in the database, in seconds. It must not be negative. The default is 30.
Enabled
Type: System.Boolean
Gets or sets whether anything is recorded. When it is false, evaluations run as they do without Audit, and nothing is built or written. Unlike most settings it is read for every evaluation, so you may switch recording off and on while the application runs. The default is true.
ExcludedMembers
Type: System.Collections.Generic.IList<System.String>
Gets or sets the members that are never recorded, in either RecordValues mode, each by its path from the evaluated object: "Customer.TaxId", "Lines.Price" (the price of every line) or "Customer" (everything of it). Use it for data that a record must not keep. A replay of the evaluation reads an excluded member as unset, so it may take another path than the production evaluation did. An argument of an action that reads an excluded member is recorded as { "excluded": true }. The return value of a method is recorded whatever it was computed from. The default is an empty list.
JournalCapMegabytes
Type: System.Int32
Gets or sets how large the journal may grow, in megabytes. Past it WhenFull applies, and the host is told through OnProblem (JournalFull). It happens only while the database is out of reach for long. It must not be smaller than JournalSegmentMegabytes. The default is 1024.
JournalFlush
Type: CodeEffects.Rule.Audit.AuditJournalFlush
Gets or sets how far each journal write goes before the evaluation returns: to the operating system, or through to the disk. The default is AuditJournalFlush.ToOperatingSystem.
JournalFolder
Type: System.String
Gets or sets the folder of the journal. It is used only when Mode is Asynchronous and Resilience is Journal, and then it must name a folder, otherwise the constructor of the recorder throws a RuleException with control number CE20001. The default is a folder named codeeffects-audit under the temporary folder of the machine (Path.Combine(Path.GetTempPath(), "codeeffects-audit")). Use a folder that survives a restart in production.
JournalSegmentMegabytes
Type: System.Int32
Gets or sets the size, in megabytes, at which the journal starts a new file. A file is deleted once every record in it is in the database. It must be at least 1. The default is 64.
MaxCollectionItems
Type: System.Int32
Gets or sets, with AuditValues.AllFields, how many items of each collection are recorded. The real size of the collection is recorded too, so the record shows the cut. The items that the engine read are recorded whatever this says. The default is 100.
MaxRetryDelaySeconds
Type: System.Int32
Gets or sets the longest wait between tries after the database refused a batch, in seconds. It must be at least 1 and not shorter than RetryDelayMilliseconds. The default is 60.
Mode
Type: CodeEffects.Rule.Audit.AuditMode
Gets or sets whether an evaluation waits for its record to be in the database. With Asynchronous, the record is handed to a background thread and the evaluation returns at once; Resilience decides how much of what is held survives the process. With Synchronous, the record is written on the evaluating thread before the evaluation returns. The default is AuditMode.Asynchronous.
OnProblem
Type: System.Action<CodeEffects.Rule.Audit.AuditProblem>
Gets or sets the delegate through which the recorder tells your application that something went wrong. The recorder never throws into an evaluation, nor from its background work, with the exception of the AuditException that ThrowOnStoreFailure asks for, so this is the only way it reports. The delegate may be called on any thread, and an exception that it throws is ignored. The default is null: nothing is told.
QueueCapacity
Type: System.Int32
Gets or sets how many records the in-memory queue holds, with Volatile and Drain, before WhenFull applies. It must be at least 1. The default is 100000.
RecordValues
Type: CodeEffects.Rule.Audit.AuditValues
Gets or sets which values of the evaluated object a record holds: only those that the engine read, or also every field that the source object declares. What the setters of a rule set is recorded either way. The default is AuditValues.Read.
Resilience
Type: CodeEffects.Rule.Audit.AuditResilience
Gets or sets, in Asynchronous mode, how much of what the recorder holds survives the process going away. It is ignored in Synchronous mode. The default is AuditResilience.Journal.
RetryDelayMilliseconds
Type: System.Int32
Gets or sets how long the background thread waits, in milliseconds, before it tries a batch again that the database refused. The wait doubles on each failure, up to MaxRetryDelaySeconds. It must be at least 1. The default is 1000.
ThrowOnStoreFailure
Type: System.Boolean
Gets or sets, in Synchronous mode, whether an evaluation whose record could not be written fails with an AuditException instead of returning its result. Use it for a decision that must not be acted on unless it is recorded. With false, the failure is reported to OnProblem as StoreFailed and the evaluation returns. A rule that throws always throws its own exception. The property is ignored in Asynchronous mode, where the evaluation has returned long before its record is written. The default is false.
WhenFull
Type: CodeEffects.Rule.Audit.AuditWhenFull
Gets or sets what an evaluation does when the queue or the journal is full. The default is AuditWhenFull.Drop.
Example
using System.Collections.Generic;
using CodeEffects.Rule.Audit;
var settings = new AuditSettings
{
JournalFolder = "/var/lib/myapp/audit",
JournalFlush = AuditJournalFlush.ToDisk,
WhenFull = AuditWhenFull.BlockWithTimeout,
BlockTimeoutMilliseconds = 50,
ExcludedMembers = new List<string> { "Customer.TaxId" },
AnalyticsFields = new List<string> { "Segment", "Customer.Region" },
OnProblem = problem => logger.LogWarning(problem.Kind + ": " + problem.Message)
};
var audit = new AuditRecorder(dbProvider, settings);