I have been following Logging in ASP.NET Core Which is working just fine.
I have a question about this line
_logger.LogWarning(LoggingEvents.GetItemNotFound, "GetById({ID}) NOT FOUND", id);
I am wondering why they are not using $ - string interpolation?
_logger.LogWarning(LoggingEvents.GetItemNotFound, $"GetById({ID}) NOT FOUND");
Why would the LogWarning extension have a params object[] args paramater?
Whats the point when you can just send everything in string message.
I assume there is a reason for this but i haven't been able to find an explanation anywhere. I am wondering which method i should be using in order to log properly in .net core.
I suspect the question can be rephrased to :
Why didn't they provide overloads that accept a FormattableString to pass message templates and parameters using string interpolation syntax, like EF Core does for parameterized queries?
I'd say they got it right. At this point in time using FormattableString offers minimal benefits but creates a lot of confusion.
I just found that Serilog's author explains why this isn't such a good idea even though a semantic logging library looks like a natural fit for this scenario
Semantic Logging
One can argue that FormattableString would be a great addition to semantic logging libraries like Serilog. In this case an interpolated string does lose important information.
The call
Log.Information("Logged in {UserId}", loggedInUserId);
Won't just log a string based on the template, it will keep the names and values of the parameters and provide them to filters and targets. Wouldn't it be great to get the same result with :
Log.Information($"Logged in {loggedInUserId}");
Serilog's author doesn't think so and explains that :
A good variable name is not necessarily a good property name
Holes don’t always have obvious names, eg Log.Information($"Enabling categories {new[]{1, 2, 3}}");
and concludes that
String interpolation is a great feature, one I’ve looked forward to in C# for a long time. The idea of providing direct support for Serilog is a very interesting one and worth exploring, but I’m increasingly convinced it’s unnecessary.
Interpolation is nice when it keeps code DRY, cutting out the redundant clutter of {0} and {1} and preventing parameter mismatches.
In the case of Serilog, I think it’s incorrect to consider the property names like {UserId} as redundant; in a well-implemented logging strategy they’re an incredibly important part of the picture that deserve their own consideration. You wouldn’t let variable names determine the table and column names in a relational database – it’s exactly the same trade-off being considered here.
Original explanation
That's one of the most controversial features of EF Core actually, and can easily result in the very SQL injection and conversion problems one wants to avoid by using parameters.
This call :
string city = "London";
var londonCustomers = context.Customers
.FromSql($"SELECT * FROM Customers WHERE City = {city}");
calls FromSql(FormattableString) and will create a parameterized query :
SELECT * FROM Customers WHERE City = #p0
And pass London as a parameter value.
On the other hand this :
string city = "London";
var query=$"SELECT * FROM Customers WHERE City = {city}";
var londonCustomers = context.Customers.FromSql(query);
calls FromSql(string) and will generate :
SELECT * FROM Customers WHERE City = London
Which is invalid. It's far too common to fall in this trap even when you do know about the risk.
It doesn't help at all when you already have predefined queries or messages. This usage is far more common in logging, where you (should) use specific message templates defined in well known locations, instead of sprinkling similar looking strings in every log location.
One could argue that this addition made EF Core 2.0 somewhat safer because people had already started using string interpolation in EF Core 1.0, resulting in invalid queries. Adding the FormattableString overload the EF Core team was able to mitigate that scenario while making it easier to accidentally cause a different problem.
At this point in time the logging designers decided to avoid this confusion. Logging a raw string doesn't have such catastrophic consequences.
At least two reasons.
First, logging pre-dates string interpolation, and Microsoft have not yet invented a time machine. String interpolation was only introduced in C# 6 in July 2015, but the logging methods follow the same pattern used in Microsoft.Build.Utilities since dotnet framework 2.0.
Second, Performance. If string interpolation is used and a string is passed as a parameter, then the interpolation is done before the call to Log. However not every call to Log results in something being logged - it depends on the configuration.
If you log something at DEBUG level and your current configuration is for INFORMATION level, the it is a waste of time to do string interpolation, you can just say "Thanks, but no thanks", and return immediately after doing nothing with the arguments.
Expanding on Second, Performance
Internally, the most logger look basically like this:
void LogDebug(string Message, params object[] args){
if(this.DebugEnabled){
Log.Write(string.Format(Message,args));
}
}
// 1 with parameters
LogDebug("GetById({ID}) NOT FOUND", id);
// 2 interpolated
LogDebug($"GetById({id}) NOT FOUND");
So if Debug is not enabled, one less interpolation operation is done.
I know this is 4 years old but I don't feel any of the answers provided are really correct.
The reason is structured logging, if you use string interpolation you are just logging a single string, with structured logging you log the variables seperatly so you can access them more easily.
Imagine you have a website and you want to alert or provide a report on how long a page takes to load. You log it like this logger.LogDebug($"{PageName} took {ms}ms to load."); All your log can contain is "Index took 53ms to load."
If you log it like this instead logger.LogDebug("{PageName} took {ms}ms to laod.", PageName, sw.ElapsedMilliseconds); Then depending on your logging provider you can access all the properties seperatly and group by the PageName easily and filter all load times over 50ms. Without having to revert to Regular Expressions. E.g. SELECT PageName, Count(*) FROM Logs WHERE LogText = '{PageName} took {ms}ms to laod.' and ms > 50 GROUP BY PageName
The reason in my opinion is that .NET is using multiple levels of logging.
Trace = 0, Debug = 1, Information = 2, Warning = 3, Error = 4, Critical = 5 and None = 6.
There are differences between below codes although they look similar.
Structural logging
Logger.LogInformation("Hello {Name}", myName);
and
String Interpolation
Logger.LogInformation($"Hello {myName}");
String interpolation under the hood is identical to the use of string.Format(). Which means string.Format will always be executed
disregarding the log level and pass the formatted string to the logger.
On the other hand, when structural logging is used, the string will only be formatted as per the log level is met.
Related
I am currently trying to understand serilogs for structured Logging.
Is there a way to enforce common Property to be used in serilog . Like if I have a log written in code like below
log.Info("Disk Quota {DiskQuota} exceeded by user {Username}", 100, "User1")
How can I use message template to ensure that any future log written in 2 to 3 classes where disk quota exceeding warning could be thrown and needs to be logged, uses always {Username} only and not {user} or {userid} etc.
log.Info("Disk Quota {DiskQuota} exceeded by user {User}", 100, "User2") // Disallow , Possibly ??
There is nothing out-of-the-box in Serilog that does that for you.
A good solution to this would be to implement your own source code analyzer, that can perform these checks during the build and emit warnings and/or errors when messages are similar but have different property names.
You'd have to define a String metric to decide what "similar" means to you. There are a number of String metrics you can use, and each of them are similar but have some different characteristics, with the popular ones being:
Levenshtein Distance: The minimum number of single-character edits required to change one word into the other. Strings do not have to be the same length;
Hamming Distance: The number of characters that are different in two equal length strings;
Smith–Waterman: A family of algorithms for computing variable sub-sequence similarities;
Sørensen–Dice Coefficient: A similarity algorithm that computes difference coefficients of adjacent character pairs.
You also leverage parts of the source code of the SerilogAnalyzer project to find message templates in code, and perform the checks.
A much more simple solution (but not as effective because relies on good developer behavior) would be to declare these standard message templates in a class, inside of a project that is shared across your solution, so that you can reference them instead everywhere instead of typing.
e.g.
public static class LogMessageTemplates
{
public const string DiskQuotaExceededByUsername = "Disk Quota {DiskQuota} exceeded by user {Username}";
}
And then everywhere you'd rely on developers to always use these pre-defined message templates, instead of typing the strings directly. e.g.:
log.Info(LogMessageTemplates.DiskQuotaExceededByUsername, 100, "User1");
If you use this approach you'll probably want to install SerilogAnalyzer in the project to help you identify places where the message template has X parameters but you are using Y given that it's now more difficult to spot how many properties a message template has just by looking at the name.
I need to locate a fast, lightweight expression parser.
Ideally I want to pass it a list of name/value pairs (e.g. variables) and a string containing the expression to evaluate. All I need back from it is a true/false value.
The types of expressions should be along the lines of:
varA == "xyz" and varB==123
Basically, just a simple logic engine whose expression is provided at runtime.
UPDATE
At minimum it needs to support ==, !=, >, >=, <, <=
Regarding speed, I expect roughly 5 expressions to be executed per request. We'll see somewhere in the vicinity of 100/requests a second. Our current pages tend to execute in under 50ms. Usually there will only be 2 or 3 variables involved in any expression. However, I'll need to load approximately 30 into the parser prior to execution.
UPDATE 2012/11/5
Update about performance. We implemented nCalc nearly 2 years ago. Since then we've expanded it's use such that we average 40+ expressions covering 300+ variables on post backs. There are now thousands of post backs occurring per second with absolutely zero performance degradation.
We've also extended it to include a handful of additional functions, again with no performance loss. In short, nCalc met all of our needs and exceeded our expectations.
Have you seen https://ncalc.codeplex.com/ and https://github.com/sheetsync/NCalc ?
It's extensible, fast (e.g. has its own cache) enables you to provide custom functions and varaibles at run time by handling EvaluateFunction/EvaluateParameter events. Example expressions it can parse:
Expression e = new Expression("Round(Pow(Pi, 2) + Pow([Pi2], 2) + X, 2)");
e.Parameters["Pi2"] = new Expression("Pi * Pi");
e.Parameters["X"] = 10;
e.EvaluateParameter += delegate(string name, ParameterArgs args)
{
if (name == "Pi")
args.Result = 3.14;
};
Debug.Assert(117.07 == e.Evaluate());
It also handles unicode & many data type natively. It comes with an antler file if you want to change the grammer. There is also a fork which supports MEF to load new functions.
It also supports logical operators, date/time's strings and if statements.
How about the Fast Lightweight Expression Evaluator? It lets you set variables and supports logical operators.
If you need something beefier and have the time, you could also design your own expression language with Irony.
Hisystems' Interpreter supports custom functions, operators and literals, is lightweight pure c# portable code. Currently runs on iOS via MonoTouch and should run on any other Mono environment as well as windows. Free for commercial use. Available on GitHub at https://github.com/hisystems/Interpreter.
I fully appreciate how late this answer is however I would like to throw in my solution because I believe it can add more above the accepted answer of using NCalc should someone wish to use the expressions across multiple platforms.
-- Update --
I have created a parser for C# with plans to also implement it for Java and Swift over the next few months. This would mean that you can evaluate the expressions on multi-platforms without the need for tweaking per platform.
While Java and Swift was planned it never made it in to a fully fledge release. Instead there is now support for .NET Standard enabling support for Xamarin apps.
-- End update --
Expressive is the tool and it is available at:
GitHub or Nuget.
The site has a fair amount of documentation on it but to prevent link rot here is an example on how to use it:
Variable support
var expression = new Expression("1 * [variable]");
var result = expression.Evaluate(new Dictionary<string, object> { ["variable"] = 2);
Functions
var expression = new Expression("sum(1,2,3,4)");
var result = expression.Evaluate();
It was designed to match NCalc as best as possible however it has added support for things like a 'null' keyword.
self promotion here
i wrote aa generic parser generator for c# https://github.com/b3b00/csly
you can find an expression parseras example on my github. you may need to customize it to fit your needs
Ok the title may be not correct but this is what i came as best
My question is this
Example 1
see , saw
I can convert see to saw with as
replace ee with aw
string srA = "see";
string srB = "saw";
srA = srB.Replace("aw", "ee");
Or lets say
show , shown
add n to original string
Now what i want it is, with minimum length of code, generating such procedures to any compared strings
Looking for your ideas how can i make it? Can i generate regexes automatically to apply and convert?
c# 6
Check diffplex and and see if it is what you need. If you want to create a custom algorithm, instead of using a 3rd party library just go through the code -it's open source.
You might also want to check this work for optimizations, but it might get complicated.
Then there's also Diff.NET.
Also this blog post is part of a series in implementing a diff tool.
If you're simply interested in learning more about the subject, your googling efforts should be directed to the Levenshtein algorithm.
I can only assume what your end goal is, and the time you're willing to invest in this, but I believe the first library should be enough for most needs.
I need to enable user that he can write own formula in datagridview. Something like a function in Excel.
Example of formula definition:
So, user write his own formula in formula cell and then in other table is shown result for each. How I can do this?
I would try NCalc
NCalc is a mathematical expressions evaluator in .NET. NCalc can parse any expression and evaluate the result, including static or dynamic parameters and custom functions.
Dictionary<string, int> dict = new Dictionary<string, int>() { { "Income", 1000 }, { "Tax", 5 } };
string expressionString = "Income * Tax";
NCalc.Expression expr = new NCalc.Expression(expressionString);
expr.EvaluateParameter += (name, args) =>
{
args.Result = dict[name];
};
int result = (int)expr.Evaluate();
Your formula could be manipulated to C# and dynamically compiled using SystemCodeCom.Compiler and you could run it on the fly feeding in your variable values.
Otherwise you are going to have to impliment some kind of mini parser/compiler - which is a rather particular skill and which could quickly get complicated - especially if your formulas become more complicated (which maybe likely).
There is are codeproject articles on dynamic complilation here and here. But there are plenty of other examples around on the web.
There are a number of ways you can do that, they all revolve around translating the formula into executable code.
Do you want to write your own parser or do you wnat to use an existing one. C# itself, IronPython, IronRuby, some off the shelf component. If you use a full parser you might want to look at how to restrict what the user can do with it, inadvertantly or otherwise...
If they are as simple as they look, some sort of expression builder, (pick two named values and an operator) might be the way to go, but modularise, both building the expression and evaluating it so you can beef up at some later point.
However given how simple they appear to be, I'd be tempted to predefine expressions (loaded as meta data from some sort of backing store, and make it select one of these as opposed to user entering it. You could easily spend months at this aspect of the design, is it worth it?
I had a similar requirement (dynamic parsing of expressions) recently in a project I am working on and ended up using VB expressions from WF (Windows Workflow Foundation). It certainly depends on how important this functionality is for you and how much effort are you willing to put into it. In my case it turned out better than NCalc for several reasons:
it supports more complex expressions than NCalc
the resulting expression trees can be analyzed to determine dependencies for individual expressions
it's the same language for expressions as in WF (which I already use elsewhere in the project)
Anyway, here is a short blogpost I've written on the subject.
I created the albatross expression parser a few years back. It has been open sourced for a while but I finally get around and published v2.02 and added documentation recently. It is being actively maintained. It has a couple nice features:
Circular reference detection
Source variable from external object directly
Reversed generation of expressions
Properly documented
For the project that I'm currently on, I have to deliver specially formatted strings to a 3rd party service for processing. And so I'm building up the strings like so:
string someString = string.Format("{0}{1}{2}: Some message. Some percentage: {3}%", token1, token2, token3, number);
Rather then hardcode the string, I was thinking of moving it into the project resources:
string someString = string.Format(Properties.Resources.SomeString, token1, token2, token3, number);
The second option is in my opinion, not as readable as the first one i.e. the person reading the code would have to pull up the string resources to work out what the final result should look like.
How do I get around this? Is the hardcoded format string a necessary evil in this case?
I do think this is a necessary evil, one I've used frequently. Something smelly that I do, is:
// "{0}{1}{2}: Some message. Some percentage: {3}%"
string someString = string.Format(Properties.Resources.SomeString
,token1, token2, token3, number);
..at least until the code is stable enough that I might be embarrassed having that seen by others.
There are several reasons that you would want to do this, but the only great reason is if you are going to localize your application into another language.
If you are using resource strings there are a couple of things to keep in mind.
Include format strings whenever possible in the set of resource strings you want localized. This will allow the translator to reorder the position of the formatted items to make them fit better in the context of the translated text.
Avoid having strings in your format tokens that are in your language. It is better to use
these for numbers. For instance, the message:
"The value you specified must be between {0} and {1}"
is great if {0} and {1} are numbers like 5 and 10. If you are formatting in strings like "five" and "ten" this is going to make localization difficult.
You can get arround the readability problem you are talking about by simply naming your resources well.
string someString = string.Format(Properties.Resources.IntegerRangeError, minValue, maxValue );
Evaluate if you are generating user visible strings at the right abstraction level in your code. In general I tend to group all the user visible strings in the code closest to the user interface as possible. If some low level file I/O code needs to provide errors, it should be doing this with exceptions which you handle in you application and consistent error messages for. This will also consolidate all of your strings that require localization instead of having them peppered throughout your code.
One thing you can do to help add hard coded strings or even speed up adding strings to a resource file is to use CodeRush Xpress which you can download for free here: http://www.devexpress.com/Products/Visual_Studio_Add-in/CodeRushX/
Once you write your string you can access the CodeRush menu and extract to a resource file in a single step. Very nice.
Resharper has similar functionality.
I don't see why including the format string in the program is a bad thing. Unlike traditional undocumented magic numbers, it is quite obvious what it does at first glance. Of course, if you are using the format string in multiple places it should definitely be stored in an appropriate read-only variable to avoid redundancy.
I agree that keeping it in the resources is unnecessary indirection here. A possible exception would be if your program needs to be localized, and you are localizing through resource files.
yes you can
new lets see how
String.Format(Resource_en.PhoneNumberForEmployeeAlreadyExist,letterForm.EmployeeName[i])
this will gave me dynamic message every time
by the way I'm useing ResXManager