Skip to content

Instantly share code, notes, and snippets.

@heaths
Last active August 19, 2020 22:06
Show Gist options
  • Save heaths/87b6a2da1b9cdd5c88fe6c3dedb28216 to your computer and use it in GitHub Desktop.
Save heaths/87b6a2da1b9cdd5c88fe6c3dedb28216 to your computer and use it in GitHub Desktop.
Repro application for Azure/azure-sdk-for-net#9737
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Azure.Identity" Version="1.2.1" />
<PackageReference Include="Azure.Security.KeyVault.Secrets" Version="4.1.0" />
<PackageReference Include="System.CommandLine" Version="2.0.0-beta1.20371.2" />
<PackageReference Include="System.CommandLine.DragonFruit" Version="0.3.0-alpha.20371.2" />
</ItemGroup>
</Project>
// Copyright 2020 Heath Stewart
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE
using System;
using System.Diagnostics.Tracing;
using System.Threading;
using System.Threading.Tasks;
using Azure;
using Azure.Core.Diagnostics;
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
namespace Issue9737
{
class Program
{
static SecretClient _client;
static int _failureCount;
static async Task Main(bool verbose, int minDelay, int maxDelay, int count = 10)
{
var vaultUri = new Uri(Environment.GetEnvironmentVariable("AZURE_KEYVAULT_URL") ?? throw new InvalidOperationException("Missing required $AZURE_KEYVAULT_URL"));
using var listener = new AzureEventSourceListener(
(e, message) => Log(e.TimeStamp.ToLocalTime(), e.OSThreadId, message),
level: EventLevel.Verbose);
var credentialOptions = new DefaultAzureCredentialOptions
{
Diagnostics =
{
IsLoggingEnabled = verbose,
IsDistributedTracingEnabled = verbose,
IsLoggingContentEnabled = verbose,
LoggedHeaderNames = { "*" },
},
};
var credential = new DefaultAzureCredential(credentialOptions);
var clientOptions = new SecretClientOptions
{
Diagnostics =
{
IsLoggingEnabled = verbose,
IsDistributedTracingEnabled = verbose,
IsLoggingContentEnabled = verbose,
LoggedHeaderNames = { "*" },
}
};
_client = new SecretClient(vaultUri, credential, clientOptions);
using var cts = new CancellationTokenSource();
Console.CancelKeyPress += (source, args) =>
{
cts.Cancel();
args.Cancel = true;
};
var rand = new Random();
var tasks = new Task[count];
for (var i = 0; i < tasks.Length; ++i)
{
tasks[i] = GetSecretsAsync(cts.Token, rand.Next(minDelay, maxDelay));
}
await Task.WhenAll(tasks);
ConsoleColor c = _failureCount > 0 ? ConsoleColor.Red : ConsoleColor.Green;
Console.ForegroundColor = c;
try
{
Console.WriteLine();
Console.WriteLine($"Failed {_failureCount} times.");
}
finally
{
Console.ResetColor();
}
}
static async Task GetSecretsAsync(CancellationToken cancellationToken, int delay)
{
try
{
await Task.Delay(delay);
await _client.GetSecretAsync("test-secret", cancellationToken: cancellationToken);
}
catch (RequestFailedException ex)
{
if (ex.Status == 401)
{
Interlocked.Increment(ref _failureCount);
}
LogError(ex.Message);
}
}
static void LogError(string message) => Console.WriteLine("\x1b[91m[{0:HH:mm:ss:ffff};{1:x4}]\x1b[0m {2}", DateTime.Now, Thread.CurrentThread.ManagedThreadId, message);
static void Log(DateTime timestamp, long threadId, string message) => Console.WriteLine("\x1b[33m[{0:HH:mm:ss:ffff};{1:x4}]\x1b[0m {2}", timestamp.ToLocalTime(), threadId, message);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment