The Daily Parker

Politics, Weather, Photography, and the Dog

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.

Some observations about my walk just now

Before I get to the technical bits comparing the Garmin Venu (now on my left wrist) to the Fitbit Ionic, let me just list some "learnings" today:

  • Both trackers are waterproof as advertised, as is my phone.
  • I am glad that I keep a towel by my back door.
  • I am glad that my washing machine—and, let's face it, my dryer—is by my back door.
  • There comes a point where one's clothes have absorbed so much water that it really doesn't matter how much more water they will encounter.

I have no one to blame but myself. This is the radar picture 10 minutes into the walk:

And 40 minutes in:

Result:

But enough about me. This post is really about fitness trackers.

In sum, the main difference between the Garmin and the Fitbit remains the Fitbit's total GPS failure, and the paucity of data Fitbit provides on its app compared with Garmin.

Here's the Fitbit data:

And the Garmin data:

I am pleased, however, that both trackers got almost exactly the same distance, given that the Garmin tracked distance using actual data and the Fitbit guessed based on my stride length. They don't agree on how many calories I burned, how many steps I took: the Garmin said 6,556, while the Fitbit said 6,109. So far today, my Garmin says 9,127 to Fitbit's 9,047, which adds data to my hypothesis that my Fitbit has always under-counted.

So, other than the rain, I thought this test went well.

Garmin v Fitbit: sleep metrics

Despite the Garmin Venu handing the Fitbit Ionic its ass in my first test of exercise tracing, the Fitbit didn't fail completely in sleep tracking.

Based on my self-perception of how well I slept, including my (and Parker's) acute awareness of the squall line that pushed through around 6:30, I think the Fitbit might have recorded my awake time more accurately. The Garmin, however, also recorded pulse oxygen, respiration, and can display movement on the UI.

Here's the Fitbit results:

And Garmin:

Also, yesterday my Fitbit counted 18,206 steps to the Garmin's 12,142—but I put the Garmin on my wrist at 1pm. Adding the 6,963 the Fitbit recorded before 1pm, that means the Garmin and Fitbit differed by (19,105 – 18,206 = ) 899, or 4.7% for the 11 hours between 1pm and midnight. Today I'm using both of them, though I switched wrists (yesterday the Garmin was on my dominant side; today it's not).

The thunderstorms from earlier have pushed on through the area, so once I digest my omelet and my Garmin fully charges, I'll do a longer test of exercise tracking.

Garmin Venu vs Fitbit Ionic short walk head-to-head

Yeah, the Garmin wins, hands down.

After realizing that my first head-to-head test pitted an Ionic whose GPS was failing against a treadmill exercise, I went out for a quick loop around the block with both trackers correctly set to "Walk."

The Garmin found a GPS signal in about 20 seconds. The Fitbit never did.

After the walk, the Garmin produced this delightful map, complete with weather report and options for different maps:

Right on the activity view, I've got a gear icon with these options:

Fitbit only exports TCX files. Or you can export your entire account archive, become a programmer like me, parse your archive, and extract the relevant item.

But the map and export options just scratch the surface. Look what the Fitbit Web app gives me for this walk (since it didn't have GPS):

And here's the Garmin:

I mean, that's not even fair. Garmin even gave me the weather report, fer gassake. (It did not give me the step count for the activity, though.

Yeah. Fitbit, you were great, but I've grown; you haven't. You fell so far behind Garmin that I don't know how you're going to catch up.

Tonight, I'll see how differently they track sleep. And I hope that I can re-import today's Fitbit steps, else I'll lose the 7,000 I had before I set up the Garmin. Also, Garmin only imports step counts, intensity times, and body mass from Fitbit, not sleep data, so I'll have to find a different solution for that.

More annals of eclectic musical interests

Back in May I started listening to every CD I own, in the order that I bought them, starting with Eugen Jochum conducting Mozart's Mass in C-Major, K317 (purchased in May 1988). I'm up to July 1989 now, and as I write this, I'm playing The Mama's and the Papa's [sic] If You Can Believe Your Eyes and Ears (1967). This follows The Beatles' With The Beatles (1963) and Paul McCartney's Pipes of Peace (1983).

And then it goes sideways.

Next up: Haydn's Piano Concerto #11 (1781), and Josquin's "Missa L'Homme Armé" (ca. 1500). I bought those five CDs on 7 July 1989.

Three days later I acquired a batch of six, including a collection of English madrigals sung by the King's Singers, Oscar Levant playing Gershwin, and the soundtrack from The Breakfast Club.

There are stretches of classical and stretches of modern throughout this list, but right now I'm in summer break after my first year of college when I was expanding both sides of my collection as fast as I could afford to.

I just did some math: at the rate I'm going, I'll be out of my university years around November 17th, in the 21st Century around the beginning of April, and through all of them in the fall of 2021. (That's a moving target for obvious reasons.)

It's a little trippy. I haven't heard some of these in a long, long time.

Wrong kind of hedge fund

A couple on the north side of Chicago planted hedges around a patch of public park land and fought the city's attempts to get the land back for 15 years. Then a local blog got ahold of the story, and the hedges came right out:

About 8:30 a.m., a landscaping crew was at the home in the 3000 block of North Lake Shore Drive West to remove the hedgerow on public land. The politically connected homeowner, businessman Michael Tadin Jr., confirmed he ordered the bushes removed.

As neighbors watched the hedgerow being torn out, one person passing by said, “I can’t tell you how happy this makes me.”

Another walked up, threw an egg at the house and left a bag of dog poop on the lawn.

Block Club revealed Tuesday that Tadin Jr. and his wife, Natalie Tadin, planted hedges around the 3,000 square feet of Chicago Park District land in front of their home, according to an inspector general report issued last week.

The entire block from Wellington to Barry that faces Lake Shore Drive West was previously a convent for a religious order. About 15 years ago, the mansion and chapel on Barry were converted to residential use when the property was sold and the land around it was rezoned.

I have a particular interest in this story because I used to live directly above the property in question. I'll try to find a photo of it from before the convent closed.

Halfway there...

Welp, it's July now, so we've completed half of 2020. (You can insert your own adverb there; I'll go with "only.")

A couple of things magically changed or got recorded at midnight, though. Among them:

And finally, I am now officially the President of the Apollo Chorus of Chicago. My first task: ensure that our annual fundraiser, Apollo After Hours, brings in the dough. More on that later.