Website change

So today this website is hosted by a new service. The intention was that it would be transparent, but it took a bit of time to remap the domain name to the new host and it resulted in quite few temporary outage.

After many years as a loyal customer to yahoo for the hosting of this website, I switched away because the iOS 9 release is coming and Apple introduced a change to improve the security of interaction between apps and website. It will now require a site with a secure connection (https). Yahoo unfortunately didn’t support https in a way that enabled me to support some of the new features of iOS 9 I intend to leverage.

It is possible to continue to interact with an insecure website from an app by registering an exception, but two main reason led me to make the change:

  1. It’s just the right thing to do. There are a few informations sent from the app to the website when you send a bug report or use google earth, and it’s just better to secure it going forward.
  2. It will allow some interesting interaction between the web and the iOS9 version of the app, where by I could write an explanation of a screen and link it directly to opening the app on your device with the matching report or graph. Given some of the graphs and analysis are a bit involved and I didn’t figure out a nice way to integrate a help on a small screen like the phone, I am hoping this will be quite helpful for people to have more fun with the app.

Note that the secure uploads and the new features I mentioned above will not likely be included in the first version for iOS9, but hopefully shortly after.

 

How to track the non reproducible bug in version 2.1

So, version 2.1 was crashing for quite a few users on startup. Obviously the app wasn’t crashing for me in any of my tests.

First line of defence when crashes happens is to ask the user what they were doing and try to replicate the same action to see if I can recreate the crash. But here they weren’t doing anything it wasn’t starting.

Second is to look for patterns in the crash. The first few users reporting the issue were all using an iPad. There are a few differences between the iPhone and the iPad, mainly that the iPad displays an activity detail at the same time as the activity list. This can result in some difference in logic and makes the startup on iPad marginally more prone to issues. This can lead to hard to reproduce bugs too as it is a function of the type of activity the user would load on startup (the last one downloaded)

Another help is the crash report from apple. In this case, they were very few and reporting crash in location that are not triggered at start up or inside apple libraries. So not helpful to pinpoint the problem.

Some users affected by the issue kindly sent me their activity data so I could try to see if the problem was linked to their specific activities data. It wasn’t, I could start the app with their data fine.

This leaves one other possibility, a thread concurrency issue. This can be really random, and a function of both the speed of the hardware and the exact activities you have. ConnectStats is quite multi-threaded to try to keep the app responsive as many calculations are performed in parallel. So it is possible that some of this parallel activity result in a collision or some instructions run too early (when required data is not ready).

I try to be very careful on collision conditions and to make the code robust to data not being ready. In version 2.1, in order to optimise the startup, I had done a clean up of all the notifications between events in the app to limit them to the minimum needed. So likely the problem was linked to that: issue affecting random users, not a logic issue (users data didn’t let me reproduce it), but the issue was systematic for some users: so this gives another hint. The one issue that can exhibit these symptoms is if you trigger a User Interface event not from the thread dedicated to the UI (main thread).

I did a review of all the events that happen on start up and found one that, in the clean up of 2.1, wasn’t not forcefully directed to that main thread…

So while I couldn’t reproduce, I feel strongly that this must be the issue:

  • linked to some change I made in version 2.1,
  • random: depends of when precisely event get triggered
  • systematic for a given user: for a set of hardware speed and size of data, always happens or not

I submitted a fix for that event issue to apple, let’s cross fingers until version 2.1.1 is approved by apple and hope the issue is indeed resolved. I requested an expedited review, but it’s not always granted.

Frustrations of a botched release

I try to release ConnectStats regularly. Once in a while, as today, I push an update with an issue. I have been receiving a lot of bug reports today from users who can’t start the app after last night release.

I know it’s quite frustrating for users, and it is for me as well. In this case so far it has been impossible for me to reproduce the issue.

So as I try to sort it out, I decided to write a bit about the testing and debugging of ConnectStats

Before the problem happens

Automatted Testing

First I wrote a bunch of tests that verify the very basic functionality of the app at the lowest level. For example it checks that all the unit conversions continue to be correct, that the statistics computation continue as expected, etc, etc

I have also built a testing sister app to ConnectStats that share most of the code, but run a bunch of test replicating the download process, or statistics on saved samples of activities.

Device Testing

While the automated testing is critical, most of the issues, like the one today I suspect are due to subtle interaction between different aspect of the app, when run with different set of activities or different devices.

Given I develop ConnectStats alone in my free time, this kind of testing is fairly limited for me. I mostly test with my phone and my activities, as well as a secondary device. For example I do not use an iPad, so issues on iPad are more likely to appear as I don’t have as much opportunity to try these.

Once a problem happens

Bug Reports

Typically, the first thing that happens is I’ll start receiving some bug report. The bug report contains workflow information and diagnostic collected as the app executes. It’s only as good as what I anticipated to record. But quite a few bug can be understood this way, especially when people email me and answer a few questions about what they were doing or how to reproduce the problem.

Apple Crash Reports

When as today, a large amount of people email me that the app crash on startup it’s much harder, as the log does not contain any useful information. I can also see some crash report collected by apple, but they take a while to appear. So right now I just need to wait and hope that the information in apple’s report will help me.

Bad Reviews

Of course the next thing that happens, is that ConnectStats will start receiving bad reviews. It’s basically a race, fix it before too many bad reviews accumulate…

 

Year to date or Month to date statistics

Version 2.1 of ConnectStats introduces the ability to see year to date or month to date statistics. The yearly cumulative graph was already giving a good idea of how well you were doing this year versus the last, but now you can see the full stats you reached at the same point of last year.

Below for example you can see that in 2015, so far I ran 758km, while on the full year of 2014 I ran 1356km. If you press on the button All, you get to the YTD screen, that shows that in 2014 at the same point in the year as today (August), I had run 913km.

IMG_1664 IMG_1665

In the monthly view, the graph is slightly different, the full month bar is shown, but the blue shows how much for each month was reached at the same point in the month, here around august 15, or about half way through the month.

 

IMG_1666 IMG_1667

Best Rolling Graphs over Time

ConnectStats can now maintain best rolling graph over time. I find it quite interesting to see how one month compare to the other. You access the feature by going to the statistics screen and it’s the graph at the bottom of the summary page.

You can also find information about best rolling plots for an activity here and how to interpret them here

Initial Computation

Computing these graphs can be quite expensive. Every time you do a download, ConnectStats will process a few activities. It requires the full activity details, so only the activities for which you will have looked at the detail screen will be used.

You can force to recalculate older activities by going to the settings, profiles, and select Compute Best for more old Activities. This processes quite a few existing activities. Each time to press it, it will look for activities not already processed.

Interpreting the graphs

Heart Rate

This is the graph showing the best Heart Rate I achieved for any given period of time.
iOS_Simulator_Screen_Shot_8_Aug_2015_09_34_03The arrow 1 below shows the graph for July. You can see here that it was a month for which the best of the year was achieved except for the area pointed out by the arrow 2. The arrow 3 potints to the yellow graph showing that the last year (2014) was not as good as this year, I definitely pushed myself more this year, especially in july, when I completed a half marathon…

If you tap once on the graph it will rotate through the last few months, to show you how you performed then.

 

 

Pace or speed

This is the graph with the best speed or pace I achieve for a given distance. Not the heart rate is for time, not distance as I think it makes more sense.

iOS_Simulator_Screen_Shot_8_Aug_2015_09_34_15
If you pan to the left on the graph it will switch to the best pace or speed. Arrow 1 here shows you that the best speed for the year on most distances was achieved in july. Note that for pace a graph lower is better, but for speed higher is better. Again, if you tap on the graph, it will rotate through the last few months.

 

 

 

ConnectStats version 2.0

ConnectStats 2.0 brings quite a few exciting new features. The major change is that now ConnectStats will start maintaining some measures over time, while until now it really only acted as a cache for the data collected on either Strava or Garmin.

This opens the door to a lot of new features. So I upgraded the version and I celebrated by redesigning the icon…

BestHRThe first data I was really interested in looking at over time, was how the best rolling heart rate graph compared from month to month and year to year. Similar to the best pace. These graphs are not necessarily very common to see,  but I find they are a fascinating way to see how I am performing on a run or over the month. I will dedicate a post soon to these. Some snapshots here

BestPace

CalendarAllThe other feature is an improved calendar view. It now has more control to only show some activities, and a new visual circle to indicate how much each day fared compared to the maximum for the month. The best day is highlighted with by a darker color in the circle.

 

CalendarRun

Upcoming Features for connectstats

Development on ConnectStats has been very slow recently. Mostly because I have started a new app related to Tennis Stats, which I’ll likely release soon. I have a few upcoming features for ConnectStats I still need to wrap up and a few bugs reports to investigate but didn’t get much time to focus unfortunately.

The main feature I have in the back burner for a while is the ability to compute best rolling heart rate or speed profile for current month or year and show that in a summary page. It isn’t working well at the moment, but the summary page is quite useful, so I may just release that alone. The stats tab now by default shows a summary page with key graphs, and of course the old pages can still be accessed.

The other small feature is I finally figured out how to optimise the screen for iPhone 6 and iPhone 6+, so that will be included too. Meanwhile, here is a preview of what the summary page looks like on an iPhone 6 resolution:

SummaryPage

Performance Analysis

In the version 1.20, ConnectStats supports a first version of long term (fitness) versus short term (fatigue) performance analysis. This is a bit rudimentary for now, and hopefully will improve over time.

The performance Index

The analysis is based on two fields, a summable field like distance, time or elevation gain and a second field to rescale it like heart rate, power, etc.

The analysis is based on an index built using this scalable field and summable field.

To access the analysis you need to select from the statistics field view, a field. If the field you select is summable (Distance, Time, Elevation Gain) it will use it as the summable field and choose Heart Rate as the scalable field. If you select a non summable field, it will use that as the scalable field and distance to sum.

Once the two fields are selected it will then apply a formula to get a performance index. The formula in this first version is simply to multiply the two fields, similar to a very simple TRIMP index, but in the future we could change that, for example along the line of normalised power and apply a function scaling more realistically to how the scalable field impact the distance field. This page gives some interesting comparison of the different way to do that.

Fitness (Long Term) versus fatigue (Short Term)

Given the two fields above and the performance index, then we will try to compare the long term accumulated fitness versus the short term training. We pick two periods, the short term period and the long term period, and plot the average performance index of the long term period versus the short term period.

Currently the short term period is the last seven days and the long term period is the month prior to that.

So the idea is to show how much training accumulated over a month (long term fitness) versus how much you are currently training. If your short term training is significantly above the long term fitness, you maybe over doing it. And you maybe taking it too easy or resting if the short term fitness is quite below the long term fitness.

In a future version I could parametrise both the performance index function and the periods used, depending how much people feel the idea is useful or not. So don’t hesitate to give feedback either with a review, tweet, comment or bug report.

Example

Once you selected a field in the statistics view, tap the bottom plot to iterate between the different choices: Monthly value, performance index graph and histogram/distribution of values.

Here is my current running performance. You can see in this graph that recently I have been training a bit more which raised my long term fitness, while the toward the end november I did less running which lowered the long term fitness .

Screen Shot 2016-02-24 at 05.20.48

New Statistics Plots

In the version 1.20, I added to the main statistics page small preview graphs embedded in the table. I also rationalised somewhat the plots shown on individual fields.

Main Statistics Table

The statistics page start looking like this

EmbeddedPlots

For selected fields, you now see a small preview of a relevant graphs.

Here in distance it shows you the cumulative distance of the previous years, one of my favorite graph to track how you are doing on a given year compare to the previous ones.

Note that you can disable the embedded graphs with an option in settings in case you don’t like it.

For the Average Heart Rate and other non summable fields, it will show you the monthly average over the last 6 months.

Pressing the All button on the right will continue to rotate between the weekly, monthly and annual summary. The Sigma icon means it displays the total or average across all activity. If you press it, it will display the stats restricted to either the last week or last month. This enables you to see all details of the last month or week.

WeeklyStats

Here you can see that the Max Heart Rate over last week was 194, average moving pace 5:21 min/km. This enables you to see any statistics over that period easily. The weekly summary of the previous versions was limited to only a few key measures. Note that in this view the embedded plot becomes a weekly plot to compare this week’s statistics to the previous.

Field Statistics Details

If you press any field of the main statistics table, it will take you a more detail information on that fields, as for example here

StatsMonthly

This shows you two graphs and some basics stats. The first graph is a scatter plot against another variable. If you tap on that plot it will let you configure it and choose the second variable.

The bottom plot will rotate when you tap on it between a monthly summary, the performance analysis graph and an histogram of the different values as here. This post describes the performance analysis in more details.

StatsHistogram

Pressing the all button on the top right as before shows you weekly or monthly statistics.

MonthlyStatsDetails

Improved Statistics Page

Version 1.19 includes an improved and better organised statistics page.

The statistics page is quite simple to find on the iPhone. A few users on iPad sometimes miss it as it’s a bit less obvious, you need to press the stats icon pointed by the blue arrow below.

IpadStatsIcon

The New Fields Stats Page

The new stats page now have the fields pre-organised rather than trying to dynamically work out the ordering based on all the fields found on garmin connect data. This is both so that it works better with other services than garmin and due to the fact that the data include now a lot of new fields that confuses the old logic resulting in quite a messy page. Note that any fields not known by the app will still appear systematically at the very end of the list under the category Other.

NewStatsPage

One new feature is that you can now have a quick filter to see the summary stats for either the week or the month of the most recent activity. For that press the Sum Icon, which will then turn into a week or month icon as pointed by the arrow below.

Screen Shot 2014 04 12 at 11 38 58

Weekly or Monthly Summary

As before if you press the All button on the right it rotates through weekly, monthly or yearly summary. There is now also a quick filter for these pages. If you press the All button pointed by the arrow below you’ll enter to filtered page for the last 3m, 6m or year.

WeeklySummaryAll2TimeFilter

Note that if you want to get more detail on an activity you can now tap on the line for the period you are interested in and it will bring up the page with that full stats on the activities. Below you will see all the statistics for the week starting on the 23rd of march.

WeeklySummaryFor3m

It achieves that with the search feature, the activity list will also contains only the relevant activities. You can from the activity clear the search to see the full list of activities again. When the stats are about the current search it then replace the activity type icon. Note that you can this way get stats on any subset of activity you can define with a search in the activity list screen.

WeeklySummaryTapToDetail