Posts Tagged ‘rx’

22
Jan
2011

Windows Phone 7 Analytics with Mixpanel

by David Wynne

Having tried out the Microsoft’s WP7 analytics partner solution, PreEmptive, I was left underwhelmed by the tooling, UI and speed of reporting.  I like Google Analytics, but getting that working looked like a fair bit of inventive hackery and involves referencing the Silverlight Analytics Framework and who needs “yet another dll”™ in their app?  I’d also heard a few reports that the Google Analytics approach was pretty slow.  So inspired by Nick Gravelyn I thought I’d give Mixpanel a shot.

The beauty of the Mixpanel’s RESTful API is in its simplicity – there’s one method and practically everything you need to know about it is contained on this one page.  Each call logs an event and each event can have a collection of properties.  For example we log a “launch” event when our application starts up with the following properties: istrial, version, locale.  You don’t have to predefine any events or properties – just send them.

When you send an event, there are 2 properties you’re always going to need: token and distinct_id.  Token is the token Mixpanel generates for you when you create a project on their site and distinct_id is an arbitrary string you provide to define what makes a user unique.  On Windows Phone it makes sense to use the DeviceUniqueId from DeviceExtendedProperties.  This is returned as a byte array, so you’ll need to Base64 encode it to use as the distinct_id.

Finally Mixpanel wants your event object serialized into JSON (for which we can use Json.Net) and then Base64 encoded into a string.

Our TrackingEvent class inherits from Dictionary<string, object> to embody the name-value-pair nature of an event’s properties and encapsulates all of the serializing and encoding behaviour into a GetData method.  It looks a little something like this:

public class TrackingEvent : Dictionary<string, object>
{
    private const string DistinctIdProperty = "distinct_id";

    // TODO: Your Mixpanel token goes here
    private const string MixpanelToken = "";

    private const string TokenProperty = "token";

    private readonly string eventName;

    public TrackingEvent(string eventName)
    {
        this.eventName = eventName;
    }

    public string GetData()
    {
        if (!this.ContainsKey(TokenProperty))
        {
            this.Add(TokenProperty, MixpanelToken);
        }

        if (!this.ContainsKey(DistinctIdProperty))
        {
            this.Add(DistinctIdProperty, GetDeviceUniqueId());
        }

        JProperty[] properties =
            this.Select(keyValuePair => new JProperty(keyValuePair.Key, keyValuePair.Value.ToString())).ToArray();

        var json = new JObject(
            new JProperty("event", this.eventName), new JProperty("properties", new JObject(properties)));

        return Convert.ToBase64String(Encoding.UTF8.GetBytes(json.ToString()));
    }

    private static string GetDeviceUniqueId()
    {
        object deviceUniqueId;
        return DeviceExtendedProperties.TryGetValue("DeviceUniqueId", out deviceUniqueId)
                   ? Convert.ToBase64String((byte[])deviceUniqueId)
                   : "anon";
    }
}

Next we need to actually send the HTTP request – for this we use the always excellent Reactive Extensions (Rx) which means we can easily make the call asynchronously using the thread pool and process the response in a terse and elegant manner.

For the purpose of this example, we’ll demonstrate this via a static Track() method and then explain what’s happening:

public static class Analytics
{
    public static void Track(TrackingEvent trackingEvent)
    {
        var uriBuilder = new UriBuilder("http://api.mixpanel.com/track")
            {
               Query = string.Format(CultureInfo.InvariantCulture, "data={0}", trackingEvent.GetData()) 
            };

        WebRequest webRequest = WebRequest.Create(uriBuilder.Uri);

        Observable.FromAsyncPattern<WebResponse>
            (webRequest.BeginGetResponse, webRequest.EndGetResponse)()
                .SubscribeOn(Scheduler.ThreadPool)
                .Select(GetResponse)
                .Subscribe(
                    response => Debug.WriteLine("Response: {0}", response), 
                    exception => Debug.WriteLine("Error: {0}", exception.Message));
    }

    private static string GetResponse(WebResponse webResponse)
    {
        if (webResponse.ContentLength > 0)
        {
            using (var streamReader = new StreamReader(webResponse.GetResponseStream()))
            {
                return streamReader.ReadToEnd();
            }
        }

        return string.Empty;
    }
}

If  you’re not familiar with Rx the FromAsyncPattern call might look a bit daunting, but it’s incredibly elegant.  It wraps the asynchronous Begin/End pattern and produces an IObservable which you can subscribe to.  Because it’s an IObservable we can instruct Rx to execute the subscription on the thread pool.  Next we use a Select to project the WebResponse returned into a string via the GetResponse() method and then subscribe to the result.

Mixpanel simply returns a 1 or a 0 to tell you whether your request was logged, so day-to-day you don’t really care about the response, but during development it’s handy to see what’s coming back.  It’s worth noting that in my discussions with Mixpanel the 1 or 0 is really just an indication of whether they managed to deserialize your JSON (at time of writing), so it’s possible you could get a 1 back but still not get data logged because you forgot to set your token property.  Luckily Mixpanel stats are “real time” – so it’s easy to check that you’re data’s getting through.

Finally we just make a call to our Track method in our codebase whenever we want to track an event:

Analytics.Track(
    new TrackingEvent("launch")
        {
            { "istrial", new LicenseInformation().IsTrial() },
            { "locale", Thread.CurrentThread.CurrentUICulture.Name },
        });

Be aware that some values you might want to track, such as IsTrial, have overhead to obtain and should ideally be done once per session and stored, but you get the idea.  It’s probably also worth thinking about disabling tracking when you’re in debug/developing to save wasting data points or skewing your production figures.

It’s early days with Mixpanel, but so far we’re liking what we see.  If you’re planning to try Mixpanel and found this useful then feel free to signup via this referral link and we’ll both get an extra 5,000 data points and this delightful carriage clock… http://mixpanel.com/user/register/700134331/ (clock not included).

3
Dec
2010

Watching Silverlight Dependency Properties with Reactive Extensions

by Stuart Harris

At yesterday’s Sliverlight Firestarter, Scott announced that Silverlight 5 will have a DataContextChanged event.  Great news!  How often have you wanted to grab the view model in the code behind and been frustrated by the fact that in Silverlight (unlike WPF) you can’t be easily notified when you have a new view model – you can’t even add your own handler by overriding the DataContext property’s metadata.

So we will wait patiently for Silverlight 5 (and all its other goodness – I was very excited by the 3D demo).  But in the meantime we could use something like Prism’s DependencyPropertyListener or BindingListener.  The former uses the traditional approach of using an attached property (with your own handler) to bind to the dependency property in question.  You have to create a binding, attach and detach it in the right place and hook onto (and off) the listener’s Changed event.  Quite a bit of plumbing.  Prism’s BindingListener sits on top of this and allows you to supply a handler and deal directly with elements and bindings.  All very useful.

But when I want the DataContext, or I just want to know when a dependency property’s value has changed, I really don’t want to dig out a pattern from the recesses of my mind and write a ton of code (which is likely wrong first time) just to be notified when something changes.  It’s gotta be one line of code!  Like this:

this.GetChanges(new Binding()).Subscribe(this.DataContextChanged);

Or if I want to know when the Width of a Canvas changes:

this.GetChanges(new Binding("Width") { Source = this.canvas })    
    .Subscribe(args => Debug.WriteLine(args.NewValue));

Obviously I can create any binding I want and pass it to GetChanges(), which is a simple extension method on FrameworkElement that returns an IObservable of ValueChangedEventArgs.  I can subscribe to this with a handler that will be called each time the binding’s value changes.  The extension method looks like this:

public static IObservable<ValueChangedEventArgs> GetChanges(
    this FrameworkElement element, Binding binding)
{
    return Observable.CreateWithDisposable<ValueChangedEventArgs>(
        observer =>
            {
                var listener = new DependencyPropertyListener();
                return Observable.FromEvent<ValueChangedEventArgs>(
                    handler =>
                        {
                            listener.ValueChanged += handler;
                            listener.Attach(element, binding);
                        }, 
                    handler =>
                        {
                            listener.ValueChanged -= handler;
                            listener.Detach();
                        }).Select(@event => @event.EventArgs).Subscribe(observer);
            });
}

So this is the DependencyPropertyListener that was adopted from Prism:

public class DependencyPropertyListener
{
    private readonly DependencyProperty dependencyProperty;

    private FrameworkElement targetElement;

    public DependencyPropertyListener()
    {
        this.dependencyProperty = DependencyProperty.RegisterAttached(
            Guid.NewGuid().ToString(), 
            typeof(object), 
            typeof(DependencyPropertyListener), 
            new PropertyMetadata(null, this.OnValueChanged));
    }

    public event EventHandler<ValueChangedEventArgs> ValueChanged;

    public void Attach(FrameworkElement target, Binding binding)
    {
        if (target == null)
        {
            throw new ArgumentNullException("target");
        }

        if (binding == null)
        {
            throw new ArgumentNullException("binding");
        }

        this.Detach();
        this.targetElement = target;
        this.targetElement.SetBinding(this.dependencyProperty, binding);
    }

    public void Detach()
    {
        if (this.targetElement != null)
        {
            this.targetElement.ClearValue(this.dependencyProperty);
            this.targetElement = null;
        }
    }

    private void OnValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        EventHandler<ValueChangedEventArgs> handler = this.ValueChanged;
        if (handler != null)
        {
            handler(this, new ValueChangedEventArgs(e.OldValue, e.NewValue));
        }
    }
}

Presumably the System.Windows.DependencyPropertyChangedEventArgs is not derived from EventArgs because it’s a struct for performance reasons.  It’s up to you whether you use that or create your own EventArgs like this:

public class ValueChangedEventArgs : EventArgs
{
    private readonly object newValue;

    private readonly object oldValue;

    public ValueChangedEventArgs(object oldValue, object newValue)
    {
        this.oldValue = oldValue;
        this.newValue = newValue;
    }

    public object NewValue
    {
        get
        {
            return this.newValue;
        }
    }

    public object OldValue
    {
        get
        {
            return this.oldValue;
        }
    }
}

Binding to the Windows Phone 7 Application Bar

The Application Bar in Windows Phone 7 (and its buttons and menu items) are not derived from DependencyObject and so can’t easily participate in data binding.  Using Silverlight 3 behaviours, we can attach functionality to them, however, including bindings for ICommands (with parameters), Text and Icons.

<phone:PhoneApplicationPage.ApplicationBar>
    <shell:ApplicationBar IsVisible="True"
                          IsMenuEnabled="True">
        <shell:ApplicationBarIconButton IconUri="/Images/appbar.add.rest.png"
                                        Text="Add" />
        <shell:ApplicationBarIconButton IconUri="/Images/appbar.delete.rest.png"
                                        Text="Delete" />
        <shell:ApplicationBar.MenuItems>
            <shell:ApplicationBarMenuItem Text="MenuItem 1" />
            <shell:ApplicationBarMenuItem Text="MenuItem 2" />
        </shell:ApplicationBar.MenuItems>
    </shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>

<i:Interaction.Behaviors>
    <Behaviors:ApplicationBarIconButtonCommand TextKey="Add"
                                               CommandBinding="{Binding Path=AddCommand}"
                                               TextBinding="{Binding Source={StaticResource LocalizedStrings}, Path=LocalizedResources.Add}"
                                               IconBinding="{Binding Path=AddIcon}" />
    <Behaviors:ApplicationBarIconButtonCommand TextKey="Delete"
                                               CommandBinding="{Binding Path=DeleteCommand}"
                                               TextBinding="{Binding Source={StaticResource LocalizedStrings}, Path=LocalizedResources.Delete}" />
</i:Interaction.Behaviors>

I’ve attached a sample project that demonstrates binding to the Application Bar buttons.  There are behaviours for binding Prism’s DelegateCommand to the app bar buttons (and menu items) and to regular buttons and other FrameworkElements.  I haven’t included the full Prism source (just the bits needed to run the sample).  Also there is no IoC container so the MainViewModel is instantiated in App.xaml for this.

Enjoy!

Source Code (Visual Studio 2010 sample solution, built against Build 2787 of Reactive Extensions for WP7):

AppBarBinding.zip (44.42 kb)

1
Sep
2010

XPF and Reactive Extensions for .Net (Rx)

by David Wynne

Update 2010-09-20: As of Build 19 XPF uses version 1.0.2698.104 of Rx as the problem referred to below has been addressed.

image XPF uses Reactive Extensions for .Net (Rx) internally to handle user input and eventing.  If you’re developing on Windows Phone 7 everything will work just fine, Rx comes with the Phone assemblies.  If you’re working on the desktop, you’ll need to install Rx in order to use XPF in your solution.

As of Build 6, XPF uses version 1.0.2617.0 of Rx which is the latest “but one” release of Rx.  The latest build of Rx (1.0.2677.0) indirectly takes a dependency on System.Web which isn’t in the .Net 4.0 Client Profile.  If we were to use to that version it would require all Windows XNA applications built with XPF to target the full .Net 4.0 profile, which is not the default for XNA applications.

It looks like this maybe addressed in a future version of Rx, so we’ll move to the latest version as soon as this problem is addressed by the Rx team.

For now, to avoid confusion you’ll need to make sure you have version 1.0.2617.0 for .Net 4 of Rx installed (multiple versions can be installed side-by-side).  You can download it from the Rx Team Blog, or by using this direct link: http://download.microsoft.com/download/F/6/4/F64CA331-075C-4A2F-BD28-7161D765A0E8/Rx_Net4.msi

Thanks to @fahadsuhaib for pointing out we were using an older version in Build 5.