PSA: Windows Services and Event Logs

clamum

Lifer
Feb 13, 2003
26,256
406
126
I'm working on a Windows Service that processes thousands of user records from a database and sends out emails to them. A record is written to a log table after each user record is processed so the service can pick up where it left off in case of a failure somewhere.

The service uses LINQ to SQL for data access. We ran a test and and unknowingly had the incorrect db connection string in the config file, so the service would just hang and not throw any exceptions when it could not connect to the database (strange, perhaps that's just LINQ).

So I was told to add a bunch of WriteEntry() calls to the EventLog object in order to find the source of the problem. We eventually found it was because of the connection string, but the calls stayed in the service.

We ended up having major problems with the service: it would hang at a few different parts of execution, and then would not even be able to be stopped without hitting Stop twice and waiting awhile. Trying to start it would give an error: "Service started and then stopped. Some services automatically...".

Google search brought me to a page where a guy said after clearing the EventViewer for the service he was able to start it again. That got me thinking so I removed all of the WriteEntry() calls in the service except for one that outputted how many records it was processing so I could check that number against the number of records in the log table.

It ended up working. Before it would only get through about 150 records until the service hung up; removing all EventLog.WriteEntry calls but that one let the service get through all 9461 records it needed to process.

The past two days have been the most stressful I've ever had at a job because of these problems. So long story short: watch how many entries you write to the EventLog! If this even helps one person save their hair from turning gray, or losing it, I'll be happy. ;)

Maybe its the speed at which the entries were written, because it usually hung up around 2,000 - 2,200 entries in the event log for the service. And that's not much compared to the 10,000+ that were in the Security log on my work machine.
 

MrChad

Lifer
Aug 22, 2001
13,507
3
81
I just use the EventLogAppender in log4net. It's incredibly easy to configure without many code changes.
 

imported_Dhaval00

Senior member
Jul 23, 2004
573
0
0
The EventViewer shouldn't be used for logging to start off with. Use a third-party API like Log4Net to write out log files or create your own custom logger. Sadly, this is one major thing missing from the Framework (something that would allow us to control the number of max log files, max log file size, etc.).

Also, for LINQ to SQL, be careful when creating auto-entity classes via the designer. I guess it depends on the type of work you do, but I have hardly been on a project where the table schema hasn't changed multiple times. On a recent project, I realized that after go-live, if a single table changes, then my libraries will also need to reflect that change. Imagine going through this ordeal when you have 100s of tables. I learned to make use of the LINQ to SQL designer only for creating methods based on SPROCs and to force those method to map to "auto-generated classes" - it is productive and effective during development and post go-live, IMO. This has a side-effect that you access access all the relational entities easily, but I think it is too much of a hassle to maintain those table schemas in the designer. Also, the issue is alleviated by the fact that M$ did not include a "refresh" feature for the designer - meaning, if a schema change is made, the only way to capture it is via deleting and adding the table again in the designer. Not a big deal with two tables, but becomes a huge pain the rear when you have a table that has numerous FKs. Luckily, the project I worked on was a pilot system, so we were able to make the change on-the-fly.
 

Snapster

Diamond Member
Oct 14, 2001
3,916
0
0
Originally posted by: MrChad
I just use the EventLogAppender in log4net. It's incredibly easy to configure without many code changes.

:thumbsup:
 

clamum

Lifer
Feb 13, 2003
26,256
406
126
Originally posted by: Dhaval00
The EventViewer shouldn't be used for logging to start off with. Use a third-party API like Log4Net to write out log files or create your own custom logger. Sadly, this is one major thing missing from the Framework (something that would allow us to control the number of max log files, max log file size, etc.).

Also, for LINQ to SQL, be careful when creating auto-entity classes via the designer. I guess it depends on the type of work you do, but I have hardly been on a project where the table schema hasn't changed multiple times. On a recent project, I realized that after go-live, if a single table changes, then my libraries will also need to reflect that change. Imagine going through this ordeal when you have 100s of tables. I learned to make use of the LINQ to SQL designer only for creating methods based on SPROCs and to force those method to map to "auto-generated classes" - it is productive and effective during development and post go-live, IMO. This has a side-effect that you access access all the relational entities easily, but I think it is too much of a hassle to maintain those table schemas in the designer. Also, the issue is alleviated by the fact that M$ did not include a "refresh" feature for the designer - meaning, if a schema change is made, the only way to capture it is via deleting and adding the table again in the designer. Not a big deal with two tables, but becomes a huge pain the rear when you have a table that has numerous FKs. Luckily, the project I worked on was a pilot system, so we were able to make the change on-the-fly.
Any particular reason the EventViewer shouldn't be used for logging? I mean I seem to have found a problem with it as I mentioned, but is using simple .txt files a better route? I should mention that the client needs to have a ton of log entries written out so whatever is used would contain a lot of lines. Perhaps splitting the logs into folders by month, with a .txt file for each day, would work.

As far as the LINQ designer, I hate the fact there's no "refresh". Even deleting and re-adding tables rarely works for me so I have to make changes manually in the Designer.cs file and the .dbml itself.
 

imported_Dhaval00

Senior member
Jul 23, 2004
573
0
0
Originally posted by: clamum
Any particular reason the EventViewer shouldn't be used for logging? I mean I seem to have found a problem with it as I mentioned, but is using simple .txt files a better route? I should mention that the client needs to have a ton of log entries written out so whatever is used would contain a lot of lines. Perhaps splitting the logs into folders by month, with a .txt file for each day, would work.

As far as the LINQ designer, I hate the fact there's no "refresh". Even deleting and re-adding tables rarely works for me so I have to make changes manually in the Designer.cs file and the .dbml itself.

The EventViewer is an administrator-level utility to monitor system-level (low-level) events. From an administrator's standpoint, you're tainting the entries by logging each and every log entry to the event log. Also, the event log recycles itself regularly plus is processed in-memory (almost like the registry). You're taking a performance hit every time the event viewer reaches a "safe point." I don't think the latter is such a big issue. I can tell from my experience that it is really helpful to create application-specific log files and exploit the disk IO wherever possible. For example, if an ASP.NET application crashes (could be SMTP or a Web app) for whatever reason, you know that there will some entry in event log - good luck finding that entry when you've an application logging 100 lines every other minute to the same log.

To overcome this, we wrote our own little log handler which runs in its own thread, maintains a specific log size for the file, and recycles the file (archives it) upon reaching the size limit. Writing a custom logger is really trivial. From what I've heard though, Log4Net already does this and is pretty good.

As far as the LINQ issue goes, I'd say get rid of the tables from the designer... instead switch to using stored procedures (methods) that map to auto-generated types - this way if the table or the SELECT changes, all you'd be doing is dragging and dropping the new SPROC. Maintaining the tables/schema within the designer will be a nightmare. It involves a bit of extra work, but you can write SPROCs that return multiple result sets - lookup IMulitpleResults<>.