Bodoconsult.App
1.0.2
dotnet add package Bodoconsult.App --version 1.0.2
NuGet\Install-Package Bodoconsult.App -Version 1.0.2
<PackageReference Include="Bodoconsult.App" Version="1.0.2" />
<PackageVersion Include="Bodoconsult.App" Version="1.0.2" />
<PackageReference Include="Bodoconsult.App" />
paket add Bodoconsult.App --version 1.0.2
#r "nuget: Bodoconsult.App, 1.0.2"
#addin nuget:?package=Bodoconsult.App&version=1.0.2
#tool nuget:?package=Bodoconsult.App&version=1.0.2
What does the library
Bodoconsult.App is a library with basic functionality for multilayered monolithic applications like database based client server apps. It delivers the following main functionality:
- App start infrastructure for console apps
- Single-threaded high-performance logging for single-threaded or multi-threaded environments (IAppLoggerProxy / AppLoggerProxy )
- Basic watchdog implementation IWatchDog / WatchDog as replacement for timers for non-time critical tasks
- Application perfromance measurement (APM) tools for performnce logging
- Business transactions to simplify transportation layer implementations for technologies like GRPC, WebAPI, etc...
- ProducerConsumerQueue/<T/> implementing the producer-consumer-pattern for one or many producers but only one consumer.
How to use the library
The source code contains NUnit test classes the following source code is extracted from. The samples below show the most helpful use cases for the library.
App start infrastructure for console and Winforms apps
See page app start infrastructure for details.
IAppLoggerProxy / AppLoggerProxy
AppLoggerProxy is a high performance logger infrastructure for multithreaded and or multitasked apps with low resulting garbage pressure.
Log entries are stored to a intermediate queue and then processed on a single thread during app runtime using a IWatchdog implementation. This avoids file access errors resulting from different threads trying to access the destinantion log at the same time.
To reduce garbage pressure log entries are reused. Therefore you should use a singelton instance of a LogDataFactory for the whole app. You can store this singleton instance i.e. in a singleton IAppGlobals instance for your app.
Each instance of IAppLoggerProxy is representing a separate logging target.
Log entries are written to the logging target in a single threaded way to avoid trouble with accessing log file from multiple threads.
Supported logging targets
IAppLoggerProxy supports the following logging targets by default:
Log4Net
Console
Debug window (only in debug mode)
Eventlog
EventSource (to use log entries in the app itself i.e. for showing it in a GUI)
This logging targets can be activated seperately or in a combined manor. Combine Log4Net and EventSource in appsettings.json if you want to log to a file and to the GUI at the same time for example.
Configuring central app logging in appsettings.json
Central app logging with IAppLoggerProxy can be configured in the appsettings.json file. See a typical example here:
{
"ConnectionStrings": {
"DefaultConnection": "Data Source=(LocalDB)\\MSSQLLocalDb;Initial Catalog=XYDatabase;Integrated Security=true;MultipleActiveResultSets=True;App=ConsoleApp1"
},
"Logging": {
"MinimumLogLevel": "Debug",
"LogLevel": {
"Default": "Information",
"System": "Information",
"Microsoft": "Information",
"Microsoft.EntityFrameworkCore": "Warning"
},
"Log4Net": {
"LogLevel": {
"Default": "Debug"
}
},
//"Console": {
// "IncludeScopes": true,
// "DisableColors": false
//},
//, "EventLog": {
// "SourceName": "MyApp"
// "LogName": "MyLogName"
// "MachineName": "MyMachineName"
//},
"Debug": {
"LogLevel": {
"Default": "Debug"
}
},
"EventSource": {
"LogLevel": {
"Default": "Error"
}
}
}
}
Configuring other loggers
Creating multiple logfiles
If you want to setup multiple logfiles for your app for example per device the app handles you can create multiple instances of IAppLoggerProxy. See class MonitorLoggerFactory. It takes a full path for the logfile to log in and the other settings from log4net.config.
Using log4net as logger
If you want to use log4net for logging you can use the Log4NetLoggerFactory.
var logger = new AppLoggerProxy(new Log4NetLoggerFactory.(), Globals.LogDataFactory);
_log.LogWarning("Hallo");
You can configure the logger with a log4net.config file in the project main folder. See log4net documentation for details.
Fake logger for unit tests
For unit tests you can use a fake implementation of a logger. It logs to the output window only.
var logger = new AppLoggerProxy(new FakeLoggerFactory(), Globals.LogDataFactory);
_log.LogWarning("Hallo");
IWatchDog / WatchDog
WatchDog is something similar to a timer. Timers do have the potential issue with multiple running tasks if tasks may run longer than the timer interval. So if your timer task will potentially run longer then the timer interval you should think about using IWatchDog implementations.
The runner method is fired and processed until done. Then the watchdog waits for the delay interval until it restarts the runner method.
For time critical tasks WatchDog is not a good solution. If you have to ensure that your task is running i.e. every minute exactly, you better should use a Timer.
The runner method is running always on the same separated background thread.
WatchDogRunnerDelegate runner = Runner;
var w = new WatchDog(runner, delayTime);
w.StartWatchDog();
...
w.StopWatchDog();
/// <summary>
/// Runner method for the watchdog
/// </summary>
private void Runner()
{
// Do your tasks here
}
BufferPool<T>
BufferPool<T> is used to handle and reuse multiple instances of potentially small objects of a type to reduce garbage pressure.
Heavily used small objects of a type lead to a relatively high demand for object creation and disposing. In such cases it might be a good idea to reuse the already created instances.
Classes used with BufferPool<T> should implement IResetable interface.
// Arrange
var myPool = new BufferPool<byte[]>(() => new byte[65535]);
myPool.Allocate(1000);
var buffer = myPool.Dequeue();
// Act
myPool.Enqueue(buffer);
// Assert
Assert.That(myPool.LengthOfQueue, Is.EqualTo(NumberOfItems));
Performance logging
See page Performance logging for details.
Business transactions
See page Business transactions for details.
ProducerConsumerQueue/<T/>
ProducerConsumerQueue/<T/> implements the producer-consumer-pattern for one or many producers but only one consumer. This may be helpful if the consumer is maybe a database or a file which should not be accessed by multiple threads at the same time.
const string s1 = "Blubb";
const string s2 = "Blabb";
const string s3 = "Blobb";
var pc = new ProducerConsumerQueue<string>();
pc.ConsumerTaskDelegate = ConsumerTaskDelegate;
pc.StartConsumer();
// Act
pc.Enqueue(s1);
pc.Enqueue(s2);
pc.Enqueue(s3);
// Assert
Wait.Until(() => _counter > 0);
Assert.That(_counter, Is.EqualTo(3));
Assert.That(_received.Count, Is.EqualTo(3));
Assert.That(_received.Contains(s1), Is.True);
Assert.That(_received.Contains(s2), Is.True);
Assert.That(_received.Contains(s3), Is.True);
...
private void ConsumerTaskDelegate(string value)
{
_counter++;
_received.Add(value);
_wasFired = true;
}
IExceptionReplyBuilder / ExceptionReplyBuilder
ExceptionReplyBuilder delivers a central exception management to be used standalone or in conjunction with business transactions.
ToDo: add more information
About us
Bodoconsult http://www.bodoconsult.de is a Munich based software company from Germany.
Robert Leisner is senior software developer at Bodoconsult. See his profile on http://www.bodoconsult.de/Curriculum_vitae_Robert_Leisner.pdf.
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
- log4net (>= 3.0.3)
- Microsoft.Diagnostics.NETCore.Client (>= 0.2.553101)
- Microsoft.Diagnostics.Tracing.TraceEvent (>= 3.1.18)
- Microsoft.Extensions.Configuration.Json (>= 9.0.0)
- Microsoft.Extensions.DependencyInjection (>= 9.0.0)
- Microsoft.Extensions.Logging (>= 9.0.0)
- Microsoft.Extensions.Logging.Console (>= 9.0.0)
- Microsoft.Extensions.Logging.Debug (>= 9.0.0)
- Microsoft.Extensions.Logging.EventSource (>= 9.0.0)
- Microsoft.Win32.Primitives (>= 4.3.0)
- System.Text.Json (>= 9.0.0)
NuGet packages (3)
Showing the top 3 NuGet packages that depend on Bodoconsult.App:
Package | Downloads |
---|---|
Bodoconsult.App.WinForms
Added IAppBuilder and base classes for it to support background services too with app infrastructure |
|
Bodoconsult.App.BackgroundService
Package providing basic functionality like logging, application performance measuring etc. for layered apps in a background service scenario |
|
Bodoconsult.App.GrpcBackgroundService
Package providing basic functionality like logging, application performance measuring etc. for layered apps in a background service scenario hosting a GRPC service |
GitHub repositories
This package is not used by any popular GitHub repositories.
Added IAppBuilder and base classes for it to support background services too with app infrastructure