The Daily Parker

Politics, Weather, Photography, and the Dog

Maybe not the best programming

I'm going into my downtown Chicago office twice a week, even though I'm the only one on the floor, just so I can get some variety and also more monitors for my work laptop. Last week the building started piping classical music into the main lobby. They, or the streaming provider, have chosen pretty basic stuff: Mozart piano concerti, Haydn symphonies, the occasional string quartet.

Today the walk-on music was Barber's Adagio for Strings. Think about the movies that used this piece and ask yourself, is this what people want to hear walking into their office building at 8:45 on a Monday morning? During a global emergency? Ten weeks before the most consequential election in the last 75 years?

I will now sob briefly before coding a fun demo.

Long weekend

After a cool front passed through yesterday, this morning we've got sun, cooler (25°C vs yesterday's 32°C) weather, and a gentle breeze.

My way of saying, see you tomorrow. Or maybe later this evening.

More about Chelsea Rectanus

Block Club Chicago has a kind article about my friend:

In opening Heirloom Books, Chelsea Carr Rectanus created a community, a place where people could come and hold weighty discussions or hear from prospective politicians.

But that community was abruptly upended last week. Rectanus, 32, died “peacefully but unexpectedly” Aug. 7 of a long-standing illness she battled, Earl Rectanus, Chelsea’s father, said on Heirloom’s Facebook page.

Now Rectanus’ friends and family are working to ensure what she created in Edgewater continues on, and serves as a testament to her impact on the neighborhood.

“It’s more than a book shop,” said Emily Carter Alexander, Rectanus’ friend. “It’s a place anyone can go. I was [at Heirloom] Monday, and it was hard not to see Chelsea bopping around and being her quirky, happy self.”

Chelsea's sister has set up a virtual memorial service next Sunday at 1pm Central.

Wasted time

I just spent 90 minutes driving to and from two different Drivers Services facilities because I wanted to renew my drivers license with a Real ID version. At both places the lines stretched into the next time zone. Since I can renew online, and I have another Real ID available, I'm just not going to bother.

I'm surprised—not very, but still—that Drivers Services still doesn't understand queuing theory. Or they just don't care. Illinois used to handle this much better, but after four years of Bruce Rauner cutting funding to the entire state, I guess it'll take some time to fix. (The pandemic didn't help, with more than half of the county's facilities temporarily closed.)

Update: Renewing online took less than a minute, and just in case I don't receive my renewed license before the current one expires, they let me print out a temporary. So if I have to take a domestic flight, I'll just bring my passport card.

Taking a minute

A friend I met just last November died on Friday night at 32. She owned Heirloom Books in Chicago's Edgewater community, one of the last independent used-book shops in the neighborhood. (Always a "shop;" never a "store.") She'd only recently adopted a kitten, Pilar, who I met a few weeks ago.

Her father posted on Facebook that she died "peacefully but unexpectedly...from complications arising from a long-standing illness which she fought valiantly against over many years, but which few people were aware of." I was aware of it, and I can say without hesitation it was not inherently fatal. But the endlessness and isolation of the pandemic, exacerbated by a president who's too stupid and too narcissistic to have the least comprehension or compassion a human being needs to call himself one, surely contributed. So did the difficulty of getting affordable health care here.

I'm sad a friend died, and I'm angry that in almost any other country she wouldn't have.

My heart goes out to her parents and her sister.

As the pipeline builds...

I'm waiting for a build to finish so I can sign off work for the day, so I've queued up a few things to read later:

Looks like the build is done, and all the tests passed. (I love green pipelines.)

How to pass secrets into your custom log target

Today I finally solved a problem that has nagged me for months: Given a .NET Core 3.1 Web API, NLog, and a custom log target for NLog, how could I pass secrets into the log target using Azure Key Vault?

The last bit required me to add Azure Key Vault support to the InnerDrive.Logging NuGet package, which I did back in February. The KeyVaultSecretProvider class allows you to retrieve secrets from a specified Azure Key Vault. (I'm in the process of updating it to handle keys as well.) Before that, you'd have to put your secrets in configuration files, which anyone on your development team or who has access to your Git repository can see. For example, to use our SendGridTarget class, you would have to put this in your nLog.config file:

<extensions>
	<add assembly="NLog.Web.AspNetCore"/>
	<add assembly="InnerDrive.Logging"/>
</extensions>

<targets async="false">
	<target xsi:type="SendGridTarget"
	        name="sendgrid"
		apiKey="{supposedly secret key}"
		applicationName="My Cool App"
	        from="service@contoso.org"
	        to="admin@contoso.org"
	/>
</targets>

That is...suboptimal. Instead, you want to use a class that implements ISecretProvider and inject it into the SendGridTarget class through this constructor:

/// <summary>
/// Creates a new instance of <see cref="SendGridTarget"/> with
/// a specified <see cref="ISendGridSender"/> implementation.
/// </summary>
/// <param name="sender">The <see cref="ISendGridSender"/> to use</param>
/// <param name="secretProvider">The <see cref="IConfiguration"/> to use</param>
/// <param name="apiKey">The API key to use</param>
public SendGridTarget(
	ISendGridSender sender, 
	ISecretProvider secretProvider = null, 
	string apiKey = null)
{
	IncludeEventProperties = true;
	if (null != secretProvider) Configuration = secretProvider;
	if (!string.IsNullOrWhiteSpace(apiKey)) ApiKey = apiKey;
	_sender = sender;
}

And now I'm going to save you about 30 hours of research and frustration. To get NLog to inject the secret provider into the target, I added this method to Startup.cs:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IComponentContext container)
{
	// Setup code elided
	ConfigureLogging(container);
}

public static void ConfigureLogging(IComponentContext container)
{
	var defaultConstructor = ConfigurationItemFactory.Default.CreateInstance;
	var secretProvider = container.Resolve<ISecretProvider>();
	ConfigurationItemFactory.Default.CreateInstance = type =>
	{
		if (type == typeof(SendGridTarget))
		{
			var sendGridSender = container.Resolve<ISendGridSender>();
			return new SendGridTarget(sendGridSender, secretProvider);
		}

		return defaultConstructor(type);
	};
	LogManager.Configuration = LogManager.Configuration.Reload();
	NLogBuilder.ConfigureNLog(LogManager.Configuration);
}

(Note that the ISecretProvider and ISendGridSender classes need to be registered with your dependency-injection framework.)

Today was a good day.

Garmin offline

Four days after I switched from Fitbit to Garmin, all of Garmin's online services have gone offline:

The problems with those services also mean that a range of features can't be used on Garmin's own devices: it is not possible to create new routes to go running or cycling, for instance, or to share those activities on services like Strava once they are completed.

The devices themselves continue to work as normal with the data they do have, however, meaning that any data collected during the outage will be safe.

Garmin wrote on its official Twitter pages that the problems were also affecting its call centres, leaving users unable to get in touch through calls or online messages.

"We are currently experiencing an outage that affects Garmin Connect, and as a result, the Garmin Connect website and mobile app are down at this time," it wrote.

"This outage also affects our call centres, and we are currently unable to receive any calls, emails or online chats. We are working to resolve this issue as quickly as possible and apologise for this inconvenience."

This is not what Garmin customers want to see:

The error message on the Garmin Connect website suggests the problem is with their Cloudflare equipment:

Update: Based on Garmin employee's social-media posts, ZDNet now reports that the company experienced a catastrophic ransomware attack, most likely a new strain of WastedLocker. Fortunately, my Venu can hold 200 hours of data. So as long as they get it back up within a week or so, I shouldn't lose anything—unless the ransomware attack already destroyed my data from this past week.

Making reservations for beer gardens

A friend and I plan to go to a local beer garden this weekend—one on the Brews and Choos list, in fact—so we had to make a reservation that included a $7.50-per-person deposit. Things are weird, man. And if you read the news today, oh boy, the weirdness is all over:

Finally, closer to home, 4,400 restaurants in Chicago have closed because of the pandemic, 2,400 permanently. The Chicago Tribune has a list of the more notable closures. 

Garmin v Fitbit: Full day comparison

I wore both my old Fitbit Ionic and new Garmin Venu for about 42 hours straight. Yesterday they overlapped for the entire day. And they came in with similar, but not quite the same, numbers.

I thought that my Fitbit would record fewer steps overall, because it recorded about 450 (about 7%) fewer on my walk yesterday. For the whole day, though, the Fitbit counted 14,190 to the Garmin's 13,250—7% more. But I wore the Fitbit on my right (dominant) wrist, so it may have just had more activity in general.

In other basic measures:

  • The Fitbit recorded 13.3 km to the Garmin's 10.6 km;
  • The Fitbit estimated my resting heart rate as 64 to the Garmin's 65;
  • Fitbit counted 82 "active" minutes to the Garmin's 359 "moderate" and 369 "vigorous";
  • Fitbit estimated my calorie burn at 3,100 to Garmin's 2,862.

I have no way to know which tracker was more accurate, but I might bet a dollar on the Garmin. I think the Garmin used actual distance to the Fitbit's estimate based on my usual stride length, which doesn't account for all the difference.

The Garmin's app presentation is so far beyond Fitbit's I wonder whether Fitbit even has software developers. Here's Fitbit:

Here's Garmin's:

And that's not even all of the Garmin data.

I walked halfway home after work today, and once again, the Garmin tracked my workout better than the Fitbit has done in months.

I'm glad I switched.