Gain Valuable Insights From Web Logs With Device Detection


9/12/2014 11:00 AM

Java Development

Use a few lines of Java and device detection to analyse web logs

The Objective

Analyse user agent strings stored in your log file to:

  • See how many visitors use mobile devices.
  • Gain deeper understanding of your users from over 150 device properties such as physical screen size, input method, and device price.
  • Augment your analytics system with additional information.


This demo uses a pre-formated log file with one user agent string per line. Depending on your log file you may wish to add code that would extract user agents from the log file records. You also need to download a Java distribution of 51Degrees device detector and include the relevant packages in to your project.


The general logic is as follows: Open file and start reading user agents line by line performing detection for each user agent. As mentioned earlier, for this demo we are interested in 'IsMobile', 'PlatformName', 'ScreenInchesDiagonalRounded' and 'LayoutEngine' properties. The console output of this program consists of lists for Layout Engines, OS and Screen Inches Diagonal Rounded with corresponding count values for each entry.

The output we expect to see is similar to this:

Total User Agents: 1000001. Of which 498919 are mobile. ---- Layout Engine ---- - Engine: Lumi used in 32 devices. - Engine: Blink used in 51705 devices. ... - Engine: U3 used in 2636 devices. ---- Platform Name (Operating System) ---- - OS: Windows Phone used in 1304 devices. - OS: Unix used in 12 devices. ... - OS: iOS used in 145068 devices. - OS: BlackBerry OS used in 10191 devices. ---- Screen Sizes In Inches ---- - Screen Size in Inches: 22 observed in 39 devices. - Screen Size in Inches: 46 observed in 7 devices. ... - Screen Size in Inches: 3 observed in 26982 devices. - Screen Size in Inches: 4 observed in 212979 devices.

The important bits in this application are:

//Create Provider object with Lite data file. p = new Provider(); br = new BufferedReader(new FileReader(AGENTS_FILE)); while ((line = br.readLine()) != null) { //Read in next user agent and detect. match = p.match(line); //Incrementing devices read count. count++; //If device is mobile. if(match.getValues("IsMobile").toBool() == true) mobile++; //Process LayoutEngine. temp = match.getValues("LayoutEngine").toString(); processlayoutEngine(temp); //Process Operating System (PlatformName) if possible. if (isPremium) { //Get PlatformName property and process it. temp = match.getValues("PlatformName").toString(); processOperatingSystem(temp); //Get ScreenInchesDiagonalRounded property and process it. temp = match.getValues("ScreenInchesDiagonalRounded").toString(); processScreenInchesDiagonalRounded(temp); } }

In this code we create a new Provider and open file that contains user agents. Then we start reading in user agents line-by-line and for each user agent detection is performed. Count of processed user agents gets incremented and if device is mobile the relevant variable also gets incremented. Then Platform Name, the Layout Engine and ScreenInchesDiagonalRounded get passed no to the relevant functions described below.

/** * Function performs a check for LayoutEngine in LE list. If LayoutEngine * already exists count for that engine gets incremented. Otherwise a new * LayoutEngine is added with count 1. * @param layoutEngineName - string containing LayoutEngine to check. */ public static void processlayoutEngine(String layoutEngineName) { if (layoutEngines.containsKey(layoutEngineName)) { Integer temp = layoutEngines.get(layoutEngineName) + 1; layoutEngines.put(layoutEngineName, temp); } else { Integer initial = 1; layoutEngines.put(layoutEngineName, initial); } }

All functions dealing with processing properties have a similar implementation. The result is stored in the relevant HashMap with String for Key and Integer for count. Arguably this is not the most efficient implementation but it serves the purpose of this demo.

Some device properties like 'PlatformName' and 'ScreenInchesDiagonalRounded' are only available in Enterprise or Premium data files. The code is able to run with both Lite and Premium data. You may want to consider Test-Driving out Enterprise or Premium data files. The only difference when using Premium or Enterprise data is in the way we initialise Provider object:

//If PREMIUM_DATA_FILE not set or empty use default data file. if (PREMIUM_DATA_FILE != null && !PREMIUM_DATA_FILE.isEmpty()) { p = new Provider(StreamFactory.create(PREMIUM_DATA_FILE)); isPremium = true; } else { //Create Provider object with Lite data file. p = new Provider(); }

Try Premium Data