Logback configuration: factoring out reusable parts - logback

Is there a way to factor out and parameterize repeating parts of Logback XML configuration? I have many different rolling file appenders configured basically the same except for the file names. I use that in conjunction with a bunch of loggers with their 'additivity' turned off so I can redirect different parts of the stack to different files. This adds up to a cumbersome and long configuration file composed of many almost identical segments.
I've used Logback's <include> feature before, but it doesn't address this reuse issue since I can't parameterize the included configuration. I'd expect such a feature to look something akin to:
<include resource="file-appender.xml">
<property name="filePath" value="/where/logs/go" />
<property name="baseLogger" value="com.mycompany.thatpartofthestack" />
</include>
But as far as I understand that's wishful thinking. Is there another way of factoring out Logback's configuration via templates, macros, functions or whatnot?

Try using variable substitution in local and/or context scope.
Perhaps the easiest way is to define variables in some resource file, say logback.properties bundled with each each application. Moreover, each application would carry a logback.xml file importing logback.properties.
<configuration debug="true">
<property resource="logback.properties" />
<!-- set root level as given by the value of the root.level variable -->
<!-- if root.level is undefined default to DEBUG -->
<root level="${root.level:-DEBUG}"/>
</configuration>
If you wish to set the root level to WARN in webapp-A, simply add the following line in logback.properties file bundled with webapp-A.
root.level=WARN
You can bundle logback.xml as a resource in a artifact common to your various applications.

Related

Multiple logback.xml

I have created a jar file, example.jar, to be consumed by various project at my work place. The jar does have SLF4J for logging, backed by Logback.
However during build , I have excluded logback.xml with assumption that actual application will be having its own logback.xml.
Now , even though actual application does have its logback.xml, logger messages from example.jar are missing .
Could you please guide how to handles multiple logback in above mentioned scenario.
In Play Application , I have added following lines in conf/logback.xml file.
You may disable logging by making level="OFF"

Solr Core Discovery mode defining extra properties

We are upgrading to solr 4.4 and would like to be able to use the new core.properties for the new core discovery.
Currently, we have a couple of properties defined in the solr.xml for most of the cores, and I am not able to create these same properties in the new core.properties file.
Here is a core as currently defined in solr.xml:
<core name="core1003" instanceDir="core1003">
<property name="xmlDataDir" value="D:\Solrfiles\ImportFiles\core1003.xml" />
</core>
This is then used in DIH-XPathEntityProcessor.xml with <str name="xmlDataDir">${xmlDataDir}</str>.
How can I define core specific property variables like this? It doesn't necessarily have to be in core.properties, but that would make it a little easier to manage.
In your core instance directories that contain your core.properties file create a conf/ subdirectory and a solrcore.properties file in it. Define your core specific properties there and it will be picked up automatically.
Alternatively, you can add a value for "properties" to your core.properties file to point to any other file:
properties=/your/path/here.properties
I believe but have not confirmed that for this to work your cores must load on startup and must not be transient. Any non-standard properties you add to core.properties will be ignored because the CoreDescriptor copy constructor only persists the following properties from that file in memory: instanceDir, config, schema, name and dataDir (see CoreDescriptor:91 in the 4.4.0 source). I believe this is a bug?

Azure Worker Role configuration issue while using SlowCheetah with custom config

We are using Nlog as logging tool with our Worker Role of Azure app.
It requires NLog.config file. We installed "SlowCheetah - XML Transforms", and have two Debug/Release transforms).
Solution does get rebuild successfully.
But when I try to run, I am getting following error. (I used exact transformation for nolog.config in one of my Windows service app, and it is working fine there).
Error 163 The item "bin\Debug\NLog.config" in item list "OutputGroups"
does not define a value for metadata "TargetPath". In order to use
this metadata, either qualify it by specifying
%(OutputGroups.TargetPath), or ensure that all items in this list
define a value for this metadata. C:\Program Files
(x86)\MSBuild\Microsoft\VisualStudio\v10.0\Windows Azure
Tools\1.6\Microsoft.WindowsAzure.targets 2299 5 Insight.CloudWeb
I don't know if this is done by the SlowCheetah extension, but could you verify if your *.csproj file contains the AfterCompile target similar to this?
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<UsingTask TaskName="TransformXml"
AssemblyFile="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll" />
<Target Name="AfterCompile" Condition="exists(’app.$(Configuration).config’)">
<TransformXml Source="NLog.config"
Destination="$(IntermediateOutputPath)$(TargetFileName).config"
Transform="NLog.$(Configuration).config" />
<ItemGroup>
<AppConfigWithTargetPath Remove="NLog.config"/>
<AppConfigWithTargetPath Include="$(IntermediateOutputPath)$(TargetFileName).config">
<TargetPath>$(TargetFileName).config</TargetPath>
</AppConfigWithTargetPath>
</ItemGroup>
</Target>
Take a look at Oleg's blog post .Config File Transformation under App.config File Transformation for more information.
I have a fix for this. Now you should be able to transform app.config as well as other XML files for Azure Worker Roles using SlowCheetah. Once I get the fix verified I will release the update to the VS gallery.
If you would like to try the fix you can download the updated VSIX at https://dl.dropbox.com/u/40134810/SlowCheetah/issue-44/SlowCheetah-issue-44.zip. If you are interested in following up on this please use the issue #44.

What's a consistent way of obtain AppSettings that accounts for applicationHost.config?

So, appSettings can be set in app.config, web.config, machine,config... But, when you work under IIS 7 you can also have appSettings being applied under applicationHost.config with a specific carve out for your site. So, what's a consistent way for me to know what AppSettings I should be using???
System.Configuration.ConfigurationManager is fine if this is a client profile.
System.Web.Configuration.WebConfigurationManager if this is a web-app ... well, maybe.
Microsoft.Web.Administration if I expect values in applicationHosting.config - ouch ... and even then they don't roll-up hierarchically so it seems that you're left holding that process.
Does anyone have a consistent approach to processing AppSettings that accounts for applicationHost.config?
You can't actually specify <appSettings> in your applicationHost.config file. This is because applicationHost.config defines settings specific to IIS only. You can review the applicationHost.config schema to confirm this:
%systemroot%\System32\inetsrv\config\schema\IIS_schema.xml
If you try to edit applicationHost.config and add an <appSetting> section to a site or under a <location path="..."> section you will get an error (IIS may not start and IIS MMC console will display a configuration error).
If you configure a global application setting in IIS manager this actually gets configured in the master web.config file that matches the default .NET Framework version setting in IIS.
<appSettings/> is specific to the .NET Framework and can only be configured in:
%SYSTEMROOT%\Microsoft.NET\Framework\[framework version]\CONFIG\machine.config
%SYSTEMROOT%\Microsoft.NET\Framework\[framework version]\CONFIG\web.config
%SYSTEMROOT%\Microsoft.NET\Framework64\[framework version]\CONFIG\machine.config
%SYSTEMROOT%\Microsoft.NET\Framework64\[framework version]\CONFIG\web.config
and of course your application's app.config or web.config files.
My advice would be to keep these settings local to your application unless there is the rare occasion where you need some value to be available globally.
Update:
Now that I understand your problem - you have multiple IIS sites which all point to the same physical folder - there is a way to approach this.
You could have a configuration table in your database that has a primary key of whatever the HTTP_HOST value is. This maps to a prefix, for example:
Host SitePrefix
==== ======
domain1.com D001
domain2.com D002
In your web.config:
In your application's Application_Start event in Global.asax.cs initialise an application wide value:
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
string httpHost = HttpContext.Current.Request.ServerVariables["HTTP_HOST"];
Application["SitePrefix"] = GetSiteKeyFromDb(httpHost);
}
This value will be available across the whole application but unique to the site.
When you need to read a setting that is specific to the site:
string siteSetting = ConfigurationManager.AppSettings[
HttpContext.Current.Application["SitePrefix"] + "_Setting1"
];
But if you're hitting the database in Application_Start then it may actually be expedient to store all these site specific settings in the database then read and cache them in Application instead of using <appSettings />.
I used the information provided by Anti-Santa's answer to accomplish this but I didn't want to parse the URL and have another database to look up information. The same codebase is used on-premise and I wouldn't have those pieces in that scenario.
Just add the appSettings to the .NET Framework web.config with a location node.
In %SYSTEMROOT%\Microsoft.NET\Framework64\[framework version]\Config\web.config, add the following where Site1 and Site2 are my two applications pointing to the same physical directory:
<?xml version="1.0" encoding="utf-8"?>
<!-- the root web configuration file -->
<configuration>
<!-- App settings for the different applications -->
<location path="Default Web Site/Site1">
<appSettings>
<add key="ConnectionString" value="the cnn str"/>
</appSettings>
</location>
<location path="Default Web Site/Site2">
<appSettings>
<add key="ConnectionString" value="the cnn str"/>
</appSettings>
</location>
...
</configuration>
The web.config in the physical folder will override this appSetting so I also needed to remove it from that file.

Making a custom binding configurable over App.config

I've created a custom binding and want to make it configurable over App.config.
The binding has no special options at the moment, so it would be sufficient to support just
<endpoint address="http://myAddress"
binding="myBinding"
contract="myContract">
After checking some sites, I found out that I have to enable configuration support through a <BindingExtension>. However, the MSDN site didn't help much, since when I try to add
<extensions>
<bindingExtensions>
<add name="myBinding"
type="MyNamespace.MyHttpBinding, NameOfMyDll, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</bindingExtensions>
</extensions>
, I only receive the following error message when trying to launch the program:
Configuration binding extension 'system.serviceModel/bindings/myBinding' could not be found. Verify that this binding extension is properly registered in system.serviceModel/extensions/bindingExtensions and that it is spelled correctly.
The type mentioned in the bindingExtension points to the type which inherits from Binding.
What do I have to add to enable configuration support for my binding?
My goal is just to be able to export my binding to the config file. I don't want to allow any special settings for the binding. It should just be usable over the config file's <endpoint> tag.
You're on the right track. The key point, however, is that the bindingExtension element should not point directly to your binding class itself.
Instead, you need to have several class that support the configuration model.
For starting, the bindingExtension you register is really a class that inherits from StandardBindingCollectionElement. This represents a collection of StandardBindingElement, which is the configuration class that has all the configuration properties that your binding will support in the .config file and would be responsible for creating your Binding instance and setting any properties on it that were set in the .config file.
Also, notice that, normally, you'd follow a similar pattern for creating a configuration view of your TransportBindingElement (if you're doing a transport channel) so that you can create custom bindings using it though configuration. In that case, you'd have a class inheriting TransportElement.
P.S. If you're thinking this is an awful lot of repetitive code if you've got lots of settings, then I agree.
Update: Found what your problem was: You need at least an empty <bindings/> section in your config file. Just add it and the binding will be recognized now.