Enterprise Library 5.0: Writing log to file without XML configuration - c#

There is some code for logging to file. I dont using app.config
class Program
{
static void Main(string[] args)
{
MyLogger.Write("This is message error", "My Category");
Console.ReadKey();
}
}
public static class MyLogger
{
static readonly LogWriterImpl _writer;
static MyLogger()
{
TextFormatter formatter = new TextFormatter
("Timestamp: {timestamp}{newline}" +
"Message: {message}{newline}" +
"Category: {category}{newline}");
var logFileListener = new Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FlatFileTraceListener
(
"c:\\messages.log", "----------", "----------", formatter
);
LogSource mainLogSource = new LogSource("MainLogSource", SourceLevels.All);
mainLogSource.Listeners.Add(logFileListener);
LogSource nonExistantLogSource = new LogSource("Empty");
IDictionary<string, LogSource> traceSources = new Dictionary<string, LogSource>();
traceSources.Add("Error", mainLogSource);
traceSources.Add("Debug", mainLogSource);
_writer = new LogWriterImpl
(
new Microsoft.Practices.EnterpriseLibrary.Logging.Filters.ILogFilter[0],
traceSources,
nonExistantLogSource,
nonExistantLogSource,
mainLogSource,
"Error",
false,
true
);
}
public static void Write(string message)
{
Write(message, "Error");
}
public static void Write(string message, string category)
{
LogEntry entry = new LogEntry();
entry.Categories.Add(category);
entry.Message = message;
_writer.Write(entry);
}
}
This program work without errors but it don't create log file c:\messages.log and don't write log entity. Where is the error? I don't want using application config file in my project

There could be a couple of reasons (at least!) why you are not seeing any logging:
The categories that are configured for logging are "Error" and "Debug" but when you call MyLogger.Write you are passing a category of "My Category"
There could be a permission problem. Writing to the root of the drive is frequently restricted
As an aside, you should probably store the reference to LogWriterImpl as the base class LogWriter.
As another aside, instead of using the logging classes directly it is preferable to use the Fluent Configuration API which was released as part of version 5.0. It makes this type of configuration much simpler. As an example:
var builder = new ConfigurationSourceBuilder();
builder.ConfigureLogging()
.WithOptions
.DoNotRevertImpersonation()
.LogToCategoryNamed("My Category")
.SendTo.FlatFile("MyMessages")
.FormatWith(new FormatterBuilder()
.TextFormatterNamed("Text Formatter")
.UsingTemplate("Timestamp: {timestamp}...{newline})}"))
.ToFile("c:\\messages.log");
var configSource = new DictionaryConfigurationSource();
builder.UpdateConfigurationWithReplace(configSource);
EnterpriseLibraryContainer.Current
= EnterpriseLibraryContainer.CreateDefaultContainer(configSource);
It's also more maintainable and supportable. E.g. there is less chance that there won't be breaking implementation changes like when LogWriter was made abstract as part of version 5.

Related

Nlog logger object gets disposed when it shouldn't

We're using NLog for our application. I have set up the logger in the code using mostly the documentation. Yet the logger object gets disposed of while the app is about to write to it causing an error. I use the logger in .NET CORE 3.1 in the Middlewares that handles exceptions globally and authentication. The funniest part is that the error itself is logged to the file by NLog. Error from the logs:
System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'LoggerFactory'.
at Microsoft.Extensions.Logging.LoggerFactory.CreateLogger(String categoryName)
at Microsoft.Extensions.Logging.Logger`1..ctor(ILoggerFactory factory)
at Microsoft.Extensions.Logging.LoggerFactoryExtensions.CreateLogger[T](ILoggerFactory factory)
Configuration in the code:
public static class NLogConfig
{
public static void CreateLogger(IConfiguration configuration)
{
var logName = configuration.GetSection("LoggerConfig").GetSection("LogName").Get<string>();
var logPath = configuration.GetSection("LoggerConfig").GetSection("Directory").Get<string>();
var infoLogLayout = configuration.GetSection("LoggerConfig").GetSection("InfoLayout").Get<string>();
var errorLogLayout = configuration.GetSection("LoggerConfig").GetSection("ErrorLayout").Get<string>();
var config = new NLog.Config.LoggingConfiguration();
var infoLog = new NLog.Targets.FileTarget("FileLog") { FileName = logPath + logName, Layout = infoLogLayout };
var errorLog = new NLog.Targets.FileTarget("FileLog") { FileName = logPath + logName, Layout = errorLogLayout };
config.AddRule(LogLevel.Trace, LogLevel.Info, infoLog);
config.AddRule(LogLevel.Warn, LogLevel.Fatal, errorLog);
NLog.LogManager.Configuration = config;
}
}
JSON configuration file:
"LoggerConfig": {
"LogName": "MY_API_${shortdate}.log",
"Directory": "C:\\Logs\\MY_API\\",
"InfoLayout": "${longdate} | INFO | ${logger} | ${message}",
"ErrorLayout": "------------------\n${longdate} | ERROR | ${logger} | ${message:withexception=true} \n------------------"
}
In the classes that use the log I do this as it is in documentation:
private static readonly NLog.Logger _logger = NLog.LogManager.GetCurrentClassLogger();
The "disposed" error happens randomly and not frequently, but often enough to be a slight concern. How can I avoid this problem? I've read that NLog should be thread-safe so calls to the API shouldn't cause such a problem. Especially when it was only one person using the API at the time

How does Akka.NET persistence handle replaying messages containing IActorRef?

If I send an Akka.NET actor a message which is an object containing an IActorRef, and then persist that message, the JSON written to the journal table looks like this:
{"$id":"1","$type":"LearningAkka.Program+BindReference, LearningAkka","Reference":{"$id":"2","$type":"Akka.Actor.ActorRefBase+Surrogate, Akka","Path":"akka://LearningAkka/user/$b#1222898859"}}
If I'm understanding this right, this is just a reference to an actor instance; the "Props" required to create it are not stored in this message.
Weirdly, I am seeing an object there after restarting the app. However, as expected, it is not as constructed before the restart. Where did this actor come from? Has Akka Persistence found an actor which is "similar enough" and used it instead?
The following C# test application creates an object and sends a message binding it to one of three others. After disposing of the actor system, that object is recreated from persistence (SQL Server) and the reference is checked.
My expected behaviour is any of the following (I'm not sure what's most appropriate):
The actor can't be created because one of its messages contains an unresolvable reference.
The actor reference is null because it cannot be resolved.
The actor reference points to dead letters or similar.
Console output:
[WARNING][27/05/2017 21:02:27][Thread 0001][ActorSystem(LearningAkka)] NewtonSoftJsonSerializer has been detected as a default serializer. It will be obsoleted in Akka.NET starting from version 1.5 in the favor of Hyperion (for more info visit: http://getakka.net/docs/Serialization#how-to-setup-hyperion-as-default-serializer ). If you want to suppress this message set HOCON `akka.suppress-json-serializer-warning` config flag to on.
From the first run B
[WARNING][27/05/2017 21:02:28][Thread 0001][ActorSystem(LearningAkka)] NewtonSoftJsonSerializer has been detected as a default serializer. It will be obsoleted in Akka.NET starting from version 1.5 in the favor of Hyperion (for more info visit: http://getakka.net/docs/Serialization#how-to-setup-hyperion-as-default-serializer ). If you want to suppress this message set HOCON `akka.suppress-json-serializer-warning` config flag to on.
From the second run B
C#:
using Akka.Actor;
using Akka.Event;
using Akka.Persistence;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LearningAkka
{
class Program
{
static void Main(string[] args)
{
using (var actorSystem = ActorSystem.Create("LearningAkka"))
{
var referenceA = actorSystem.ActorOf(Props.Create(() => new TestReferencedActor("From the first run A")));
var referenceB = actorSystem.ActorOf(Props.Create(() => new TestReferencedActor("From the first run B")));
var referenceC = actorSystem.ActorOf(Props.Create(() => new TestReferencedActor("From the first run C")));
var actor = actorSystem.ActorOf(Props.Create(() => new TestActor()));
actor.Tell(new BindReference { Reference = referenceB });
actor.Tell(new CheckReference());
Console.ReadLine();
}
using (var actorSystem = ActorSystem.Create("LearningAkka"))
{
var referenceA = actorSystem.ActorOf(Props.Create(() => new TestReferencedActor("From the second run A")));
var referenceB = actorSystem.ActorOf(Props.Create(() => new TestReferencedActor("From the second run B")));
var referenceC = actorSystem.ActorOf(Props.Create(() => new TestReferencedActor("From the second run C")));
var actor = actorSystem.ActorOf(Props.Create(() => new TestActor()));
actor.Tell(new CheckReference());
Console.ReadLine();
}
}
public struct BindReference { public IActorRef Reference; }
public struct CheckReference { }
public sealed class TestActor : ReceivePersistentActor
{
public override string PersistenceId => "test hardcoded";
private IActorRef StoredFromMessage;
public TestActor()
{
Command<CheckReference>(m => StoredFromMessage.Tell(m));
Command<BindReference>(m => Persist(m, m2 => StoredFromMessage = m2.Reference));
Recover<BindReference>(m => StoredFromMessage = m.Reference);
}
}
public sealed class TestReferencedActor : ReceiveActor
{
public TestReferencedActor(string ourLabel)
{
Receive<CheckReference>(m => Console.WriteLine(ourLabel));
}
}
}
}
HOCON:
akka {
persistence {
journal {
plugin = "akka.persistence.journal.sql-server"
sql-server {
class = "Akka.Persistence.SqlServer.Journal.SqlServerJournal, Akka.Persistence.SqlServer"
connection-string = "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=LearningAkka;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"
schema-name = dbo
table-name = Journal
auto-initialize = on
}
}
snapshot-store {
plugin = "akka.persistence.snapshot-store.sql-server"
sql-server {
class = "Akka.Persistence.SqlServer.Snapshot.SqlServerSnapshotStore, Akka.Persistence.SqlServer"
connection-string = "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=LearningAkka;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"
schema-name = dbo
table-name = Snapshot
auto-initialize = on
}
}
}
}
Could someone please comment on the behaviour here? Thank you.
As you can see from serialization data - your IActorRef points to this address akka://LearningAkka/user/$b. Where $b is usually placed for unnamed actors. So it will always be the second unnamed actor you create in the actor system root (as far as I know).
So you are right - the system behavior is undefined here.

How do I execute a script with Roslyn in End User Preview

I'm trying to play around with the end user preview of roslyn and would like to execute a simple script. What I would like to do is something like:
static void Main(string[] args)
{
// Is this even valid?
var myScript = "int x = 5; int y = 6; x + y;";
// What should I do here?
var compiledScript = Something.Compile(myScript);
var result = compiledScript.Execute(myScript);
Console.WriteLine(result);
}
Can someone point to some resources and/or tell me which nuget packages to install to make this happen. I've installed the Microsoft.CodeAnalysis, but can't figure out if it doable with just that, I feel like I'm missing something.
The scripting APIs which would allow you to do this very easily were (temporarily) removed in the latest preview. You can still compile a script, emit and load the assembly and invoke its entry point by doing something along the lines of
public static class Program
{
public static void Main(string[] args)
{
var assemblyPath = Path.GetDirectoryName(typeof(object).Assembly.Location);
var defaultReferences = new[] { "mscorlib.dll", "System.dll", "System.Core.dll" };
var script = #"using System;
public static class Program
{
public static void Main(string[] args)
{
Console.WriteLine(""Hello {0}"", args[0]);
}
}";
// Parse the script to a SyntaxTree
var syntaxTree = CSharpSyntaxTree.ParseText(script);
// Compile the SyntaxTree to a CSharpCompilation
var compilation = CSharpCompilation.Create("Script",
new[] { syntaxTree },
defaultReferences.Select(x => new MetadataFileReference(Path.Combine(assemblyPath, x))),
new CSharpCompilationOptions(OutputKind.ConsoleApplication));
using (var outputStream = new MemoryStream())
using (var pdbStream = new MemoryStream())
{
// Emit assembly to streams.
var result = compilation.Emit(outputStream, pdbStream: pdbStream);
if (!result.Success)
{
return;
}
// Load the emitted assembly.
var assembly = Assembly.Load(outputStream.ToArray(), pdbStream.ToArray());
// Invoke the entry point.
assembly.EntryPoint.Invoke(null, new object[] { new[] { "Tomas" } });
}
}
}
It will output Hello Tomas in the console :)
It appears that in the April 2014 release, scripting has been temporarily removed:
What happened to the REPL and hosting scripting APIs?
The team is reviewing the designs of these components that you saw in
previous CTPs, before re-introducing the components again. Currently
the team is working on completing the language semantics of
interactive/script code.

can't write into log file using TraceSource Method in C#

I am using the following code to log the exception, but it's not writing any logs into the file "mylistener.log". What am I missing here?
using System;
using System.Diagnostics;
namespace TraceSourceApp
{
class Program
{
private static TraceSource mySource = new TraceSource("TraceSourceApp");
static void Main(string[] args)
{
TextWriterTraceListener textListener =
new TextWriterTraceListener("myListener.log");
mySource.Listeners.Add(textListener);
int i = 10, j = 0, k;
try
{
k = i / j;
}
catch
{
mySource.TraceEvent(TraceEventType.Error, 12,
"Division by Zero");
}
mySource.Close();
}
}
}
In order for the TraceSource to write data to the file, you need to set the Switch-property of the TraceSource to a SourceSwitch instance. Change your code as follows:
static void Main(string[] args)
{
TextWriterTraceListener textListener = new TextWriterTraceListener("myListener.log");
// New code starts here
var sourceSwitch = new SourceSwitch("SourceSwitch", "Verbose");
mySource.Switch = sourceSwitch;
// New code ends here
mySource.Listeners.Add(textListener);
// ...
In addition to have the TraceWriter flush its content automatically, set Trace.AutoFlush at the beginning of you main method (the sample works without it, but it is always a good idea to make sure that the listeners are flushed in order not to loose log entries):
static void Main(string[] args)
{
Trace.AutoFlush = true;
// ...
As an alternative, you can also flush the listener explicitly by calling its Flush-method at the end:
textListener.Flush();
mySource.Close();
In real world code, I'd suggest to add a try-finally or using block to assert that Flush is called and that the source is closed.

MEF Catalog is Empty

I am working a WPF application that uses MEF. But even when I run the below code(As a test code snippet some where in the code), the catalog is always empty. All the sample codes have done the same thing, those are working fine. but mine is not working. I am missing something important that I can not figure out on my own. So,I want some help on this.
var catalog = new AggregateCatalog();
var x = Assembly.GetExecutingAssembly().Location;
catalog.Catalogs.Add(
new DirectoryCatalog(
Path.GetDirectoryName(
Assembly.GetExecutingAssembly().Location)));
CompositionContainer container = new CompositionContainer(catalog);
This is the actual scenario code. there are 3 projects in the same solution.
W PF Project.
Extension Project.
Contract Project.
Extension project contains the Exports. and the contract project contains the interfaces shared by the W PF project and the Extension project.
[Export("LoginManager", typeof(IEmployeeLoginManager))]
public class LoginManager : IEmployeeLoginManager
{
public EmployeeLoginModel LoginEmployee(String userName, string password)
{
DEmployeeLoginManager employeeLoginManager = new DEmployeeLoginManager();
return employeeLoginManager.LoginEmployee(userName, password);
}
}
this Export is used in the WPF project as belows,
public partial class LoginWindow
{
public EmployeeLoginModel LoggedInEmployee;
[Import("LoginManager",AllowDefault = true)]
private IEmployeeLoginManager LoginManager;
public LoginWindow()
{
InitializeComponent();
}
private void RadWindow_Closed_1(object sender, Telerik.Windows.Controls.WindowClosedEventArgs e)
{
Application.Current.Shutdown();
Environment.Exit(0);
return;
}
private void RadButton_Click_1(object sender, RoutedEventArgs e)
{
string passWord = PasswordText.Password;
LoggedInEmployee.Password = passWord;
var container = MEFLoader.GetMEFContainer();
container.ComposeParts(this);
EmployeeLoginModel employee= LoginManager.LoginEmployee(LoggedInEmployee.UserName, passWord);
if (employee.LoginStatus == true)
{
this.Close();
}
}
PS: This is the MEFLoader Class:
public static class MEFLoader
{
public static CompositionContainer GetMEFContainer()
{
var catalog = new AggregateCatalog(new DirectoryCatalog("."), new AssemblyCatalog(Assembly.GetExecutingAssembly()));
var container = new CompositionContainer(catalog);
return container as CompositionContainer;
}
}
I am new to MEF and I appreciate any improvement point as well in my code.
thanks in advance.
First I thought parts in other projects that are in the same solutions are identified automatically by code snippet shown below.
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(
new DirectoryCatalog(
Path.GetDirectoryName(
Assembly.GetExecutingAssembly().Location)));
CompositionContainer container = new CompositionContainer(catalog);
but it is not like that, we have to manually place the dll in the executing projects bin/debug(since this is running in the debug mode)
or what you have to do is, you have to change the project properties=> build events => post built event command line to
copy $(TargetPath) $(SolutionDir)\[Your running application folder]\bin\Debug
this will automatically copy the necessary dlls to the executing bin.
OR you can change it in the project properties=> build => output path, you can set the output path to the Debug folder of the executing project.

Categories

Resources