I'm new to azure and also a rookie in .net, so this may be a noob question :)
Anyway, I have successfully managed to log to Azure Log Analytics using this code snippet:
var loggerConfig = new LoggerConfiguration().
Enrich.WithExceptionDetails().
Enrich.WithApplicationInformation(serviceName).
MinimumLevel.Debug().
MinimumLevel.Override("Microsoft", LogEventLevel.Information).
Enrich.FromLogContext().
Destructure.ByTransforming<ExpandoObject>(JsonConvert.SerializeObject).
//Enrich.WithProperty("ErrorMsg_CF","test").
WriteTo.AzureAnalytics(workspaceId: "MyWorkSpaceID",
authenticationId: "MyAuthID",
logName: "MyCustomLog_CL",
restrictedToMinimumLevel: LogEventLevel.Debug)
And:
Logging.Logger.Initialize(serviceName: "Logging Web Test v1.1");
Logging.Logger.GetLogger().Log(LogLevel.Debug, "{ErrorMsg_CF}:{TraceID_CF}:{UserName_CF}", errorMsg,traceID,userName);
I have, in my Log Analytics custom log table, created 3 custom fields: "ErrorMsg_CF", "TraceID_CF" and "UserName_CF", and I want to either be able to directly log to these custom fields, or somehow split my errormsg into these three custom fields.
When I import a file, I see that the message is stored in the "RawData" field, and with that field I am able to use the custom field generator and create custom fields, and also let Log Analytics split the message into the fields for me. But, when I do it through my application, the message is stored in the "LogMEssage_s" field, and seems like it's not possible to create custom fields from that field.
So, anyone know how I can log to my custom fields from my application?
The default formatting configuration is a line by line event logging. ALN can be ingested using JSON so that will be the best way to format log entry in that way.
.WriteTo.DESTINATION(new CompactJsonFormatter(), OTHER OPTIONS HERE)
Serilog formatting
Related
I'm using Serilog as logging framework in my project. My question is as it states in the Title. I want different logs based on my minimum level.
I'm using LoggingLevelSwitch for dynamic log levels while the app is working but I want to customize the log itself based on this switch.
For example if my level is debug I want to show the whole object in my log but if it is information level then I just want to show lesser detail about my object or even better change the whole message template.
Something similar like this below:
if(logLevelIsAboveDebug)//inf, wrn, err, ftl
logger.Information(msgTemplateCodes.INF001,myObject.someProperty);
else
logger.Debug(msgTemplateCodes.DBG001, myObject, secondVariable)
and my template string would be something like this.
INF001 => "Some detail about action. {userKnownVariableGoesHere}"
DBG001 => "Yet another log for same action with more detail. {#myCustomObject} {someVariableDoesntMatter}"
Since not all of my logs are using the same template I guess I can't just configure this at start. I decided to make a method that will take a parameter and check. Something like this:
public static bool isLoglevelEqualOrAboveGiven(LogEventLevel givenLevel)
{
if ((int)givenLevel <= (int)logLevel.MinimumLevel) return true;
else return false;
}
And now I can just use this method to check which log I should use but is this right?
I don't want to log the whole object if it's in information level I only want the whole object in case something happen and I'm running the app in debug log level in production.
Is this approach correct? should I continue with this? will it cause any problem in my app to check this is many places?
I can do this in .net core
_logger.LogInformation("Token validated {clientId}", "MyId");
And then logging libraries like NLog will know that there is a property called clientId with the value MyId in the message and can render it in a special way.
I am trying to do the same without including the property in the message itself, but cannot manage to nail it. This is what I have done so far and it does not result in a property in NLog:
LogEventInfo info = new LogEventInfo
{
Properties = {{"clientId", "MyId"}},
};
_logger.Log(Microsoft.Extensions.Logging.LogLevel.Information, "Token validated", info, null, info.MessageFormatter);
This results in a message without property. Is there a better way to do this or have I done something wrong?
The whole idea with Microsoft-Extension-Logging (MEL) ILogger-interface is not being dependent on a specific Logging-Framework.
If you start creating NLog LogEventInfo-objects, then you might as well call NLog.LogManager.GetCurrentClassLogger() and use that as Logger.
But maybe this wiki-page can give you some ideas:
https://github.com/NLog/NLog.Extensions.Logging/wiki/NLog-properties-with-Microsoft-Extension-Logging
I'm using Serilog to write structured log data to Elasticsearch via Logstash. When writing an object in a log message like so
Log.Information("This is the {#object}", new {Prop = "example"})
An additional property, _typeTag is included in the JSON that is output. Is it possible to exclude this property?
It's possible to specify a custom ITextFormatter when logging to Elasticsearch with Serilog. The property in ElasticsearchSinkOptions is:
public ITextFormatter CustomFormatter { get; set; }
You might need to do some work to get a custom formatter configured the way you want - subclassing Serilog's JsonFormatter, or the ElasticsearchJsonFormatter that's provided with the sink, or forking to create your own, might work.
I am polling a well formatted xml messages from SQL Server table using sqlserver stored procedure that returnes me xml like the following one
<PolledMessage xmlns="http://SomeNamespace.ru/">
<Message>
<MessageNode>
<MasterDataMemberAddRequest xmlns="http://AnotherNamespace">
...
</MasterDataMemberAddRequest>
</MessageNode>
</Message>
<Message>
<MessageNode>
<MasterDataMemberAddRequest xmlns="http://AnotherNamespace">
...
</MasterDataMemberAddRequest>
</MessageNode>
</Message>
</PolledMessage>
Where the MessageNode is a node, containing the message that i want to extract. I have done that using Envelope schema with XmlReceive pipeline, and it worked well. But after that i need to write some custom values to the message context of each of that extracted messages. i've wrote a custom pipeline, that takes property name, namespace and value and writes it to the message context, but i can't figure out how to put together that disassembling and promoting properties of disassembled messages.
Thanks for any advice!
Arsen,
The XMLReceive pipeline debatches your envelope using the XML dissembler component, and will promote individual message properties providing they are correctly marked as context properties (and assuming they are in the message!)
If you need to push custom non-message properties into each message, you could create a custom pipeline and place your pipeline component that acts on each disassembled message in the resolve party stage.
Here's a link to a custom context property promotion component. You'll see in the example that it is placed in the validate stage - I believe validate or resolve party are both ok. Hope this helps!
I'm trying to localize error messages from NHibernate.Validator. From what I have read, the messages should automaticaly be localized if I set the CurrentCulture/CurrentUICultule ; wich I tried without success. I'm using S#arp Architecture with the default configuration. As I said, the only thnig I changed is the CurrentCulture/CurrentUICultule.
Do I have to create a custom message interpolator for nhibernate validator?
I have posted in my blog about creating a Custom Interpolator that overrides the default messages if they exist in your resources. It allows you to override the default messages and add new messages for your validators.
Check it out: NHibernate Validator Custom Messages
Changing the culture for was not a good idea, since all my website is in spanish, so the path that I took was to create a SpanishMessageInterpolator and then set it up in my nhv.config like:
<property name="message_interpolator_class">NHibernateValidator.SpanishMessageInterpolator, Assembly</property>
And finally I did modify my global.asax.cs file to include the nhv.config file on NHibernate initialization, like:
NHibernateSession.Init(
webSessionStorage,
new string[] { Server.MapPath("~/bin/Assembly.dll") },
new AutoPersistenceModelGenerator().Generate(),
Server.MapPath("~/NHibernate.config"), Server.MapPath("~/nhv.config"));