NHibernate log4net performance problem - how to disable? - asp.net

I was profiling our ASP .NET application to try and reduce the CPU usage and fond some strange behaviour regarding NHibernate and log4net.
Over 50% of the time on our app is spent in the log4net GetLogger and CreateRepository methods, which are called from ExecuteReader in NHibernate. The screenshot below is a jetBrains dottrace hotspot analysis where the arrows point from a calling method to the called method.
The below screenshot is just a straight up list of slowest functions.As you can see the NHybridDataReader constructor calls GetLogger and it takes ages.
Clearly something fishy is going on, and I want to disable log4net completely in NHibernate as we use other logging functionality.
Our web.config has no entries in it regarding log4net, so how do I disable it? There are no log files being produced, and from the look of the method names, it hasn't actually got round to logging anything, but is merely trying to find the logger it should write stuff to.
Most confusing, can anyone help?

For an answer to your specific question (turning off use of log4net by NHibernate), look into the code the Logging.cs file for NHibernate. When I looked at it (granted, I looked at 3.0 alpha code, but I doubt it's much different than 2.x), in the static LoggerProvider constructor, it delegates to GetNHibernateLoggerClass to determine the class to utilize. If it doesn't get one, it uses a no-op based class. So if you look in the GetNHibernateLoggerClass method, you see that it first looks for an appsettings key called "nhibernate-logger", which you should be able to set to "NHibernate.NoLoggingLoggerFactory, NHibernate". You may also notice that lacking a defined key, it will automatically use log4net if it finds the log4net DLL in the search path (likely just the directory containing NHibernate DLL. So you may also want to try removing the log4net DLL itself and see what happens. Though the first solution is more explicit and the second more is more inferred, so I would use the first.
As a side note, this is a great example of why open source works so well. Being able to just look thru the source code to answer a question like this. In closed source, you'd either have to cheat and .NET reflector the code (which could be obfuscated), or pray that the owners heavily documented obscure points like this one.
BTW, this same source code file provides what would need if you want to take NHibernate's log messages and redirect them to your own logging solution, as you mentioned you had (implement the ILogger and ILoggerFactory interfaces and use the config setting).

As I see it, the screenshot you posted says that the time is actually spent on NHibernate running some query. log4net has nothing to do here. The real problem is that you seem to be executing some query 3529 times.

Set the logging level approproately for the NHibernate logger in your config file:
<logger name="NHibernate">
<level value="ERROR" />
</logger>
I believe it defaults to DEBUG and it does a lot of logging. I would not disable it entirely since you want to be informed of ERROR or FATAL events.

Related

Biztalk insists "This Assembler cannot retrieve a document specification using this type" but I am confident it is wrong

First and foremost I would like to draw your attention to this:
That's because I have been to all of those links. I've tried those suggestions (I'll get into that). I've even been to the second page of Google.
I'm working on an existing setup which I think I might have broke when I imported bindings from another server without backing up the current bindings. When the imported bindings failed I had nothing to revert to. My bad, I know you are always supposed to back things up but this time I did not. Anyways, or maybe the bindings have nothing to do with any of it, I really don't know.
When executing a stored procedure it says This Assembler cannot retrieve a document specification using this type: "http://Foo.Bar.SQLIO#A_sqli". Now the namespace and database server are covered up here but trust me, they are correct.
Now this is where people will insist the only possible reason this ever happens is either:
There is a namespace collision and you have to explicitly specify the strong name.
The assembly is not in the GAC.
So let's talk about 1 first... So I'm gonna grab the SchemaStrongName, AssemblyName AKA Foo.Bar.SQLIO, Foo.Bar, Version=1.5.0.0, Culture=neutral, PublicKeyToken=585b3f1e468ca8f5 and paste that into the DocumentSpecNames of the XMLTransmit Send pipeline on the Send Port.
Now I rerun and the namespace ambiguity/collision/problems should be gone but they are not. Instead I get a new error which basically says the same thing.
Okay but I am pretty sure that the schema exists exactly once and the dll is deployed to the GAC correctly. Why? Several reasons:
First, the schema is listed only once. .
I can further validate that by programmatically referencing the assembly in a standalone console app, and printing the schema to a file.
static void Main(string[] args)
{
var x = new Foo.Bar.SQLIO();
Console.WriteLine(x.XmlContent);
File.WriteAllText(#"C:\Users\CoolSean\Desktop\OUT-OF-ASSEMBLY.xsd", x.XmlContent);
}
As for the dll being in the GAC I can verify that with gacutil -l Foo.Bar and it is there. If I do gacutil -u Foo.Bar and restart the host instances it fails because it can't find the assembly, meaning I am poking at the right assembly. It does exist and it does contain the schema and even the BizTalkMgmtDb database knows about it.
What can I do to run this down? I've got a working copy of this BizTalk application on another server and I setup a SQL Profiler trace on the broken box and the working box. The database calls are identical right up until the broken box starts logging errors about how it can't find that schema. idk man. What if I recompile Foo.Bar.dll such that it writes to a file any time anyone calls any of its methods. That would tell me ....something. Maybe. Probably not. I'm out of ideas.

How to log warnings by using elmah

I am using elmah to handle exceptions. Now my needs have been increased and I want to log some warnings after few statements like NLog.
Here i want to add data in SQL database. I also want to add one column in elmh table, which tells me which row is belongs to error and which belongs to warning, because I need to render them separately.
Eg. ElmahError.axd and ElmahWarn.axd.
I may need to override elmah class to achieve this, but is there any other library which gives both features, error handling and logging?
What is the best way to get this done?
If you want to log warnings in ELMAH, you will need to log it as an exception. You can create a custom exception named WarningException or something. With that said, ELMAH is created for errors and doesn't really fit well with other severities.
Adding custom data to ELMAH isn't possible either. Unless you fork the ELMAH source code and create a custom build of course. You will need to extend the Error class among others.
I'm the founder of the cloud-based error management system elmah.io. We support all severities known from other logging frameworks. With my experiences developing elmah.io, I will recommend you to use ELMAH what it's good for (logging errors) and combining it with a logging framework of choice. We use Serilog to get structured logging in Elasticsearch, but NLog, log4net etc. should do the job as well.

understanding Trace listeners

I've recently just discovered the power of Tracing(no clue why it took this long). The theory and practice wasn't unknown to me just the resources available in .Net for doing so. Traditionally I would just log the parts of my programs that I needed to investigate until I got an answer to any problems or confusion. As of recent this task just doesn't give me enough information and is far too tedious as my application is too big now. There are not a lot of clear resources on much of this so I have a few questions:
If I add my own trace listener source to the trace.listeners collection will that trace listener receive the trace information that can be seen in the trace.axd page when tracing is enabled in the web.config of my application?
If so how would I go about creating said listener that can receive that input? I've created my own class that implements the trace listener class and I can't seem to get any other input to be logged other than my own? Have I misunderstood something?
If there is another way to log my application line by line without having to place my own logging, that would be very very helpful. Thank you.
If I add my own trace listener source to the trace.listeners
collection will that trace listener receive the trace information that
can be seen in the trace.axd page when tracing is enabled in the
web.config of my application?
You will be able to see anything written to Trace. The trace that is written to trace.axd is a bit different from a plain vanilla TraceSource, TraceListener, etc. The biggest difference is that it uses the Trace object, which is the .NET 1.1 way of doing trace. in .NET 2.0 & later, named TraceSources are introduced.
If you register a TraceSwitch, TraceSource and TraceListener in your web config, you can enable listening to any TraceSource that you know the name of, the WCF libraries are an example.
Other places document TraceSource and TraceListener and switches better than I can, e.g. http://blog.stephencleary.com/2010/12/simple-and-easy-tracing-in-net.html or https://msdn.microsoft.com/en-us/library/ms228984(v=vs.110).aspx
If so how would I go about creating said listener that can receive
that input? I've created my own class that implements the trace
listener class and I can't seem to get any other input to be logged
other than my own?
You can start by subclassing the ConsoleLogListener or a TextWriterTraceListener. This library has many tools for dealing with the rough edges of System.Diagnostics Trace. https://essentialdiagnostics.codeplex.com/
(Because the built in library has rough edges, expect to see a few people tell you to use some other logging library, there are many, but only System.Diagnostics is built in and always available)
If there is another way to log my application line by line without
having to place my own logging, that would be very very helpful.
This requires "code weaving" or Aspect oriented programming, where you use a tool to recompile your application and add things like logging or trace everywhere or where ever a certain attribute is found. PostSharp is one such application. Memory profiles sort of give you that line by line trace as a byproduct of showing you where your application is spending most of its time.

Debugging SDL Tridion 2011 Custom Resolvers and the GetListPublishItems() method

In one of my C# Template Building Blocks I have the following line of code
publication.GetListPublishItems(uriTarget, false, false,
TDSDefinesInterop.ListColumnFilter.XMLListDefault, listRowFilter);
Before implementing a Custom Resolver, this code executed very quickly. Now that my resolver is implemented for the Publication ItemType the code executes really slowly. From this I conclude that the new Resolver is being called behind the scenes by the GetListPublishItems() method (which makes sense). I assume I need to modify the resolver somehow. However I can't seem to hit a break point in my resolver when the method is called.
I normally attach to the 'TcmTemplateDebugHost' when debugging a template or directly to the publisher process when debugging the resolver. My Resolver only seems to get hit when I first press Publish and not when the GetListPublishItems() method is called.
So this question is twofold:
Do Resolvers get called when the GetListPublishItems() method is used?
Assuming they are called, which process should I attach to when I need to debug it in this scenario?
I don't know for certain, but I can't imagine a sane scenario where a custom resolver wouldn't be involved in GetListPublishItems(). Your evidence seems to back this up, but of course, if we can answer the second part of your question, we'll know it for certain.
I imagine that any normal assumptions you've made about the hosting process are probably correct, so for example, if you are invoking your template during a publish, then the TcmPublisher will be the process. Alternatively, if you were to open up the publish dialog for the publication in the GUI and hit "Show Items To Publish", then it would probably be the COM Surrogate process (dllhost.exe)... and so on. One way to find out for sure, though, is to use Sysinternals Process Explorer, which has a very handy feature that will allow you to search for which processes have a given dll loaded. (Look in the Find menu)
One likely cause for a breakpoint failing to bite is that Visual Studio isn't able to load the symbols correctly. When you're debugging a template building block, Tridion explicitly loads the symbols from a known location, which you can configure (tridion.templating/debugging/#pdbdirectory in the CM config), which is where the template uploader places the PDBs. When the publisher process loads the custom resolver, I doubt if there's any such special mechanism to locate the symbols, so you'll have to fall back to standard .NET methods. The first thing I'd try is to ensure your symbols for the custom resolver class are located in the same place as the assembly (i.e. your bin directory). Failing that you could perhaps configure a symbols path in Visual studio.
The first thing to do is to watch the debug output in Visual Studio. If you start the process and then attach to it, you will see the various assemblies being loaded. If Visual Studio can find the symbols, you will see that the output says "Symbols Loaded".

ASP.Net MissingMethodException - "ctor" method not found

We are getting intermittent problems on a production server that we cannot recreate.
There are two very strange things about the issue. Firstly it's a method not found error on the constructor (ctor) for an exception handling helper class and secondly we have custom errors switched on for remote users and this property is being ignored.
The detail of the error is:
Server Error in '/MyWebsite' Application.
Method not found: 'Void MyExceptionHelperClass..ctor (System.Exception)'.
...
Exception Details: System.MissingMethodException: Method not found: 'Void MyExceptionHelperClass..ctor (System.Exception)'.
...
The stack trace is pretty unhelpful.
My thoughts are that there may be an out-of-memory error or something like that that is killing the page. When the exception handling code kicks in it tries to create an exception object which fails for the same reason giving this error.
However this is wild speculation. We are waiting for the event logs to see whether anything is amiss with the server but in the meantime does anyone have any thoughts or suggestions?
UPDATE:
It has proven difficult to get information out of the team responsible for the production servers but I have managed to find out that as far as load balancing is concerned, this site is currently only running on one server (this can be made to switch over onto another if necessary). Given that this is an intermittent problem and there is only one server involved, then I find it difficult to believe that this could be an assembly issue. Surely if it was then the problem would occur every time?
If you see this error happening on a site that has custom errors turned on, then the error is happening in the custom error handling routine itself.
From the look of the .NET error message it appears that your routine is expecting a constructor that accepts an exception by reference - your comment above shows a constructor that accepts by value.
Check carefully that there isn't a stale version of an assembly in your system somewhere. These can lurk in the Temporary ASP.NET Files folder; you'll need to do an "iisreset /stop" before you can clear them out.
In that regard it's always a good idea to make sure that AssemblyInfo.cs is set up to automatically stamp version numbers in some way. We have our version numbers tied to our source code repository system and CI build box so we can tell exactly what was in what assembly really easily.
I would use elmah: http://code.google.com/p/elmah/ to hopefully give you a bit more insight into the issue. It is free and can be used on an existing site without any recompilation. Try it - and post back if the issue is still happening.
As others have also mentioned, I would suspect that your site is somehow using an out of date version of an assembly. Something you could try doing is a full Precompile of your site before deploying to your production server. This ensures that ASP .Net doesn't dynamically compile the site on the fly, and therefore should mean that it's using completely up to date code throughout.
Do you have a no parameter public constructor defined for MyExceptionHelperClass in your code? Or is the class meant to only have static methods, in which case it should be a static class.
public class MyExceptionHelperClass()
{
public MyExceptionHelperClass() { }
}
Unfortunately, this may be one of those cases where the error message is of little to no value. In my experience, this general class of exception may be the result of either a configuration issue or bad logic aroung threading/app domains. For example, I have seen similar issues upon attempting to load the same assembly into an app domain more than once.
You mention that this is difficult to reproduce. If it's only happening on one server in the production farm it's more likely to be a config issue (with that machine). If it's happening on more than one server than it could be either config or threading.
It might be worth spending some time looking at the larger code base around the areas mentioned above. The root cause may not be in this class. Good luck!
I think it's a Framework issue with keeping compiled versions consistency. It's common to see same sort of errors while updating site sources repeatedly. Just try something like
net stop iisadmin /y && del /q /f /s "%systemroot%\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\*.*" && iisreset
I encountered this exception today on a webforms page. I found a solution, but I'm not sure why it worked.
Nest the code behind in a 'Namespace [YourNamespace]' tag.
Add the namespace to the html Page tag's Inherits property in the aspx page 'Inherits="PathStart.YourNameSpace.ClassName"'.
Rebuild
Navigate to the page again and you should not encounter the exception.
After following the steps above I reverted the changes and did not re-encounter the exception.

Resources