I use Serilog for logging. I need to configure App.config as to remove 2 standard columns from Logs table (StandardColumn.Properties and StandardColumn.MessageTemplate). I've searched for it in Serilog docs and other resources but can't find how to do it. This is what I got so far:
<configuration>
<appSettings>
<add key="serilog:using:MSSqlServer" value="Serilog.Sinks.MSSqlServer" />
<add key="serilog:write-to:MSSqlServer.connectionString" value="Data Source=SomeServer;initial catalog=DB; integrated security=True" />
<add key="serilog:write-to:MSSqlServer.tableName" value="Logs" />
<add key="serilog:minimum-level" value="Debug" />
</appSettings>
</configuration>
I guess I would have to add this line:
<add key="serilog:write-to:MSSqlServer.columnOptions" value="someColOptions" />
but how should I define someColOptions? For example, I removed columns using this kind of code:
var colOptions = new Serilog.Sinks.MSSqlServer.ColumnOptions();
colOptions.Store.Remove(StandardColumn.Properties);
colOptions.Store.Remove(StandardColumn.MessageTemplate);
Log.Logger = new LoggerConfiguration()
.WriteTo
.MSSqlServer(
connectionString: conn_string,
sinkOptions: new MSSqlServerSinkOptions { TableName = "Logs" },
columnOptions: colOptions)
.MinimumLevel.Debug()
.CreateLogger();
and now I want to do the same in App.config
I had a similar question, I've been able to find out that by adding the following, the configSections has to be first section after
that this will:
create a Logs table in the specified Database (from the connection string)
Use the Serilog database account (from the connection string)
Remove the column called Properties from the Logs table
Add a new column called RunId that declared as an int
<configuration>
<configSections>
<section name="MSSqlServerSettingsSection" type="Serilog.Configuration.MSSqlServerConfigurationSection, Serilog.Sinks.MSSqlServer"/>
</configSections>
<MSSqlServerSettingsSection DisableTriggers="false" ClusteredColumnstoreIndex="false" PrimaryKeyColumnName="Id">
<!-- SinkOptions parameters -->
<TableName Value="Logs"/>
<BatchPeriod Value="00:00:15"/>
<RemoveStandardColumns>
<remove Name="Properties"/>
</RemoveStandardColumns>
<Columns>
<add ColumnName="RunId" DataType="int"/>
</Columns>
</MSSqlServerSettingsSection>
<appSettings>
<!-- Serilog Settings -->
<add key="serilog:minimum-level" value="Verbose" />
<add key="serilog:using:Console" value="Serilog.Sinks.Console"/>
<add key="serilog:write-to:Console"/>
<add key="serilog:using:File" value="Serilog.Sinks.File" />
<add key="serilog:write-to:File"/>
<add key="serilog:write-to:File.path" value="{PATH}" />
<add key="serilog:write-to:File.rollingInterval" value="Day"/>
<add key="serilog:using:MSSqlServer" value="Serilog.Sinks.MSSqlServer" />
<add key="serilog:write-to:MSSqlServer.connectionString" value="Server=[SERVER];Database=[DATABASE];User Id=Serilog;Password=[PASSWORD];"/>
<add key="serilog:write-to:MSSqlServer.tableName" value="Logs"/>
<add key="serilog:write-to:MSSqlServer.autoCreateSqlTable" value="true"/>
</appSettings>
</configuration>
Calling Log.("{RunId}{Message}", _runId, _messageToShow) causes my File, Console AND MSSqlServer sinks to execute writing to these, if it doesn't exist the Logs table will be created, removing the Properties column and adding the RunId column. (If the table exists it doesn't do anything but write the data, still trying to work out how to handle that).
I'm still playing around with this (my next thing is to work out how to write {RunId} but not have it appear in the log, only written to the corresponding database field).
HTH,
Phil
Related
How to fetch the corresponding value of a key that I would get dynamically. I wish to use the system defined DictionarySectionHandler to do the job, of fetching the data from my custom built config section in the Web.config file
Code block in Web.Config
<section name="domainsource" type="System.Configuration.DictionarySectionHandler"/>
<domainSource>
<add key="0" value="170" />
<add key="1" value="171" />
<add key="2" value="172" />
<add key="3" value="173" />
<add key="12" value="174" />
</domainSource>
Sourcecode in the main cs file from where I wish to retrieve the data from the Web.Config
Hashtable statusCodes = ConfigurationManager.GetSection("domainSource") as Hashtable;
vDomainSource = statusCodes[vDomainID];
This is where I am stuck vDomainID would be a value 0/1/2/3/12, based on this value I need to fetch its respective Source from the Web.Config. Any help on this aspect would be really appreciated.
You have a missspelling in the defintion of the section domainsource -> domainSource. Further ensure that the elemnt is defined in an element. Then it should work.
<configuration>
<configSections>
<section name="domainSource" type="System.Configuration.DictionarySectionHandler"/>
</configSections>
<domainSource>
<add key="0" value="170" />
<add key="1" value="171" />
<add key="2" value="172" />
<add key="3" value="173" />
<add key="12" value="174" />
</domainSource>
</configuration>
i am trying to start working with serilog. The normal RollingFile doesn't fit my needs (i need the counting like logs\20160701-00002.txt), so i want to use the RollingFileAlternate as a sink.
When using RollingFile i added
loggerInstance = new LoggerConfiguration()
.ReadFrom.AppSettings()
and was able to get the path from the App.config file with using:
<add key="serilog:minimum-level" value="Debug" />
<add key="serilog:using:RollingFile" value="Serilog.Sinks.RollingFile" />
<add key="serilog:write-to:RollingFile.pathFormat" value="..\Log\MyLOG.LOG" />
Now i switched to RollingFileAlternate :
<add key="serilog:minimum-level" value="Debug" />
<add key="serilog:using:RollingFileAlternate" value="Serilog.Sinks.RollingFileAlternate" />
<add key="serilog:write-to:RollingFileAlternate.logsDirectory" value="..\Log\test.log" />
<add key="serilog:write-to:RollingFileALternate.logsFolder" value="..\Log" />
I tried using logsDirectory and logsFolder since both are described in the examples of https://github.com/BedeGaming/sinks-rollingfile
but my program won't create a file.
if I add to the Loggerconfiguration:
loggerInstance = new LoggerConfiguration()
.ReadFrom.AppSettings()
.WriteTo.RollingFileAlternate("..\\log")
the foldername will be used and the logfiles are put in this folder.
Can some one help me and tell me what i am missing?
There may be a problem with the documentation; the argument is called logDirectory, not logsDirectory. So, you need:
<add key="serilog:write-to:RollingFileAlternate.logDirectory" value="..\Log" />
Is there any way to define multiple sinks in the XML config for serilog that will allow the outputTemplate to change based on the level of log?
I currently have:
<add key="serilog:minimum-level" value="Verbose" />
<add key="serilog:write-to:ColoredConsole" />
<add key="serilog:write-to:RollingFile.pathFormat" value="C:\Logs\AdapterService-{Date}.txt" />
<add key="serilog:write-to:RollingFile.retainedFileCountLimit" value="10" />
<add key="serilog:write-to:RollingFile.outputTemplate" value="[{Timestamp:G}] [{Level}] [{SourceContext:l}] {Message}{NewLine:l}{Exception:l}" />
However would like the Debug level logs to not include the SourceContext string as in:
<add key="serilog:write-to:RollingFile.outputTemplate" value="[{Timestamp:G}] [{Level}] {Message}{NewLine:l}{Exception:l}" />
I am aware you can set the restrictedToMinimumLevel: LogEventLevel.Verbose but I am unsure how to do this in the XML.
Well, yes there are multiple posts on the same subject. One of the solutions for my problem is multiple web.config files but I am not sure if it works.
The problem:
I have a asp.net project. I have two clients (having their own storage and database) on which i need the application to be deployed. Storage and database are just two examples but there are many other settings unique to the client which can be managed in app settings. Whatever changes i do the project code, i need to deploy for both the clients.
Currently my web config looks like this:
<!-- GHR Settings -->
<connectionStrings>
<add name="DefaultConnection" connectionString="conn-string" providerName="System.Data.SqlClient" />
</connectionStrings>
<appSettings>
<add key="StorageConnectionString" value="DefaultEndpointsProtocol=https;AccountName=<acntName>;AccountKey=<acntKey>" />
<add key="StorageURL" value="<storageurl>" />
<add key="ProfileURL" value="<ProfileURL>" />
<add key="GenericURL" value="<GenericURL>" />
<add key="IDocURL" value="<IDocURL>" />
<add key="LogosURL" value="<LogosURL>" />
<add key="DocsURL" value="<DocsURL>" />
<add key="DefaultPassword" value="pass123" />
</appSettings>
<!-- TP Settings -->
<!--
<connectionStrings>
<add name="DefaultConnection" connectionString="conn-string" providerName="System.Data.SqlClient" />
</connectionStrings>
<appSettings>
<add key="StorageConnectionString" value="DefaultEndpointsProtocol=https;AccountName=<acntName>;AccountKey=<acntKey>" />
<add key="StorageURL" value="<storageurl>" />
<add key="ProfileURL" value="<ProfileURL>" />
<add key="GenericURL" value="<GenericURL>" />
<add key="IDocURL" value="<IDocURL>" />
<add key="LogosURL" value="<LogosURL>" />
<add key="DocsURL" value="<DocsURL>" />
<add key="DefaultPassword" value="pass123" />
</appSettings>
<add key="DefaultPassword" value="pass123" />
</appSettings> -->
As you can see, I have duplicated the settings and comment one client's settings, deploy on the server. Then I do it for other client.
This works alright, but too much maintenance during the publishing and prone to errors.
Please suggest what is the correct way of doing this.
Thanks.
What I have done in my case is create a separate config file for the DB connectionstring and reference that file inside your web.config. By this way you can have the same web.config for both your clients and would only need to send the connectionstring.config file only once!
Inside your web.config
<connectionStrings configSource="ConfigFiles\ConnectionStrings.config" />
And inside that file put the connectionstring
Same thing can be done for section
Is it possible to transform the following Web.config appSettings file:
<appSettings>
<add key="developmentModeUserId" value="00297022" />
<add key="developmentMode" value="true" />
/* other settings here that should stay */
</appSettings>
into something like this:
<appSettings>
<add key="developmentMode" value="false" />
/* other settings here that should stay */
</appSettings>
So, I need to remove the key developmentModeUserId, and I need to replace the value for the key developmentMode.
You want something like:
<appSettings>
<add key="developmentModeUserId" xdt:Transform="Remove" xdt:Locator="Match(key)"/>
<add key="developmentMode" value="false" xdt:Transform="SetAttributes"
xdt:Locator="Match(key)"/>
</appSettings>
See Also: Web.config Transformation Syntax for Web Application Project Deployment
Replacing all AppSettings
This is the overkill case where you just want to replace an entire section of the web.config. In this case I will replace all AppSettings in the web.config will new settings in web.release.config. This is my baseline web.config appSettings:
<appSettings>
<add key="KeyA" value="ValA"/>
<add key="KeyB" value="ValB"/>
</appSettings>
Now in my web.release.config file, I am going to create a appSettings section except I will include the attribute xdt:Transform=”Replace” since I want to just replace the entire element. I did not have to use xdt:Locator because there is nothing to locate – I just want to wipe the slate clean and replace everything.
<appSettings xdt:Transform="Replace">
<add key="ProdKeyA" value="ProdValA"/>
<add key="ProdKeyB" value="ProdValB"/>
<add key="ProdKeyC" value="ProdValC"/>
</appSettings>
Note that in the web.release.config file my appSettings section has three keys instead of two, and the keys aren’t even the same. Now let’s look at the generated web.config file what happens when we publish:
<appSettings>
<add key="ProdKeyA" value="ProdValA"/>
<add key="ProdKeyB" value="ProdValB"/>
<add key="ProdKeyC" value="ProdValC"/>
</appSettings>
Just as we expected – the web.config appSettings were completely replaced by the values in web.release config. That was easy!
If you want to make transformation your app setting from web config file to web.Release.config,you have to do the following steps.
Let your web.config app setting file is this-
<appSettings>
<add key ="K1" value="Debendra Dash"/>
</appSettings>
Now here is the web.Release.config for the transformation.
<appSettings>
<add key="K1" value="value dynamicly from Realease"
xdt:Transform="SetAttributes"
xdt:Locator="Match(key)"
/>
</appSettings>
This will transform the value of K1 to the new value in realese Mode.
I do not like transformations to have any more info than needed. So instead of restating the keys, I simply state the condition and intention. It is much easier to see the intention when done like this, at least IMO. Also, I try and put all the xdt attributes first to indicate to the reader, these are transformations and not new things being defined.
<appSettings>
<add xdt:Locator="Condition(#key='developmentModeUserId')" xdt:Transform="Remove" />
<add xdt:Locator="Condition(#key='developmentMode')" xdt:Transform="SetAttributes"
value="false"/>
</appSettings>
In the above it is much easier to see that the first one is removing the element. The 2nd one is setting attributes. It will set/replace any attributes you define here. In this case it will simply set value to false.