Last updated at Mon, 06 Nov 2017 20:25:09 GMT
A few years back now, I took on an assignment to help a company modernize a series of legacy .NET applications. One of these did some back office processing. A vendor would stick some files on a shared drive, and a windows scheduled task would invoke this bit of code to parse the file, apply a whole slew of business rules to its contents, and then update the appropriate internal systems. The details are both proprietary and uninteresting, so I will spare you those.
The author of this application, if memory serves, was teaching himself on the fly (and doing an impressive job of it). One could see improvements in approach over the course of time with an audit of source history. While this is impressive, it also meant that some of the earlier decisions were not always ideal.
One such decision was a tendency to log by having the code email him. His credentials were actually hard-coded in the software, and his principal means of becoming aware of operational problems was receiving an email. Generally, this would happen after a trapped exception. So, conceptually, something like the following.
public void TryProcessLineNumber(int lineNumber) { try { ProcessLineNumber(lineNumber); } catch (Exception ex) { LetMyselfKnowViaEmail("Something went wrong: " + ex.Message); } }
If you ponder this for a moment, you can probably conceive of a possible problem. I was aware of this problem, vaguely, but I had much bigger fish to fry in the modernization effort I was leading. At least, until one fateful day, I did.
The developer who had worked on this code and who was the domain expert, involved in operations, decided one day to move onto greener pastures for his next adventure. This didn’t prove to be an immediate problem, but life sure got interesting, when, after the standard time period, IT shut down his email account. With this person leaving and all of the institutional knowledge going away, the “email myself” scheme for some quiet back office service slipped through the cracks, until a lot of tickets started coming through one day.
What was happening? Well, The SMTP client code was dutifully sending an email from this guy’s account, to his own account, both of which created exception-generating situations. And nothing was handling these exceptions, generated inside of the catch block, so the application would simply crash. That’s right — it would crash on a non-critical path logging activity. Yikes. We fixed the issue with a minimum of lasting trouble, but it was a brief and completely unnecessary fire drill.
Reflecting on this years later and, pressed for the moral of the story, I wouldn’t go with “make sure you aren’t generating unhandled exceptions in exception handling code.” It wouldn’t be “don’t hard code your email address” or “don’t email yourself” or “use a service account” either. All of those are valid lessons, but they’re symptoms of the root problem which, I’d argue, is sub-optimal dependency management. There was no need to couple that application to email sending in the first place.
Do you have applications whose code generates notification emails? Would you prefer to offload this consideration entirely while still getting the emails? If so, let me show you how quickly and easily this can be accomplished.
Logging to Logentries
The first step is to quasi-outsource the logging itself. Don’t get me wrong; you still have to make calls to a logger in your code. But what you don’t have to do is worry about how the stuff you decide to log gets to where it’s going. There is an apache tool called log4net that does a nifty architectural thing: it decouples the mechanics of writing to a log from the mechanics of capturing and storing the data.
This is accomplished via an abstraction called an “appender,” which means “the thing to which what you’re logging should be appended”. Log4net logs to whatever appender you specify via configuration. It ships with a whole ton of them, and these include implementations that allow you to log to files, databases, the console, the windows syslog, etc. There’s actually a default one that appends to SMTP, so the developer in my story could have at least used this to move the credential details out of his code. But let’s not stop there.
The abstraction allows people to create their own log4net appenders, and that’s what Logentries has done. If you have a Logentries account, getting it to store and manage your log data is as easy as installing log4net and the appender furnished by Logentries. And this is very easy to do, following their instructions for .NET and choosing log4net (vs the section for another logger, NLog). Really, this just boils down to installing a Nuget package and then updating your application’s app.config or web.config.
Seriously, that’s it. Within a few minutes, you can be logging to the cloud.
This 9 line C# program, results in the screenshot immediately below it.
class Program { private static readonly ILog _logger = LogManager.GetLogger(typeof(Program)); static void Main(string[] args) { _logger.Fatal("He's dead, Jim."); Console.ReadLine(); } }
Getting Email from Logentries
While it’s great that we’ve offloaded the burden of storing and processing our logging concern locally, it still hasn’t replaced the legacy developer’s trusty “LetMyselfKnowViaEmail” method. Let’s look now at how this might be accomplished.
In the screenshot above, you’ll notice a “Tags & Alerts” tab right above the shot of the timeline. If you click that, and then click “Create Tag /Alert” button, you’ll see a form for alert creation. Let’s fill that out. First up, let’s give the alert a descriptive name. Secondly, I think it’d be good to get an email if anything goes SERIOUSLY wrong with the code — let’s look for the word FATAL. And, finally, let’s add a label for when we review the log itself. I searched for and added one called “fatal.”
](/content/images/le-img/2016/03/FatalAlert.png)
Now, scrolling down a bit, let’s add the alert portion that will actually dispatch the email (the proper log should already be chosen, assuming you had it selected when you clicked on the “Tags & Alert” tab). Don’t worry too much about the options just now, for proving the concept. Just check the “email” checkbox next to “Send to” and then enter your email address, as shown here, and then click “Save Changes.”
Now, if I run my tiny program again, check out what happens. First, I get a snazzy new entry in my log, with the new tag applied.
Then, I get this in my inbox.
The Architectural Value Proposition
I’ve proven that you can do something interesting, but why do it? Why offload log capture and email notifications to the cloud in this case? After all, I talked about poor dependency management, but is depending on a third party vendor to store your logs and provide email alerts actually better? After all, the programmer could have simply put another try/catch around the email logging scheme and swallowed any exceptions, right?
Well, the last statement is true, and optimizing your dependency management is a complex topic, but I would argue that outsourcing the log capture and emails would have been a much better option. I could cite any number of nuanced opinions and architectural arguments, but I’ll offer just one, instead. IT infrastructure should be cohesive, meaning that things that belong together should occur together.
The software we were doing specialized in back office processing of its specific problem domain. It did not specialize in aggregating, maintaining, and mining log data, and it did not specify in managing email communications. Logentries’ software, on the other hand, *does *specialize in these things. They are experts at solving these problems and they do it for many customers so that those customers don’t have to. You have enough to worry about without making your app heavily dependent on your knowledge of log mining and email transmission. Let the experts handle that.
Capturing log data from your .Net application is easy with Logentries. You can create a free Logentries account in less than a minute – get started!