There is a webforms application with classes that contain lot of methods. I want to keep logs of the methods that are being called in a flexible and easy way.
I want to know which method has finally been called and some other additional info like:
input values and
result values
Crash exceptions (if there is a crash)
Currently, I am using log4net for filesystem logging like:
using log4net;
private static readonly ILog Log1 = LogManager.GetLogger("Log1");
public int DoSomething(int itemId = 0)
{
Log1.DebugFormat("[DoSomething] - Doing Something on item {0} Started", itemId );
try
{
//something..
}
catch (Exception ex)
{
Log1.Debug("[DoSomething] - Something Failed", ex);
}
Log1.DebugFormat("[DoSomething] - Doing Something on item {0} Finished", itemId );
return 0;
}
How is it possible to achieve this without writing every time these pieces of code in every method? Is there a better and automatic way?
What about the performance cost in every case?
An alternative approach would be great!
Below code should give you a starting point. It's a sample which uses console instead of log4net, but I think it's trivial to extend it to use whatever you need.
First install PostSharp nuget package. Then define new aspect:
[Serializable]
public sealed class TraceAttribute : OnMethodBoundaryAspect
{
private readonly string _argumentsFormat;
[NonSerialized]
private string _methodName;
public TraceAttribute() {
}
public TraceAttribute(string argumentsFormat) {
_argumentsFormat = argumentsFormat;
}
public override void RuntimeInitialize(MethodBase method) {
_methodName = method.Name;
}
public override void OnEntry(MethodExecutionArgs args) {
string msg = $"[{_methodName}]: entered";
if (!String.IsNullOrWhiteSpace(_argumentsFormat)) {
msg += String.Format(". Arguments:" + _argumentsFormat, args.Arguments.ToArray());
}
Console.WriteLine(msg);
}
// Invoked at runtime after the target method is invoked (in a finally block).
public override void OnExit(MethodExecutionArgs args) {
string msg = $"[{_methodName}]: exited";
if (!String.IsNullOrWhiteSpace(_argumentsFormat)) {
msg += String.Format(". Arguments: " + _argumentsFormat, args.Arguments.ToArray());
}
Console.WriteLine(msg);
}
public override void OnException(MethodExecutionArgs args) {
string msg = $"[{_methodName}]: exception";
if (!String.IsNullOrWhiteSpace(_argumentsFormat))
{
msg += String.Format(". Arguments: " + _argumentsFormat, args.Arguments.ToArray());
}
msg += ". Details: " + args.Exception.ToString();
Console.WriteLine(msg);
}
}
What we basically do here is inheriting MethodBoundaryAspect and define what code should be executed when target method is entered, exited, and when exception is thrown. Use it like this:
public class Program {
static void Main(string[] args) {
TestStuff(1);
TestStuff(2);
TestStuff(3);
Console.ReadKey();
}
[Trace("itemId: {0}")]
static void TestStuff(int itemId) {
Console.WriteLine("Inside TestStuff: " + itemId);
if (itemId == 3)
throw new Exception("Test exception");
}
}
You can also apply that attribute to whole classes. In this case - all methods inside that class will be traced.
Related
Is it possible to pass the generic type from one class to other class generic property.
For example:
Assembly Logger
namespace Logger
{
public class GenericLoger<T>
{
T _genericLog;
LogManager _logManager;
public GenericLoger(string logName)
{
_logManager = new LogManager(logName);
//Assigning the generic type to Log.GenerciLog, this is how I am
expecting or by some other possible way?.
Log.GenerciLog = _genericLog;
}
public static Write(string description)
{
_logManager.write(description);
}
}
public static class Log
{
LogManager _logManager;
static Log()
{
_logManager = new LogManager();
}
public static Write(string description)
{
_logManager.write(description);
}
//The generic type supplied in GenericLoger need to pass here,
//like this or by some other possible way?
public static T GenerciLog { get; internal set; }
//T is unrecognized here as type is available in GenericLoger
//I want to pass here from GenericLoger
}
}
Assembly Main Caller of Logger
using Logger;
namespace DataProcessor
{
internal class SpecialLogger
{
private static Lazy<GenericLog<SpecialLogger>> _passed;
public static GenericLog<SpecialLogger> Passed
{
get
{
if (_passed == null)
{
_passed = new Lazy<GenericLog<SpecialLogger>>(() => new GenericLog<SpecialLogger>("Passed"), true);
}
return _passed.Value;
}
}
private static Lazy<GenericLog<SpecialLogger>> _failed;
public static GenericLog<SpecialLogger> Failed
{
get
{
if (_failed == null)
{
_failed = new Lazy<GenericLog<SpecialLogger>>(() => new GenericLog<SpecialLogger>("Failed"), true);
}
return _failed.Value;
}
}
}
internal class Processor
{
public void ProcessRate()
{
var trans = dataManager.GetData();
//Will write the log in "Log.txt" file
Log.write(trans.Count + " transaction found");
foreach (var item in trans)
{
try
{
//transaction process code here
//This will write the text in "Passed.txt" file. 'Passed' property I want to access like this
Log.GenerciLog.Passed.Write(item);
}
catch (Exception ex)
{
//This will write the text in "Failed.txt" file. 'Failed' property I want to access like this
Log.GenerciLog.Failed.Write(item);
}
}
}
}
}
NOTE: In .NET you don't have a way for automatic type inference for use case like yours, also there is no automatic type substitution.
Not sure if this is what you are looking for
Your method definition should look like this
public static T GenerciLog<T> { get; internal set; }
and this is how to call it
try
{
//transaction process code here
//This will write the text in "Passed.txt" file. 'Passed' method I want to access like this
Log.GenerciLog<SpecialLogger>.Passed.Write(item);
}
catch (Exception ex)
{
//This will write the text in "Failed.txt" file. 'Failed' method I want to access like this
Log.GenerciLog<SpecialLogger>.Failed.Write(item);
}
This is a very simple log class. There is a lot more you could do with this sort of thing. Its all provided by log4net which I'd recommend using rather than trying to write your own logger. But the below is a start of how I'd implement a simple logger. It allows you to log to several different things at once. I appreciate the below doesn't answer exactly what you want but its an indication of how to start and you can adapt it to suit your needs.
public static class Logger
{
private static List<ILogger> _loggers = new List<ILogger>();
public static void Log(string message)
{
foreach (var logger in _loggers)
logger.Write(message);
}
public static void AddLogger(ILogger logger)
{
_loggers.Add(logger);
}
}
public interface ILogger
{
void Write(string message);
}
public class SpecialLogger : ILogger
{
public void Write(string message)
{
//special log code here eg
Console.WriteLine(message);
}
}
then somewhere do this
Logger.AddLogger(new SpecialLogger());
Logger.Log("A log message");
I have application for which I need to add additional hidden logging.
I have put prototype in way.
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Start");
new DummyTest().Report();
Console.WriteLine("End");
Console.ReadKey();
}
}
public class DummyTest
{
public void Report()
{
var reporter = new Reporter();
Console.WriteLine("Reporting");
for (var i =0; i < 155; i++)
{
reporter.Process(i);
}
Console.WriteLine("Reporting end");
}
}
public class Reporter
{
// attach behavior here
public void Process(int requestId)
{
Console.WriteLine("Processing request: {0}" , requestId);
System.Threading.Thread.Sleep(100);
}
}
Now I have new project logger.dll that contains
using System;
namespace logger
{
public class Log
{
public Log()
{
Console.WriteLine("Line executed");
}
}
}
Now I would like to execute this method every time Main gets executed. This however cannot be referenced in any other way except only by referencing the dll.
=Update=
I do not mind to have reference to that dll. But in main code I cannot have any reference to Log. I thought about using reflection in order to make this work. The problem I am trying to solve first is how to attach that to the execution.
Why I cannot call logger from main?
This is supposed to be reporting on usage of the class, monitoring usage, in order to report on performance on bottle necks.
You could do something like this:
void Main()
{
System.Console.SetOut(new CustomTextWriter());
Console.WriteLine("test");
}
public class CustomTextWriter : TextWriter
{
private TextWriter _consoleOut = null;
private Log _logger = null;
public CustomTextWriter()
{
_consoleOut = System.Console.Out;
_logger = new Log();
}
public override void Write(char[] buffer, int index, int count)
{
this.Write(new String(buffer, index, count));
}
public override void Write(string value)
{
_consoleOut.Write(value);
_logger.Write(value);
}
public override void WriteLine(string value)
{
_consoleOut.WriteLine(value);
_logger.WriteLine(value);
}
public override Encoding Encoding
{
get { return System.Text.Encoding.Default; }
}
}
Wasn't sure if you wanted to do logging without actually calling Console.WriteLine() (if yes you'll need to look at Interception) but if that's ok then this should get you through.
Hope this helps.
You could do that with reflection like this:
// load the assembly
Assembly LogDll = Assembly.LoadFile(#"Log.dll");
// get the type of the Log class
Type LogType = LogDll.GetType("logger.Log");
// get instance of the Log class
object LogInstance = Activator.CreateInstance(LogType);
// invoke class member "Log()"
LogType.InvokeMember("Log",
BindingFlags.InvokeMethod |
BindingFlags.Instance |
BindingFlags.Public,
null,
LogInstance,
null);
Although I'm not sure if the constructor "Log()" already gets called by creating the instance. You should probably move your actual log method out of the constructor. To pass arguments you can use the last parameter of InvokeMember which is an array of the type Object.
I am attempting to create an aspect to manage security on a few properties of a class. However, the security aspect for one member relies on the data in another property of the class. I've read some tutorials on the IntroduceAspect, but I'm not sure it's what I need.
public class ClassWithThingsIWantToSecure
{
[SecurityAspectHere(inherits from LocationInterceptionAspect)]
public int ThingIWantToSecure;
public string ThingINeedToKnowAboutInSecurityAspect;
}
Can someone point me in the right direction for making the runtime value of ThingINeedToKnowAboutInSecurityAspect available in the SecurityAspect?
I have done something a bit like this before, I've knocked up a test on a machine with postsharp installed and just tried it out, here is the code...
class Program
{
static void Main(string[] args)
{
Baldrick baldrick = new Baldrick();
baldrick.ThingINeedToKnowAboutInSecurityAspect = "Bob";
Console.WriteLine("There are {0} beans", baldrick.ThingIWantToSecure);
baldrick.ThingINeedToKnowAboutInSecurityAspect = "Kate";
try
{
//This should fail
Console.WriteLine("There are {0} beans", baldrick.ThingIWantToSecure);
}
catch (Exception ex)
{
//Expect the message from my invalid operation exception to be written out (Use your own exception if you prefer)
Console.WriteLine(ex.Message);
}
Console.ReadLine();
}
}
[Serializable]
public class SecurityAspect : LocationInterceptionAspect
{
public override void OnGetValue(LocationInterceptionArgs args)
{
ISecurityProvider securityProvider = args.Instance as ISecurityProvider;
if (securityProvider != null && securityProvider.ThingINeedToKnowAboutInSecurityAspect != "Bob")
throw new InvalidOperationException("Access denied (or a better message would be nice!)");
base.OnGetValue(args);
}
}
public interface ISecurityProvider
{
string ThingINeedToKnowAboutInSecurityAspect { get; }
}
public class Baldrick : ISecurityProvider
{
public string ThingINeedToKnowAboutInSecurityAspect { get; set; }
[SecurityAspect]
public int ThingIWantToSecure{get { return 3; }}
}
So, the idea here is to interrogate the args.Instance property for the instace of the object that is being decorated.
So, this example is contrived to try to give a simple view of a much larger system I am trying to modify (namely, Orchard CMS). As such, it may not be perfect.
I am trying to create a logging system that is managed through settings. The problem I'm running into is that retrieving the settings causes logging to occur. Here's a simple example that hopefully describes the problem:
static void Main(string[] args)
{
string[] messages = "this is a test. but it's going to be an issue!".Split(' ');
Parallel.ForEach(messages, Log);
Console.ReadLine();
}
public static void Log(string message)
{
Console.WriteLine(GetPrefix() + message);
}
public static string GetPrefix()
{
Log("Getting prefix!");
return "Prefix: ";
}
This is an obvious StackOverflowException. However, how can I resolve it? I can't just disable the logging until I get the response from GetPrefix, because I may miss logs. (In fact, in this simple example, I miss all but the first.)
static void Main(string[] args)
{
string[] messages = "this is a test. but it's going to be an issue!".Split(' ');
Parallel.ForEach(messages, Log);
Console.ReadLine();
}
static bool _disable = false;
public static void Log(string message)
{
if (_disable)
{
return;
}
_disable = true;
Console.WriteLine(GetPrefix() + message);
_disable = false;
}
public static string GetPrefix()
{
Log("Getting prefix!");
return "Prefix: ";
}
(^Bad.)
Note that I do not currently have control over the GetPrefix method, only the Log method.
I'm not sure if there's a way to resolve this; I may need to put the settings elsewhere (such as the config or a separate settings file). However, if anyone has ideas or suggestions, I'd be happy to try anything, as I'd prefer to leave the settings as I have them now (which is in an admin interface).
All you need to do is to disable on the current stack frame. Now you could use reflection to go over the stack frame and see if it's been called but there's a much simpler method. You have a stack frame for each thread. So make the static variable [ThreadStatic]
[ThreadStatic]
static bool _disable = false;
How does this work?
http://msdn.microsoft.com/en-us/library/system.threadstaticattribute.aspx
"Indicates that the value of a static field is unique for each thread."
Edit: that alone might not be enough, however. What you probably want is one static variable per TASK. Now, as tasks would be executed sequentially per thread, in this particular case I don't think it's an issue, unless loggers can potentially fail without disabling... and I'm not sure what happens in that case, but it might require you to at the very least wrap things in a try/finally block:
static void Main() //Main(string[] args)
{
string[] messages = "this is a test. but it's going to be an issue!".Split(' ');
Parallel.ForEach(messages, Log);
Console.ReadLine();
}
[ThreadStatic]
static bool _disable = false;
public static void Log(string message)
{
if (_disable)
{
return;
}
try {
_disable = true;
Console.WriteLine(GetPrefix() + message);
} finally {
_disable = false;
}
}
public static string GetPrefix()
{
Log("Getting prefix!");
return "Prefix: ";
}
Edit II: From http://msdn.microsoft.com/en-us/library/dd460712.aspx it seems that once any of a set of tasks throws an exception outside of the task delegate, you are not guaranteed execution of any remaining tasks. It's best to handle those exceptional cases in your delegate.
How about splitting the log method into:
public static void LogWithPrefix(string message)
{
var prefix = GetPrefix();
Log(prefix + message);
}
public static void Log(string message)
{
Console.WriteLine(message);
}
Here is my code:
static class MessageHandler<T> where T : Message
{
public delegate void MessageDelegate(T m);
private static MessageDelegate messageHandlers;
public static void Publish(T message)
{
messageHandlers(message);
}
public static void Subscribe(MessageDelegate messageHandler)
{
messageHandlers += messageHandler;
}
}
Message is just an empty class that other classes can inherit from. Most Message derivations are simple objects with relevant properties (this is for a game so there might be a PlayerDamagedMessage with the damage and assailant as the properties.)
Basically, in the Player class when they are attacked they would publish a PlayerDamagedMessage and then other classes that want to know about that can subscribe and then receive the relevant details when it occurs.
The reason why this works with more than one message is because the way generic classes work in C#. By this I mean that there will be a copy of the delegate for each different generic type used under the covers.
I actually figured this out by accident while playing around and am excited because it really simplified my code and looks almost like a design pattern at this point.
I'm posting here to ask about the potential downsides for using this kind of approach. Is there a limit to the amount of generic delegates under the covers? How well would something like this scale?
Also, is there any way to have some sort of generic type-inference so that the statements don't have to be this long?
MessageHandler<MessagePlayerDamaged>.Publish(new MessagePlayerDamaged(this, this));
I've actually used a very similar pattern with much success. One further step I took was encapsulating the actual message handlers within a MessageHandlerRegistry to allow for cleaner syntax. Here is your example modified:
Message.cs
public class Message
{
}
MessageHandler.cs
public class MessageHandler<T> where T : Message
{
private Action<T> messageHandlers;
public void Publish(T message)
{
messageHandlers(message);
}
public void Subscribe(Action<T> messageHandler)
{
messageHandlers = (Action<T>) Delegate.Combine(messageHandlers, messageHandler);
}
}
MessageHandlerRegistry.cs
public static class MessageHandlerRegistry
{
private static readonly IDictionary<Type, object> _handlers = new Dictionary<Type, object>();
public static void Publish<T>(T m) where T : Message
{
if (_handlers.ContainsKey(typeof (T)))
{
((MessageHandler<T>) _handlers[typeof (T)]).Publish(m);
}
}
public static void Subscribe<T>(Action<T> messageHandler) where T : Message
{
if (!_handlers.ContainsKey(typeof (T)))
{
_handlers[typeof (T)] = new MessageHandler<T>();
}
((MessageHandler<T>) _handlers[typeof (T)]).Subscribe(messageHandler);
}
}
Program.cs
class Program
{
static void Main(string[] args)
{
MessageHandlerRegistry.Subscribe((Message m) => Console.WriteLine("Message received."));
MessageHandlerRegistry.Publish(new Message());
}
}
The only downside I have seen to this is being overly-loosly coupled, and in some situations where it would make more sense to use a traditional event based approach, sometimes it is easier to just publish a message.
The main differences to C# events:
Your messages are identified by their Arguments-Class which makes it impossible to have two different events serving alike purposes (think of MouseUp, MouseDown, MouseMoved, etc.)
Your messages are coupled to a static context, not to objects, which makes it hard to register for events from say player1 and not player2
And your messages can be invoked from anywhere at all, whereas event invocations are always private to the class/object owning that event
There is a solution I use in my projects.
public class MessageDispatcher {
private readonly Dictionary<Type, MulticastDelegate> registeredHandlers = new Dictionary<Type, MulticastDelegate>();
private delegate void MessageActionDelegate<in T>(T message);
public void Register<T>(Action<T> action) {
Type messageType = typeof (T);
if (registeredHandlers.ContainsKey(messageType)) {
var messageDelegate = (MessageActionDelegate<T>) registeredHandlers[messageType];
registeredHandlers[messageType] = messageDelegate + new MessageActionDelegate<T>(action);
}
else {
registeredHandlers.Add(messageType, new MessageActionDelegate<T>(action));
}
}
public void Deregister<T>() {
Type messageType = typeof (T);
if (registeredHandlers.ContainsKey(messageType)) {
registeredHandlers.Remove(messageType);
}
}
public void DeregisterAll() {
registeredHandlers.Clear();
}
public void Send<T>(T message) {
Type messageType = typeof (T);
if (!registeredHandlers.ContainsKey(messageType)) return;
((MessageActionDelegate<T>) registeredHandlers[messageType])(message);
}
}
And test example:
private static void Main(string[] args) {
var messenger = new MessageDispatcher();
messenger.Register<Message>(m => Console.WriteLine(m.Text));
messenger.Send(new Message() { Text = "Good morning, sir."});
messenger.Register<Message>(m => Console.WriteLine(m.Text + " It's nice weather today."));
messenger.Register<Notification>(n => Console.WriteLine(n.Text));
messenger.Send(new Message() { Text = "How do you feel? "});
messenger.Send(new Notification() { Text = "Cup of tea, sir?" });
messenger.Deregister<Message>();
messenger.Send(new Message() { Text = "Good bye" });
Console.ReadLine();
}
public class Message {
public string Text { get; set; }
}
public class Notification {
public string Text { get; set; }
}
You can make MessageDispatcher a singleton.
And if your application is multi-threaded then you need to think about thread-safety.
I found a way to do it using generics, I added a private Registry class which stores the static delegate:
class Message
{
}
class MessageHandler
{
public static void Publish<T>(T message) where T : Message
{
Registry<T>.action(message);
}
public static void Subscribe<T>(Action<T> h) where T : Message
{
Registry<T>.action += h;
}
private class Registry<T> where T : Message
{
public static Action<T> action;
}
}
This way you don't have to add the type arguments:
class IntMessage : Message
{
public int Value = 100;
}
class StringMessage : Message
{
public string Value = "a string";
}
static void Main(string[] args)
{
MessageHandler.Subscribe((StringMessage m) => Console.WriteLine("String : " + m.Value));
MessageHandler.Subscribe((StringMessage m) => Console.WriteLine("2nd String : " + m.Value));
MessageHandler.Subscribe((IntMessage m) => Console.WriteLine("Int : " + m.Value));
MessageHandler.Subscribe((IntMessage m) => Console.WriteLine("2nd Int : " + m.Value));
MessageHandler.Publish(new IntMessage());
MessageHandler.Publish(new StringMessage());
}