Just-Eat spectrum-bottom spectrum-top facebook google-plus instagram linkedIn pinterest reddit rss twitter_like twitter_reply twitter_share twitter_veriviedtwitter vimeo whatsapp youtube error_filled error file info-filled info loading star tick arrow arrowLeft arrowRight close download minus-filled minus move play plus-filled plus searchIcon settings

Tag : Open Source

1003 views

iOS Event tracking with JustTrack

Overview

At Just Eat, tracking events is a fundamental part of our business analysis and the information we collect informs our technical and strategic decisions. To collect the information required we needed a flexible, future-proof and easy to use tracking system that enables us to add, remove and swap the underlying integrations with analytical systems and services with minimal impact on our applications’ code. We also wanted to solve the problem of keeping the required event metadata up-to-date whenever the requirements change.

JustTrack is the event tracking solution we built for that and it’s available open source on Github at //github.com/justeat/JustTrack.

Examples and documentation are available in the Github repository Readme.

Main features

  • Events are declared in a .plist file and Swift 3 code is automatically generated at build time from it.
  • Events can be sent to multiple destinations (called Trackers) at the same time.
  • Custom Trackers are easy to create and use.

Events Definition

One of the problems we found with existing solutions is that the events are declared in code and therefore can only be maintained by developers. Similarly, existing solutions offer very generic tracking facilities for developers. Because of that, whenever the required metadata associated with an event changes for any reason, the developer has to search the code base and update all instances of the event with the correct implementation. This, of course, is a very fragile process and is prone to errors.

JustTrack solves these problems by declaring events in a plist file that is used to automatically generate equivalent definitions of the events in Swift that can be used in the app. This provides several benefits:

  • Each event is uniquely identified.
  • The metadata associated with each event is type checked.
  • When the requirements for an event change, the developers can see it through build errors and warnings that will naturally occur.
  • Plists can be edited as XML, which means anybody in the business can edit them.
  • It’s easy to search for events that are no longer used and deleted events won’t compile.

An Event is made of:

  • Name: the unique identifier
  • Registered Trackers: List of event destinations (e.g. Google Analytics)
  • Payload: The metadata associated with the event (at this time only String key-value pairs are supported)

Trackers

Another problem we found with existing solutions is that, generally speaking, all the events need to be tracked with the same Trackers. The developer doesn’t have any freedom to decide which event goes to which Tracker, and several solutions only support specific tracking technologies (such as GA, Firebase, and so on)

JustTrack solves this problem by allowing the developer to specify the “registered” trackers for each event and to create custom trackers.

A Tracker is an object implementing the JETracker protocol and is loaded using: tracker.loadCustomTracker( ... ) function. You can implement any tracker you want and JustTrack provides a few default trackers:

  • JETrackerConsole – print events to the system’s console
  • JEFacebookTraker (not yet implemented)
  • JEGoogleAnalyticsTraker (not yet implemented, Google’s pods can’t be used as a dependency in a pod)
  • JETrakerFirebase (not yet implemented, Google’s pods can’t be used as a dependency in a pod)

Conclusions

Using JustTrack you can easily track your app’s events to multiple destinations, having all the necessaire flexibility, intrinsic events documentation and all the expandability you will ever need in future, all of that writing the minimum amount of code possible.

About the author

Federico Cappelli is a Senior iOS Engineer and iOS COG Leader at Just Eat.

1464 views

A better local and remote logging on iOS with JustLog

just_log_banner

In this blog post we introduce the solution for local and remote logging we developed for the Just Eat iOS app. It’s named JustLog and it’s available open source on Github at github.com/justeat/JustLog.

Overview

At Just Eat, logging and monitoring are fundamental parts of our job as engineers. Whether you are a back-end engineer or a front-end one, you’ll often find yourself in the situation where understanding how your software behaves in production is important, if not critical. The ELK stack for real-time logging has gained great adoption over recent years, mainly in the back-end world where multiple microservices often interact with each other.

In the mobile world, the common approach to investigating issues is gathering logs from devices or trying to reproduce the issue by following a sequence of reported steps. Mobile developers are mostly familiar with tools such as Google Analytics or Fabric.io but they are tracking systems, not fully fledged logging solutions.

We believe tracking is different in nature from logging and that mobile apps should take advantage of ELK too in order to take their monitoring and analysis to another level. Remote logging the right set of information could provide valuable information that would be difficult to gather otherwise, unveil unexpected behaviors and bugs, and even if the data was properly anonymized, identify the sequences of actions of singular users.

JustLog takes logging on iOS to the next level. It supports console, file and remote Logstash logging via TCP socket out of the box. You can also setup JustLog to use logz.io with no effort. JustLog relies on CocoaAsyncSocket and SwiftyBeaver, exposes a simple swifty API but it also plays just fine with Objective-C.

JustLog sets the focus on remote logging, but fully covers the basic needs of local console and file logging.

Usage

JustLog, is available through CocoaPods. To install it, simply add the following line to your Podfile:

Import it into your files like so:

This logging system strongly relies on SwiftyBeaver.
We decided to adopt SwiftyBeaver due to the following reasons:

  • good and extensible design
  • ability to upload logs to the cloud
  • macOS app to analyze logs

A log can be of one of 5 different types, to be used according to the specific need. A reasonable adopted convention on mobile could be the following:

  • 📣 verbose: Use to trace the code, trying to find one part of a function specifically, sort of debuggin with extensive information.
  • 📝 debug: Information that is diagnostically helpful to developers to diagnose an issue.
  • ℹ️ info: Generally useful information to log (service start/stop, configuration assumptions, etc). Info to always have available but usually don’t care about under normal circumstances. Out-of-the-box config level.
  • ⚠️ warning: Anything that can potentially cause application oddities but an automatic recovery is possible (such as retrying an operation, missing data, etc.)
  • ☠️ error: Any error which is fatal to the operation, but not the service or application (can’t open a required file, missing data, etc.). These errors will force user intervention. These are usually reserved for failed API calls, missing services, etc.

When using JustLog, the only object to interact with is the shared instance of the Logger class, which supports 3 destinations:

  • sync writing to Console (custom destination)
  • sync writing to File (custom destination)
  • async sending logs to Logstash (usually part of an ELK stack)

Following is a code sample to configure and setup the Logger. It should be done at app startup time, in the applicationDidFinishLaunchingWithOptions method in the AppDelegate.

The defaultUserInfo dictionary contains a set of basic information to add to every log.

The Logger class exposes 5 functions for the different types of logs. The only required parameter is the message, optional error and userInfo can be provided. Here are some examples of sending logs to JustLog:

It plays nicely with Objective-C too:

The message is the only required argument for each log type, while userInfo and error are optional.
The Logger unifies the information from message, error, error.userInfo, userInfo, defaultUserInfo and call-site info/metadata in a single dictionary with the following schema form of type [String : Any] (we call this ‘aggregated form’). E.g. in JSON representation:

All destinations (console, file, logstash) are enabled by default but they can be disabled at configuration time like so:

The above 5 logs are treated and showed differently on the each destination:

Console

The console prints only the message.

console

File

On file we store all the log info in the ‘aggregated form’.

Logstash

Before sending a log to Logstash, the ‘aggregated form’ is flattened to a simpler [String : Any] dictionary, easily understood by Logstash and handy to be displayed on Kibana. E.g. in JSON representation:

Which would be shown in Kibana as follows:

kibana

A note on Logstash destination

The logstash destination is configured via properties exposed by the Logger. E.g.:

When the logLogstashSocketActivity is set to true, socket activity is printed to the console:

socket_activity

This destination is the only asynchronous destination that comes with JustLog. This means that logs to Logstash are batched and sent at some point in future when the timer fires. The logstashTimeout property can be set to the number of seconds for the dispatch.
In some cases, it might be important to dispatch the logs immediately after an event occurs like so:

or, more generally, in the applicationDidEnterBackground and applicationWillTerminate methods in the AppDelegate like so:

Sending logs to logz.io

JustLog supports sending logs to logz.io.

At the time of writing, logz.io uses the following host and port (please refer to the official documentation):

When configuring the Logger (before calling setup()), simply set the token like so:

Conclusion

JustLog aims to be an easy-to-use working solution with minimal setup. It covers the most basic logging needs (console and file logging) via the great foundations given by SwiftBeaver, but also provides an advanced remote logging solution for Logstash (which is usually paired with Elasticsearch and Kibana in an ELK stack). JustLog integrates with logz.io, one of the most widely used ELK SaaS, placing itself as the only solution in the market (at the time of writing) to leverage such stack on iOS.

We hope this library will ease the process of setting up the logging for your team and help you find solutions to the issues you didn’t know you had.

About the author

Alberto De Bortoli is the Principal iOS Engineer at Just Eat.

1130 views

Introducing JustPeek

JustPeek Banner

An iOS framework that ports Force-Touch Peek/Pop-like interactions to devices that aren’t force-touch enabled

At Just Eat, teams tend to build software with the community in mind. Over time, Just Eat has published several Open Source projects and has been an important pillar to the C# community.

More recently, the Company has grown its iOS team in London to focus on improving the Just Eat app for the UK market. With this growth phase, I had the opportunity to join the team for some time.

As part of the effort to improve our app, launch the new Just Eat brand and build modules to help us in the long run, we’re building and open sourcing more iOS projects than ever before. JustPeek, is the first of them to get published.

JustPeek is an iOS library that adds support for Force Touch-like Peek / Pop interactions on devices that don’t natively support it due to lack of force recognition capability in the screen. Under the hood it uses the native implementation if available, otherwise a custom implementation based on UILongPressGestureRecognizer. It fallbacks to the latter also on the iOS Simulator if needed.

Unlike similar libraries already available on the web, JustPeek tries to mimic entirely the original implementation. It doesn’t simply use screenshots to display a preview, but previews the UIViewController itself. As of version 0.2.0, it also supports committing to a preview in the fallback implementation. As there’s no way to measure pressure on old devices, committing happens when a user keeps the preview open for more than a certain amount of time – 3 seconds at the time of writing.

Here’s how you use JustPeek:

Here’s what it looks like in the demo application we ship with the code, as run on the iOS Simulator:

JustPeek Demo

We use JustPeek in the Just Eat UK app, in the list of results you get when searching for restaurants that serve your area, to show a preview of popular dishes a restaurant has to offer.

JustPeek is now publicly available on GitHub and can be added to your projects using CocoaPods. We really hope you’ll like it!

About the author

Gianluca Tranchedone is a Senior iOS Engineer and, at the time of writing, the main contributor of JustPeek.

503 views

OpenSourced: JustFakeIt

Introducing JustFakeIt. A Http Mocking Library

JustFakeIt is designed to help you write better tests by mocking away any 3rd party HTTP services your application might depend on.  JustFakeIt does this by acting as a HTTP server which is hosted within your unit test process and which you can specify mock endpoints and responses against. Because it’s hosted In Process, it’s really fast and takes very little effort to use.

Why would I want to use this?

We’re used to writing tests that mock HTTP clients, like the really basic test below which mocks a CustomerApiClient

The problem with tests like these are that by mocking away the CustomerApiClient, we don’t actually test it.  What about the logic that goes on inside the client? Typically we might write a suite of integration tests against the CustomerApiClient, but integration tests take a fair amount of time and effort to write compared to a unit test, and we might not cover our core usage scenarios (integration tests against external dependencies are usually very isolated) JustFakeIt helps in this situation by allowing us to write a unit test that covers the whole of the API client.

Tests like this are still expensive to write, however we do get 2 big benefits

  1. our tests covers the whole of the API client, including any logic and dependencies within the client itself
  2. we can easily adapt the test to run against the actual API, by injecting a real URL into the client, and thus reuse it as an integration test

Teams at JUST EAT don’t write all of their tests using JustFakeIt, that’d be overkill! Most teams use JustFakeIt when writing bigger outside-in tests, or when writing SDKs for their own internal APIs, and that’s where we’ve JustFakeIt to have the biggest benefit.

Downloads

Source code is available on GitHub here: //github.com/justeat/JustFakeIt NuGet packages available here: //www.nuget.org/packages/justfakeit

682 views

OpenSourced: OpenRasta Middleware

OpenRasta meet OWIN

We are at it again. Previously we brought you OpenRastaSwagger allow you to have shiny documentation for your APIs. Now we wanted to contribute something to the community that would get you excited again as an OpenRasta developer or someone looking for an alternative to the WebAPI world.

Enter OpenRasta.Owin – a Middleware package for the OpenRasta framework allowing you to host your APIs in Katana on the OWIN Specification.

Why have we created this?

Today we’re working in the OpenRasta community which has served us well – after all, we’ve accomplished great things. But as always many minds are always better and, by joining forces with the OWIN Middleware community, we open a whole new world of options to our solution and yours. The Middleware community has exploded recently and will continue to do so with the introduction of vNext, which is hosted on Owin/Katana by default.

nuget.org search: ‘Search for OWIN returned 478 packages’

‘How do I move’ We hear you say.

The move can be as easy as three steps…

  1. Remove your current OpenRasta hosting.

remove AspNet Hosting

  1. Add OpenRasta.Owin hosting Middleware.

Add OpenRasta.Owin

  1. Create the magic Startup.cs with the following code. The key feature that the OpenRasta.Owin package brings you is the UseOpenRasta Middleware extension.

If your project is a little more complicated and you need to specify your own dependency resolver that’s also fine. You can specify the dependency as the second parameter.

I need more from this Package!!

No one is perfect and, despite our best efforts, this package might not meet everyone’s expectations. But don’t worry – there is light at the end of the tunnel. The light is you…. Yes, you can contribute or even fork it and make it your own. Take a look at the licence on GitHub for peace of mind.

Downloads

Source code is available on GitHub here:
//github.com/justeat/openrasta-hosting-owin

NuGet packages available here:
//www.nuget.org/packages/OpenRasta.Owin