I have a class BackgroundTask that I have set up to log events when things happen, such as when the task completes. For example, for the Success case, I call Log.Verbose("{Task} completed successfully", this); My default ToString() includes the progress, but for a completed task we know it's 100% so I would like to ignore it. I know that with numeric types you can pass in a custom format specifier string (like "{IntProperty:p5}", which would render my int as a percentage with 5 decimal places), and I would like to be able to do the same, such as Log.Information("{Task:Name}", this), which would pass in "Name" into my ToString() method.
I've tried adding lots of different methods like adding ToString()'s, (taking in nothing, a string, a string and IFormatProvider), implementing IFormattable, forcing stringification etc and nothing seems to work. I can see that Serilog is correctly parsing my format string: (PropertyBinder.cs, ConstructNamedProperties() line 111)
This calls ConstructProperty() which just ignores the Format property of the token, which explains why it's being ignored, but I was wondering if there was a way that would work that I haven't thought of.
PS
Yes I'm aware I have several options I could do, but I'd rather not do these:
Use a custom destructurer or manually pulling out the properties myself into an anonymous type - This essentially destroys the original object, which is exactly what I don't want (I still want the original value stored as a property). E.g. Log.Information("{Task}", new {Name = this.Name, Id = this.Id});
Manually call ToString() with my own format string - Same as (1), this destroys the original, and means it won't be stored with all it's information. E.g. Log.Information("{Task}", this.ToString("Custom Format"));
Create a property on my object like ToStringFormat before passing it into Serilog - This seems bad practice and just adds extra clutter, not to mention the concurrency issues. E.g. this.Format = "Custom FOrmat"; Log.Information("{Task}", this);
This is due to the split between capturing and formatting in the Serilog pipeline.
In order for format strings like :X to be processed when rendering to a sink, the original object implementing IFormattable needs to be available.
But, because sinks often process events asynchronously, Serilog can't be sure that any given logged object is thread-safe, and so any unknown types are captured at the time/site of logging using ToString().
To get around this, you need to tell Serilog that your Point class is an (essentially immutable) value type with:
.Destructure.AsScalar(typeof(Point))
when the logger is configured. You can then implement IFormattable on Point and use {Point:X} etc. in templates.
Related
Using PostSharp for a C# application, I have the following scenario:
Namespace_A.CustomLoggingMethod
Namespace_B.DoSomethingMethod (in fact several different methods)
DoSomethingMethod makes a call to CustomLoggingMethod, which creates the log entry in the desired format and is working well. As expected, the log entry logs the source as CustomLoggingMethod, and I would prefer to override this to show the original calling method (e.g. DoSomethingMethod), which I can obtain from the stack. Does anyone know how I can achieve this for this one method?
As a follow-up is there a way I can also prevent the entry/exit log entries for my custom logging method only?
You can, but at the cost of some performance.
The follow-up is easy: you annotate CustomLoggingMethod with [Log(AttributeExclude=false)] and it will no longer produce automatic logging of entry/exit.
As for the main question, there are overloads for both LogSource.Get() and the .Write method on LogLevelSource where you can supply your own CallerInfo. The CallerInfo object contains both the type and the method name.
What you could do is create the CallerInfo object in your custom method programatically and pass it to those methods. You can get the method name from [CallerMemberName] but you would need to pass the type as an argument.
Or, as you said, you can obtain the type from the stack. You can do this most easily with CallerInfo.GetDynamic, but in my experience, this is slow. If you start logging thousands of lines per second, you will see a performance drop from walking the stack this way.
Here's how the custom method could look like:
[Log(AttributeExclude = true)]
public static void CustomLogging(string message)
{
CallerInfo callerInfo = CallerInfo.GetDynamic(1);
LogSource.Get(ref callerInfo).Warning.Write(FormattedMessageBuilder.Formatted(message), default, ref callerInfo);
}
Writing custom logging without using a custom method avoids the problem because PostSharp rewrites the custom logging call to include the information on the caller in the IL code.
This is probably a matter of personal preference, but when do you use properties instead of functions in your code
For instance to get an error log I could say
string GetErrorLog()
{
return m_ErrorLog;
}
or I could
string ErrorLog
{
get { return m_ErrorLog; }
}
How do you decide which one to use? I seem to be inconsistent in my usage and I'm looking for a good general rule of thumb. Thanks.
I tend to use properties if the following are true:
The property will return a single, logic value
Little or no logic is involved (typically just return a value, or do a small check/return value)
I tend to use methods if the following are true:
There is going to be significant work involved in returning the value - ie: it'll get fetched from a DB, or something that may take "time"
There is quite a bit of logic involved, either in getting or setting the value
In addition, I'd recommend looking at Microsoft's Design Guidelines for Property Usage. They suggest:
Use a property when the member is a logical data member.
Use a method when:
The operation is a conversion, such as Object.ToString.
The operation is expensive enough that you want to communicate to the user that they should consider caching the result.
Obtaining a property value using the get accessor would have an observable side effect.
Calling the member twice in succession produces different results.
The order of execution is important. Note that a type's properties should be able to be set and retrieved in any order.
The member is static but returns a value that can be changed.
The member returns an array. Properties that return arrays can be very misleading. Usually it is necessary to return a copy of the internal array so that the user cannot change internal state. This, coupled with the fact that a user can easily assume it is an indexed property, leads to inefficient code. In the following code example, each call to the Methods property creates a copy of the array. As a result, 2n+1 copies of the array will be created in the following loop.
Here are Microsoft's guidelines:
Choosing Between Properties and Methods
Consider using a property if the member represents a logical attribute of the type.
Do use a property, rather than a method, if the value of the property is stored in the process memory and the property would just provide access to the value.
Do use a method, rather than a property, in the following situations.
The operation is orders of magnitude slower than a field set would be. If you are even considering providing an asynchronous version of an operation to avoid blocking the thread, it is very likely that the operation is too expensive to be a property. In particular, operations that access the network or the file system (other than once for initialization) should most likely be methods, not properties.
The operation is a conversion, such as the Object.ToString method.
The operation returns a different result each time it is called, even if the parameters do not change. For example, the NewGuid method returns a different value each time it is called.
The operation has a significant and observable side effect. Note that populating an internal cache is not generally considered an observable side effect.
The operation returns a copy of an internal state (this does not include copies of value type objects returned on the stack).
The operation returns an array.
I use properties when its clear the semantic is "Get somevalue from the object". However using a method is a good way to communicate "this may take a bit more than a trivial effort to return".
For example a collection could have a Count property. Its reasonable to assume a collection object knows how many items are currently held without it actually having to loop through them and count them.
On the hand this hypothetical collection could have GetSum() method which returns the total of the set of items held. The collection just a easily have a Sum property instead but by using a method it communicates the idea that the collection will have to do some real work to get an answer.
I'd never use a property if I could be affecting more than one field - I'd always use a method.
Generally, I just use the
public string ErrorLog { get; private set; }
syntax for Properties and use Methods for everything else.
In addition to Reed's answer when the property is only going to be a getter like getting a resource such as an Event Log might be. I try and only use properties when the property will be side effect free.
If there is more than something trivial happening in a property, then it should be a method. For example, if your ErrorLog getter property was actually going and reading files, then it should be a method. Accessing a property should be fast, and if it is doing much processing, it should be a method. If there are side affects of accessing a property that the user of the class might not expect, then it should probably be a method.
There is .NET Framework Design Guidelines book that covers this kind of stuff in great detail.
Is there a way to access the string shown by DebuggerDisplayAttribute at runtime?
For our business objects i try to get automatic debugger information on exception handling. the actual object that was used while the exception was caught should be serialized to text to enhance the exception message. Since some attributes have other business objects as type, this could get really long if used recursively. Therefore i'd like to serialize to just the information that is already defined in DebuggerDisplay attributes of the class. The ToString() implementation of the classes can differ and are not usable for this task.
So is it possible to get the string that is shown in the debugger at runtime?
I don't think so (at least not without some effort on your part) - I've just done a bit of digging around and found this an article about Debugger Display Best Practices. It's not directly related, but it does highlight one thing:
Each property {expression hole} must
be evaluated individually and done so
once for every instance of this type
in every debugger display window.
I expect that it's using the debugger to do the evaluation once the code has been broken into (kind of similar to how you would use the immediate window to evaluate a statement when you're at a breakpoint).
The long and short of it is that the resulting debugger display value for an object is not available to you at runtime, unless you're willing to parse each of the expression holes and use reflection to evaluate them yourself.
The article suggests that the most efficient way to provide debugger output is to have a private method do a String.Format over all the properties you want to display. You might want to consider making this a public method (maybe on an interface) and use this to retrieve your exception information from.
Probably there is some way to extract that information, but wouldn't it be easier to redefine those classes with a property like this:
[DebuggerDisplay("{InfoProperty}")]
class X {
public string InfoProperty {
get { return "Debug and display info here"; }
}
}
Then you include that InfoProperty in your error messages / logs instead of digging the way the data for display is reconstructed by Visual Studio.
Of course I am assuming that you can modify the business object classes, which might not be the case...
Technically, sure, it's possible - you could access the DebuggerDisplayAttribute at runtime with Reflection and write some code that parses the string and again uses Reflection to get the values.
This won't work if you've got anything but properties and fields inside those curly braces, though.
In any case, I strongly suggest you heed Mike or Paolo's advice -if there are hundred of classes you need to change - then find a way to change them automatically - either with something like Resharper's Structural
Search and Replace, or a Regular Expression - it shouldn't take too long.
After reading this blog entry : http://wekeroad.com/post/4069048840/when-should-a-method-be-a-property,
I'm wondering why Microsoft choose in C# :
DateTime aDt = DateTime.Now;
instead of
DateTime aDt = DateTime.Now();
Best practices say : Use a method when calling the member twice in succession produces different results
And DateTime.Now is perfect example of non-determistic method/property.
Do you know if there any reason for that design ?
Or if it's just a small mistake ?
I believe in CLR via C#, Jeffrey Richter mentions that DateTime.Now is a mistake.
The System.DateTime class has a readonly
Now property that returns the current date and time. Each time you query this
property, it will return a different value. This is a mistake, and Microsoft wishes that
they could fix the class by making Now a method instead of a property.
CLR via C# 3rd Edition - Page 243
It actually is deterministic; it's output is not random, but is based on something quite predictable.
The 'current time' changes all the time; so to be relatively "the same" with each call, that value must change so that every time it's called, it's returning the current time.
EDIT:
This just occurred to me: Of course, two subsequent calls to a property getter can return different results, if something changed the property value in the interim. Properties are not supposed to be Constants.
So, that's what happening (conceptually) with DateTime.Now; its value is being changed between subsequent calls to it.
According to MSDN you should use a property when something is a logical data member of the object:
http://msdn.microsoft.com/en-us/library/bzwdh01d%28VS.71%29.aspx#cpconpropertyusageguidelinesanchor1
The go on to list out the cases where a method would be more appropriate. What is ironic is that one of the rules for a method is to use it when successive calls may return different results and of course Now certainly meets that criteria.
Personally I think this was done to eliminate the needs for the extra (), but I have found the absence of () confusing; it took me a little while to shift from the old approach in VB/VBA.
Guidelines are just that, not hard and fast rules.
Those guidelines are intended for stateful objects, and in reality are trying to say that properties should not mutate an object. DateTime.Now is a static property, so calling it does not mutate an object. It's also merely reflecting the natural state of time, not changing anything. It is simply observing a constantly changing timer.
So the point is, don't create properties that change the state of the object. Do create properties that merely observe the state of the object (even if the state changes externally).
As another example, let's look at the length of a string. This is a property, but the length of the string can change from invocation to invocation if something else changes the string externally. That's basically what is going on, the timer is being changed externally, Now just reflects its current state just as string.Length or any other such property.
In deciding "method versus property", a suggested test is "will successive calls return different results". I would suggest that a better test is the similar, but not identical question, "will calling the routine affect the outcome of future calls to the same or different routines?" In most cases, the answers to both the questions will be the same, since by far the most common reason that later calls to a routine will yield different results from the former one would be that the former one caused the later call to return a different result than it otherwise would have.
In the case of DateTime.Now, the only way in which one call would affect the value returned by another would be if the execution time taken by the first call caused the second call to occur measurably later than it otherwise would have. While a pedant might consider the passage of time to be a state-altering side effect of the first call, I would suggest that there are many properties which take longer to execute than DateTime.Now, and thus a call to any of those would have a greater likelihood of changing the value returned by a subsequent DateTime.Now call.
Note that if the "get time" routine were a virtual class member rather than being a static member, that would shift the balance in favor of making it a method; while the "expected" implementation would not affect the state of any object, it would be likely--or at least plausible--that some implementations might have side-effects. For example, calling Now on a RemoteTimeServer object might attempt to get the time from a remote server, and such attempt might have considerable side-effects on the rest of the system (e.g. by causing one or more machines to cache DNS/IP routing information, such that the next attempt to access the same server will complete 100ms faster).
Since there are no brightline rules on when to use a method and a property, DateTime.Now is truly just reading an exposed property of the state of the server, it may be constantly changing, but DateTime.Now never effects the state of any property, object or what not, so it is a property in the Framework.
In the application I am testing I want to make sure that for certain inputs the logger is being called. Some of the methods have different possible logger messages (ex. "value is malformed", "value is out of range"). Thus, I want to make sure that the logger is being called with the correct message.
The logger strings themselved are in a RESX and may be localized in the future. Also, the wording may change. So simply comparing with a hard-coded string could result in breaking the associated tests whenever the text changes. Since they are localizable, this would mean I would have to force the unit-test to execute under a certain culture, or is there a better way?
Complicating this, the RESX strings are actually not as simple as above, but of the form "Line {0}: Value '{1}' at column {2} is malformed." This is then used as input to string.Format() to produce "Line 12: Value '12a.45' at column 45 is malformed.", for example. This is the string which the logger then actually gets. Should I hard-code this string into the unit-test?
Edit:
I'll try to explain with some more detail, with a strongly simplified method to show what I mean:
public void ConvertSomething(object value)
{
if (/* Check if valid value */)
{
var convertedValue = /* Some conversion */ ;
if (/* Check is in range */)
{
// Do something
}
else
{
Logger.Log(string.Format(Resources.OutOfRange, LineNumber, convertedValue));
}
}
else
{
Logger.Log(string.Format(Resources.InvalidValue, LineNumber, value, ColumnNumber));
}
}
How do I test that the logger gets called with the correct message? I can't simply check if any call to the logger was made. If I give it a valid, but out-of-range value, but the validity check has a bug, it will call the logger, but with the message "invalid value", when it should actually be "out of range".
I can mock the logger, so I can see that it got called and what the parameters were. But what should I assert against?
You can change the current culture of threads in code, if the culture exists on the machine. If it doesn't exist, you need to install / create it.
As for comparing the strings used in the application (that may change), I would suggest not to make that the target of the test.
Instead, perhaps have a sanity test string in each resource that is static, and test for that. If that changes with the culture then you have loaded the correct resource and can safely assume the rest of the contents are correct also.
NUnit supports changing the culture of test harnesses:
http://www.nunit.org/index.php?p=culture&r=2.4.8
Update: I see so the issue is the test cannot look into the logger? I would suggest that you can either mock a logger than knows it is being tested and contains its own assertions, or abandon testing the logger itself and test that satellite assemblies are loaded currently on a culture change. If the logger simply uses the resource file then the .NET runtime will handle the loading of the correct file or default to the base culture file.
You can then have separate tests to show that the logger logs, without worrying about what it logs as that is covered in another test.
Update 2: I think I see what you are trying to do. Would it be possible at all to have the logger accept the string format and a params object[] args in order to get access to the string before it is inserted with specific values?
Alternatively, is it possible to make the string static or is it by nature changing each test run? It is valid for the test to have values hardcoded in them if the test itself is responsible for seeding the values in the first place. Also, as for the culture, I would address those changes separately to the changes introduced by different code paths choosing different messages.
Update 3: sorry, I could not see the wood for the trees. The test itself can build the expected string from the resx file that the code uses - and just plugs in hardcoded values. This relies on the test output not differing from each run.
If the resx changes, then so long as the number of values plugged into the formatted string doesn't change, you shouldn't need to fix either the code or the test.
You create a fake logger, and monitor that it your code is calling it when needed.