My children would have loved this Multi-Terra Helio Cell Vehicle 407 cockpit control. I especially like the addition of the fans!
Streamlit and a trivial cities explorer
Board game UX
I don't know if the game Star Wars: Outer Rim is enjoyable, but the game's physical design is amazing. Which reminds me I have What the Tech World Can Learn from Video Game UX lined up to watch.
Update: The video was about using gamification to enhance learning to use a handheld ultrasound scanner. Nothing new.
Ad hoc systems for managing work
I love seeing people's systems for managing their work. Even those of fictional people. This short from The Bear on managing the restaurant's guests and their orders is great.
A list of physical infrastructure monitoring tools
Flights into Providence
https://flightaware.com/live/airport/KPVD
Shipping in Narragansett Bay
https://www.marinetraffic.com/en/ais/home/centerx:-71.5/centery:41.4/zoom:10
RI DOT Traffic Camera
https://www.mapquest.com/?center=41.809012,-71.40841&zoom=12&layer=traffic
Gritters in Scotland
http://scotgov.maps.arcgis.com/apps/webappviewer/index.html?id=2de764a9303848ffb9a4cac0bd0b1aab
Furthermore on dashboards for maintenance developers
A display for showing details of actors, messages, and listeners (dependents) might be
More on dashboards for maintenance developers
Yesterday I wrote about providing tools to visualize & manage the internal workings of applications for maintenance developers. That note was long on advocacy and sort on detail. This note somewhere between those two.
We are all familiar with run-time debuggers. We can get our job done with gdb [1], but for day in and day out work a visual debugger is a must have. A debugger is a point-in-time dashboard of the execution of the programming language used to implement the application. It is not a dashboard of the application, it does not directly represent the application's data or processing models. Nor does it provide a history of where the application was or a prediction of where it will be heading too next. Nevertheless, it is a useful analogous image of the application dashboard to keep in your mind.
If, for example, your application relies on the observer pattern [2] then you will need to visualize & manage the actors (observed), their dependents (observers), and the messages. The effort to implement this dashboard can be significant, which is the exact opposite of implementing the pattern itself. The pattern is often implemented as a list of callbacks. This implementation is so insignificant that your high performing developers probably choose not to use a framework at all, but to re-implement for each use. And there is the root of the trouble ahead for the maintenance developers, there is no one place to watch this running application. Callbacks and messages are being created and dispatched all over the place.
Suppose there had been a reusable implementation. The management of the listeners was done in a single place. The dispatching of messages to the listeners was done in a single place. Each reuse required that the developer explain the purpose, configuration, and expectations of this reuse. For example, "Status of the nightly recalculations of base prices: the messages are life cycle events; messages are ticketed and numbered for correlation; the listeners can be local or remote; the listeners are contacted asynchronously; no receipt acknowledgement is wanted, but when given will be logged; expect a dozen messages over a 2 hour period in every 24 hour period to be sent to a few hundred listeners." When this pattern is visualized on the dashboard not only is the context clear, but timelines of planned to actual and switches to toggle synchronicity will automatically be included. And what if you could dynamically toggle receipt acknowledgement? How many of your application's ailments are the result of lost messages sent to remote listeners?
The rise of DevOps has brought with it both tools and new (renewed?) appreciation for visualizing processes and their artifacts. Lets keep on pushing these ever deeper into the application itself.
[1] gdb, https://www.gnu.org/software/gdb/
[2] Observer pattern, https://en.wikipedia.org/wiki/Observer_pattern
We all want visibility into a running application
We all want visibility into a running application. The need becomes acute when the application is ailing and that visible schedule, map, and cartogram of the data and processing will swiftly guide you to the failing part.
What is less recognized is that these same visuals are needed in maintenance. Your original, high performing developers are unlikely to be around after the application has been in production for a few years. They will have moved on to new green pastures. If you are lucky and they are still with the company then they will be somewhat available to the maintenance developers. If a little cantankerous about that.
The maintenance developer usually has little broad knowledge of the application’s operation. Her first task at resolving an application’s ailment will be to find suitable entrance and exit points. This is not an easy task for our applications now run continuously, across multiple processes and hosts, and are highly asynchronous. Hopefully, those high performing developers adhered to standards, used a common framework throughout, and kept to best-of-class external libraries and supporting tools. If they did then she might have a straightforward resolution path. In all likelihood, however, those high performing developers probably invented too much and documented too little. [I speak from the experience of my younger self.]
What the maintain crew needs is not logs alone. They need meta tools that connect to the running application and visually show its operation. Once connected the tool must be able to slow down the application to a human pace. Restrict it to one active user at a time. It might even need to switch it to run synchronously.
These are not easy features to implement, but the cost of not doing it is not just the ever lengthening backlog of ailments to fix, but the erosion of customer confidence and, in the end, loss of customers.
All modern applications have three users. The first is the customer. The second is the customer support. The third is the maintenance crew. It is way past time that the maintenance developer is provided the meta tools needed to look inside the running application and keep it fit for market.
BitBar shout out
Incident Response Slack App
During the response, tasks emerge that need to be assigned and tracked. Slack itself is not good at this alone. There are many applications for task management that can be made accessible via Slack slash-commands. For incident response tasks, however, these general purpose applications were too focused on the user and not enough on the channel. When listing tasks we only want to see those for this incident. Their extra features also had a cognitive weight that I brisselled at. Overall, their fit for purpose was poor.
What was needed was a task manager with a scope limited to one channel. The task manager would be installed in the workspace, and so accessible to everyone, everywhere without configuration, but when in use was channel focused. The task manager needed to support these simple the use cases
- Adding tasks with a description, assignments, and a status.
- Updating a task’s description, assignments, or status. Only notify the channel when the changes are pertinent to all.
- Listing the tasks with optional criteria.
These use cases turned into the /ir slash-command
/ir description [ user … ] [ status ]
/ir task-id [ description [ user … ] [ status ]
/ir [ all | finished ] [ user … ] [ status … ]
If you are interested in the implementation then see github.com/andrewgilmartin/com.andrewgilmartin.incidentresponse
Two kinds of noise
Three tweets in 100 square inches of screen space. (Large editorial photos and illustrations do not count as content.)
Grumble about messaging conversation indistinguishability
Meeting room geek lights
How are branches being used? A visualization
The code is
#!/bin/bash
date1=$(date -v -180d +'%Y-%m-%d')
date2=$(date -v -1d +'%Y-%m-%d')
svn='svn+ssh://.../branches'
svn log --revision {$date1}:{$date2} $svn | perl -e '
my %D = (); # dates
my %U = (); # users
while( <> ) {
if ( /\| (.*?) \| (\d\d\d\d-\d\d-\d\d) / ) {
my $u = $1;
my $d = $2;
$D{$d} ||= {};
$D{$d}->{$u} += 1;
$U{$u} = 1;
}
}
my @d = sort keys %D;
my ( $l ) = reverse sort map { length($_); } @d; # max length
for my $u ( sort keys %U ) {
printf( "%*s %s | ", -$l, $u, $d[0] );
for my $d ( @d ) {
print $D{$d}->{$u} ? "*" : "-";
}
printf( " | %s\n", $d[$#d] );
}
'
# END
Update: A failing of this script is that it only shows days with activity. Days without activity by any developer will be missing from the timeline. I replaced this script with this one#!/usr/bin/perl -w
use strict;
use DateTime;
my $svn_url='svn+ssh://.../branches';
my $stop = DateTime->today();
my $start = $stop->clone()->subtract( days => shift @ARGV || 90 );
my %W = (); # week days
my %D = (); # dates
my %U = (); # users
# initialize the dates and the weekdays hashs with days between the start and stop dates
for ( my $next = $start->clone(); $next->compare($stop) <= 0; $next->add( days => 1) ) {
my $F = $next->strftime('%Y-%m-%d');
$D{$F} = {};
$W{$F} = $next->day_of_week();
}
# collect the svn usage data
if ( open( IN, "svn log --revision \{$start\}:\{$stop\} $svn_url |" ) ) {
while( <IN> ) {
if ( /\| (.*?) \| (\d\d\d\d-\d\d-\d\d) / ) {
my $u = $1;
my $d = $2;
if ( defined $D{$d} ) {
$D{$d}->{$u} += 1;
$U{$u} = 1;
}
}
}
close(IN);
}
my @d = sort keys %D;
my ( $l ) = reverse sort { $a <=> $b } map { length($_); } keys %U; # max user length
# output the chart
for my $u ( sort keys %U ) {
printf( "%*s %s | ", -$l, $u, $d[0] );
for my $d ( @d ) {
print $D{$d}->{$u} ? "*" : "-";
}
printf( " | %s\n", $d[$#d] );
}
# output the line of mondays
printf( "%*s %*s | ", -$l, "", length($d[0]), "" );
for my $d ( @d ) {
print $W{$d} == 1 ? "M" : " ";
}
printf( " |\n" );
# END
A gnuplot example
I want on a single chart the lines graphs of count of all queries, count of matching queries, and mean duration of all queries. This chart gives me the temperature of the previous day's query load which is a useful qualitative factor for capacity planning. The data retrieval results in records representing a 10 minute interval with counts of all queries, counts of matching queries, and mean durations. This is then plotted to give a chart like the following:
The file of records contains values that looks like
2014-07-07T00:10:00 10449 3850 934 2014-07-07T00:20:00 18445 5676 407 2014-07-07T00:30:00 18497 6507 535 2014-07-07T00:40:00 11419 4463 734 2014-07-07T00:50:00 11634 4454 724 2014-07-07T01:00:00 11960 5077 808 ...
The Gnuplot script is
set terminal png size 800, 400 small interlace set output "/tmp/chart.png" set size ratio 0.5 set xdata time set timefmt "%Y-%m-%dT%H:%M:%S" set xlabel "Hour" set format x "%H:%M" set ylabel "Count" set ytics nomirror set yrange [0:40000] set y2label "Milliseconds" set y2tics set y2range [0:4000] set title "MetaData matching search counts and average durations (10 min intervals) for 2014-07-07" plot \ "/tmp/chart.data" using 1:2 title "Query count" with lines, \ "/tmp/chart.data" using 1:3 title "Matching count" with lines, \ "/tmp/chart.data" using 1:4 title "Request duration" axes x1y2 with lines
The chart is produced daily and it is useful to visually align several days of charts to look for patterns. For comparable charts this requires that the charts all have the same y-axes ranges. To do this Gnuplot's range setting is used. If you do not want a fixed range then remove the set yrange ... and set y2range ... lines.
I hope this helps someone else with their Gnuplot use.
Too little skeuomorphism!
I find iOS 7's UI boring rather than utilitarian and/or minimalistic. I am, frankly, surprised at my reaction to this utilitarianism as it is something I have wanted for some time. How I have it, I think Apple went too far in removing the skeuomorphism.
Horizon charts
Update: Updated the working example to be more general. Removed the code from this posting in preference to the Gist.
I want more "geek lights"
However, geek-lights are incredibly useful for other kinds of information. Information that is different for you and me. For example, one to indicate if traffic is too heavy to venture out now. Another to tell me that I have email. Another to tell others that I am in a conference call and not just talking to myself again.
I would like to have a box of these geek-lights that I can use each for a specific purpose. The geek-light would be nothing more than a shallow and wide cylinder with the light on the top, temporary adhesive on the bottom, and the electronics sandwiched in between. Let's call them eyelets as they let you see something ordinarily invisible. Each eyelet is individually addressable by a short range wireless signal. An eyelet receives a signal that indicates whether it is illuminated or not. Eyelets don't send signals back. I can imagine the hardware being something akin to Logitech's Unifying receiver -- that is, unobtrusive.
The question now is, should eyelets have a battery charge indicator light?
Need multiple-view calendar
The top chart contains my unique events over the last 2 and next 8 days. The second chart contains my common events over the last 2 and next 8 days. The bottom left chart is a list of common events for the next several weeks. And the bottom right chart is a list of unique events for the next several weeks.Since we have separated events that actually occupy the same timeline we need to rejoin them somehow. My initial thought was to add a ghost to each chart that signifies the presents of an event in another chart, but I am not wedded to this.
Does anyone make a calendar like this, either visually or purposefully?
In praise of gnuplot's dumb terminal support
#!/bin/bash
function show_usage {
echo \
usage: $(basename $0) \
[-x label] \
[-y label] \
[-t title] \
[-s width:height] \
[-f time-format-strftime] \
timeseries-input ...
}
function swap {
echo $2 $1
}
function parse_size {
W=$(expr $1 : "\\([0-9]*\\):[0-9]*")
H=$(expr $1 : "[0-9]*:\\([0-9]*\\)")
echo "$W $H"
}
TIMEFMT="%Y-%m-%dT%H:%M:%S"
XLABEL="Time"
YLABEL="Units"
TITLE="Timeseries"
SIZE=$(swap $(stty size))
while getopts "x:y:t:f:s:h" opt
do
case $opt in
x) XLABEL=$OPTARG ;;
y) YLABEL=$OPTARG ;;
t) TITLE=$OPTARG ;;
f) TIMEFMT=$OPTARG ;;
s) SIZE=$(parse_size $OPTARG) ;;
h) show_usage ; exit 0 ;;
*) show_usage ; exit 1 ;;
esac
done
shift $(expr $OPTIND - 1)
for INPUT in $*
do
if [ "$INPUT" = "-" ]
then
INPUT=$(mktemp /tmp/timeplot.XXXXXXXXXX)
cat > $INPUT
fi
gnuplot <<EOH
set terminal dumb $SIZE
set autoscale
set xdata time
set timefmt "$TIMEFMT"
set xlabel "$XLABEL"
set ylabel "$YLABEL"
set title "$TITLE"
plot "$INPUT" using 1:2 with lines
EOH
done
# END
For example, if the data in /tmp/data is 2011 34 2012 34 2013 56 2014 24then this can be quickly plotted using
timeplot -f %Y /tmp/dataand get






