Thursday, February 27, 2014

Don't blame logging, start monitoring events

Traditional logging has proven its usefulness in software development over decades. Nevertheless, sometimes logging is blamed for issues that it, as a tool, is not responsible for. Logging oftentimes is simply used where it does not fit. In this post, we describe what logging should be used for and for which use cases event monitoring is more appropriate.

Core Values of Logging

Logging has been an integral part of software development for a long time. However, logging is a rather general term and overused at times. On a practical level, all of us know and use so-called logging frameworks such as log4j and log4net. What they are designed for is software tracing, that is, making an execution flow persistent. Software tracing records low-level technical events and is aimed at highly technical users. As a cross-cutting concern it is designed to help find and cure defects in a program or its runtime environment.
Most logging libraries allow their users to categorize the severity of the event that is being logged by specifying their log level, such as DEBUG, INFO or ERROR. Users can then specify the minimum severity level of events that should be persisted at runtime. When events are logged from a very low level – such as DEBUG – upwards, log files can grow large very quickly.

Challenge #1: Reproducing a Bug based on Gigabytes of Log Data

As mentioned above, detailed log files can carry huge amounts of data about the runtime flow of a program. When a bug is reported by a user, log files are often the sole source of information to diagnose it. But when there are gigabytes of historical log data to analyze, this can become a challenge. Sifting through such a huge amount of textual data manually is tedious. When log files from different subsystems have to be correlated, the task becomes even more time-consuming. Apart from that, issues reported by non-technical end users generally do not include sufficient detail to reproduce an issue. In such cases, developers have to map high-level events expressed in the language of the user's business to technical events. These are some of the main reasons why diagnosing bugs using log files is one of the most challenging tasks for software developers.

Challenge #2: Extracting Business Metrics from Log Entries

Of course, more than just diagnostic information can be collected using log files. Logging is also commonly used for recording business metrics. As an example, consider the owner of a SaaS product who is interested in improving her signup workflow. To that end, she wants to determine the proportion of signups that are aborted by users to signups that actually go through to completion. Of course, it is easy to find completed signups from logs. It is more challenging, however, to quantify aborted signup attempts, since those can have various technical reasons or can simply be abandoned by users.
Extracting all signups that have not gone through from log data means that the developer has to imagine all log entries that imply an abort. Since logging, in the sense of stored execution traces, is first and foremost done to help with the creation and maintenance of software, it is likely that the log files are incomplete in regard to business metrics. This results in inaccurate business metrics which moreover are collected through a very time-consuming and as a consequence costly manual process.

Start Monitoring High-Level Events

Recently, technologies complementary to logging that can help to perform tasks and reach goals such as the ones described above have become available. One of those technologies is high-level event monitoring. Its core idea is to raise the abstraction of logged data from low-level technical events to business events. In contrast to normal log messages, which typically consist of little but a timestamped message, event monitoring allows for including structured data in event messages. An event may consist of a category, a subject, a body, tags and properties. This built-in structure makes processing, filtering and analysis of business information easier and faster, for people as well as business intelligence software.

Lower Granularity, More Context Data

High-level event monitoring also differs from software tracing with regard to granularity. High-level events occur at a much lower rate than log messages since they represent business events rather than mere technical details – for instance, a delivery being fulfilled rather than a file not being found.

Ideally, a stream of business events is understandable to people unfamiliar with the implementation details of a system. A key aspect in this regard is that a business event includes context information, like an order number or a user ID. This context information comes in handy, when for example a customer reports an issue with an order: the support staff can reproduce what has happened by simply filtering events by the order number of this particular order.

Challenges in a World of Distributed Systems

Another core concept of high-level monitoring is owed to the fact that more and more software systems are distributed. As a result the demand for the aforementioned correlation of multiple logging sources is becoming increasingly important. This challenge is mastered by introducing a central server component which collects, processes and visualizes high-level events.

At Xaidat, we are building Caduceus, a technology-agnostic and lightweight application monitoring platform. If you want to see high-level event monitoring in action, try Caduceus.

Thursday, February 21, 2013

How to handle not authenticated Ajax requests with a web authentication service

Whether your are a software developer in an internal IT department or a programmer in a small software development shop - new applications primarily target the web. A couple of weeks ago you finished a custom CRM web site. While creating your second web application - a warehouse reporting system - you soon will find that there are some commonalities between those apps.

One of those commonalities is authentication and authorisation. Nearly every web application needs that - it's a so called cross cutting concern. In times of service oriented architectures (SOA) and obeying good software engineering practices like DRY, you came up with the idea of writing your own authentication service. And you already have a name for it: Simple Authentication Service (SAS).

Hey, this is a great idea. And if Google does that, you will be able to pull that off too. Weather you like it or not: if you log in to GMail, you will be authorized to access other Google services like Google Drive, Google Calendar and Google Contacts too. As depicted in the screenshot below, these applications are just a mouse click away.



Advantages of a central authentication service

At Xaidat we develop various web applications and decided to roll out our own central authentication service as well. We believe in numerous advantages of a central authentication service:
  • Authentication code is written once - and used everywhere
  • Bug fixing and new feature development is done in one single place
  • User interface components like a 'log in' and 'Forgot my password' page are shared amongst applications
  • Users sign in to one application and are authenticated to other web applications automatically 
  • Users do not have to remember multiple accounts

The basic architecture of a form based authentication service

There exist several authentication types in web application security:
  • HTTP Basic Authentication
  • HTTP Digest Authentication
  • HTTPS Client Authentication
  • Form Based Authentication
All of those authentication types have pros and cons. However, in this article we focus on Form Based Authentication. Regardless of the concrete server-side technology, be it Java, .NET or even PHP, basically you want to implement something like this:
Form Based Authentication means that when a user successfully logged in, a session identifier is stored as a cookie in the user's browser. As long as this cookie is valid, each HTTP request to the same URL the cookie originated from is signed with this auth-cookie. We won't go into detail how to process this auth-cookie on the server. Every modern web application environment should support Form Based Authentication in some way.

If the Form Based Authentication mechanism recognizes a not authenticated user, the user should be forwarded to a log in page. To give an example, say an HTTP request approaches for the URL http://www.yourapp.com/admin. The sent auth-cookie is either missing or no longer valid (e.g. due to a session timeout). Consequently the server won't respond with the requested resource, but will sent an HTTP redirect with status code 302 and a response header named location pointing to http://sas.yourcompany.com/login. The users browser recognizes HTTP status code 302 and will transparently redirect the user to http://sas.yourcompany.com/login. The user enters his credentials, hits the submit button and a HTTP request is sent to your SAS service. The SAS service then processes the authentication process. If the authentication was successful, SAS responds with HTTP 302 with the response header 'location' set to the initially requested URL, namely http://www.yourapp.com/admin. Here is screenshot of Firebug showing the HTTP redirection.



Pro Tip: if you are in a Java shop and feel comfortable with Spring, we recommend using Spring MVC in conjunction with Spring Security. Spring Security is a well established security framework heavily used in the industry. It allows to decorate Spring MVC Controller methods with authentication and authorisation annotations. Moreover a central configuration file allows to define general security constraints for the URLs of your web application.

Authentication of Ajax requests

You implemented your own SAS and already integrated it in two web applications. Developing SAS was an upfront investment but it will save you precious development time in future projects. With SAS in your toolbox, you can now concentrate on more fancy stuff, i.e. adding some cool on-page interactivity stuff. There Ajax is the name of the game and with the widely used jQuery framework this should be a breeze. You've even implemented long-polling so that events trickle in the web application as they happen - without requiring the user to refresh the browser. But one day your boss will approach you saying "I was able to do stuff on your web application although I was logged out. This seems to be a serious security issue and we need to fix this!" It turns out that your boss had opened your web application in separate tabs in the same browser. He logged out in the first tab and came back to the second tab. While the session is set invalid, your boss was not redirected to the log in page.

You think this is an easy one: the client-side code in the browser has to be slightly adapted. You add a global jQuery ajaxComplete handler which is checking for HTTP 302 and in case redirects the browser to the log in page. At least numerous posts on stackoverflow, likes this one, tell you to do so.

But it just doesn't work. You've already wasted several hours in Firebug analyzing the HTTP traffic. You even started to debug jQuery to find out why the HTTP 302 response is not executed by the browser.



Congratulations, you've fallen into the 'same origin policy'-trap. Because your application is hosted on http://www.yourapp.com/admin and your SAS runs on http://sas.yourcompany.com, the XmlHttpRequest will not process redirects. See this piece of the official W3C specification:
Two origins are said to be the same origin if the following algorithm returns true:

  1. Let A be the first origin being compared, and B be the second origin being compared.
  2. If A and B are both opaque identifiers, and their value is equal, then return true.
  3. Otherwise, if either A or B or both are opaque identifiers, return false.
  4. If A and B have scheme components that are not identical, return false.
  5. If A and B have host components that are not identical, return false.
  6. If A and B have port components that are not identical, return false.
  7. If either A or B have additional data, but that data is not identical for both, return false.
  8. Return true.

 

Authentication of Ajax requests

To handle authentication of Ajax requests across origins, both server and client-side code has to be modified.

The server-side

On the server-side Ajax requests need to be handled separately. Ajax requests are recognizable by a special request-header with the name X-Requested-With set to the value XMLHttpRequest. If this header is detected on server-side, the server sends a response with a custom, not standardized HTTP status code, say 333. In addition a response-header is attached (e.g. X-Location) which holds the referer request-header. Xaidat's authentication service uses Spring Security. Here is an exemplary code snippet of the implemented AuthenticationEntryPoint interface:


The client-side

On the client-side the global jQuery ajaxComplete handler needs to check status code 333. If the status code is detected, the browser's URL is set to the location that comes with the response-header location. Here is an example of the client-side handler.


Xaidat is an Austrian software company focusing on web technologies and has successfully developed numerous web applications, amongst others its own Simple Authentication Service. You would like to implement your own authentication service and need assistance? Feel free to contact us.

Sunday, April 1, 2012

Unwrapping the bunny

On time for the easter holidays our newest member at Xaidat arrived: Zoe our  Karotz rabbit! It took about a week for it to arrive. This is how it unpacks:
Karotz manual
Karotz user manual
Opening the package #1
Opening the package #1
Opening the package #2
Opening the package #2
All the parts included
All parts included
First boot
First boot
Software update
Initial software update
Karotz with custom ears
Our Karotz with custom ears
The initial setup took quite a long time so I guess the firmware version was rather old on our rabbit as the update process took almost 30 minutes. After your new friend is updated you can go to http://www.karotz.com/ and install apps (I guess everything needs apps these days - which is good as I love to customize). The apps come in two flavors and have several options for activations.

Installation

Go to your profile on http://www.karotz.com/, navigate to Appz and one of the category (media, social, news, ..) select the app you want and click install - it installs on your registered device(s) (don't know the exact procedure if you have multiple rabbits). After a few seconds you can watch the rabbit updates itself (led flashes orange) and as soon as the led is turning green again the installation is ready to use.
If you want to uninstall the app navigate to your device in your profile look for the app and click the red X to delete the app from your device.

Local and remote apps

Your device has 256MB internal storage which is available to install local apps to. Local apps as the name suggests are living on your device and once activated run on your device either interacting with the device (ears, led, speaker, camera, rfid, external storage, serial port) or web via HTTP calls.

Remote apps are applications that reside on your own server (e.g. PHP program). The 'installation' procedure is the same as for local apps but they work differently: Once activated the device triggers an HTTP callback providing a unique session-id. Your application can then issue commands to the device using this session-id which has a natural timeout of 15 minutes.

Activation

Apps on your device are not active all the time rather than triggered by various events:


Time scheduler

You can program an installed app to be activated at a specific time of the day per day e.g. having your rabbit tell you the news and weather forecast during breakfast each morning.


Periodically

Have your rabbit activate an app periodically (from 1 minute to every 3 hours) e.g. read the news every 3 hours or let it check your emails every 10 minutes.


Manually

You can also assign one of your included 'Flat Nanoz' (RFID tags) to trigger the app. Once assigned just hold the tag to the nose of your rabbit and the app is started.

Advice

One thing that's not obvious but rather intuitive: To initially register the flat nanoz with your profile/device just hold them to your rabbit's nose. It will tell you that it does not recognize the tag as yours and it is not assigned to any application. After that the tag shows up in your web profile and you can assign it to any application.

Next time I will provide some feedback about programming the rabbit giving it some live. In the meantime Zoe tells its mood every now and then and greets us with forecast of the day in the morning.

If you own a rabbit yourself or have any questions feel free to drop a comment - I'd be glad if I can answer your question.

Wednesday, March 28, 2012

Why and what

Well, what should one say in his very first blog post ever?
Let me introduce myself to you:
I am a 30+ year old software engineer who loves writing software from the bottom of my heart. At the age of 9 I got my first programming book (a BASIC book) at some event when we're visiting my grandparents. I couldn't wait until we would get home to try out my first lines of code so I wrote my first program on a table napkin. The program was very simple, read in two numbers and calculated the area of a rectangle with the input side lengths (I just learned how to do that manually in elementary school).
Since then I write software. Most of the things I learned by reading books and later the internet and eventually deepened my knowledge in classes on the university.

Since 2001 I run a company named Xaidat that does focus on consulting services and individual software engineering. Recently we started to work on a few projects we eventually want to publish as services - more on that later, stay tuned.

Why did I start a/this blog? That's simple - maybe you're a software developer yourself and maybe that did already happen to you: You're in the middle of some task, you just want to add a little bit of something to your program (maybe using a (new) library for the first time) and two hours later you're getting angry/exhausted/frustrated/bored because it just doesn't work! Either you're too stupid, your karma has a bad spin or the whole world is against you, anyway - you can't get this simple thing working!
I thought I want to try to compile such headaches into blog posts (providing a solution) so others may get help when stuck with a similar problem.

We're mostly a Java shop but expect other languages as well as we're not so much into one language than into engineering as such.