Skip to content
This repository was archived by the owner on Mar 31, 2026. It is now read-only.

Commit f945fdf

Browse files
committed
Reduce dependency telemetry and fix log level for isolated worker
1 parent 310d47a commit f945fdf

13 files changed

Lines changed: 192 additions & 48 deletions

deploy/bicep/function-worker.bicep

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,14 @@ resource worker 'Microsoft.Web/sites@2022-09-01' = {
135135
name: 'AzureFunctionsJobHost__logging__LogLevel__Default'
136136
value: logLevel
137137
}
138+
{
139+
name: 'logging__LogLevel__Default'
140+
value: logLevel
141+
}
142+
{
143+
name: 'logging__ApplicationInsights__LogLevel__Default'
144+
value: logLevel
145+
}
138146
{
139147
name: 'AzureFunctionsWebHost__hostId'
140148
value: hostId

deploy/deploy.ps1

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ process {
7272
$deploymentDir = [System.IO.Path]::GetFullPath((Join-Path $PSScriptRoot "../artifacts/deploy"))
7373
function Publish-Project ($ProjectName) {
7474
Write-Status "Publishing project '$ProjectName'..."
75-
7675
# Workaround: https://github.com/Azure/azure-functions-dotnet-worker/issues/1834
7776
dotnet build (Join-Path $PSScriptRoot "../src/$ProjectName") `
7877
--configuration Release `
@@ -98,8 +97,10 @@ process {
9897
}
9998

10099
$zipPath = Join-Path $deploymentDir "$ProjectName.zip"
100+
Write-Host "Zipping $ProjectName"
101101
Compress-Archive -Path (Join-Path $publishDir "*") -DestinationPath $zipPath -Force
102102

103+
Write-Host "Cleaning publish directory for $ProjectName"
103104
Remove-Item $publishDir -Recurse -Force
104105

105106
return $zipPath.ToString()

deploy/scripts/NuGet.Insights.psm1

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,8 @@ function New-WorkerStandaloneEnv($ResourceSettings) {
457457
# These set up the Azure Functions job host or match with the normal Azure Functions worker settings.
458458
$config["AzureFunctionsJobHost__logging__Console__IsEnabled"] = "false";
459459
$config["AzureFunctionsJobHost__logging__LogLevel__Default"] = $ResourceSettings.WorkerLogLevel;
460+
$config["logging__LogLevel__Default"] = $ResourceSettings.WorkerLogLevel;
461+
$config["logging__ApplicationInsights__LogLevel__Default"] = $ResourceSettings.WorkerLogLevel;
460462
$config["AzureFunctionsWebHost__hostId"] = $ResourceSettings.WorkerHostId;
461463
$config["AzureWebJobs.MetricsFunction.Disabled"] = "true";
462464
$config["AzureWebJobs.TimerFunction.Disabled"] = "true";

src/Logic/Instrumentation/ITelemetryClient.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4+
using System;
45
using System.Collections.Generic;
56

67
namespace NuGet.Insights
@@ -13,5 +14,6 @@ public interface ITelemetryClient
1314
IMetric GetMetric(string metricId, string dimension1Name, string dimension2Name, string dimension3Name);
1415
IMetric GetMetric(string metricId, string dimension1Name, string dimension2Name, string dimension3Name, string dimension4Name);
1516
void TrackMetric(string name, double value, IDictionary<string, string> properties);
17+
IDisposable StartOperation(string operationName);
1618
}
1719
}

src/Logic/Instrumentation/LoggerTelemetryClient.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ public IMetric GetMetric(string metricId, string dimension1Name, string dimensio
4242
return new LoggerMetric(metricId, new[] { dimension1Name, dimension2Name, dimension3Name, dimension4Name }, _logger);
4343
}
4444

45+
public IDisposable StartOperation(string operationName)
46+
{
47+
return _logger.BeginScope(new { OperationName = operationName });
48+
}
49+
4550
public void TrackMetric(string name, double value, IDictionary<string, string> properties)
4651
{
4752
if (properties.Count == 0)

src/Logic/Instrumentation/NullTelemetryClient.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4+
using System;
45
using System.Collections.Generic;
56

67
namespace NuGet.Insights
@@ -34,8 +35,22 @@ public IMetric GetMetric(string metricId, string dimension1Name, string dimensio
3435
return NullMetric.Instance;
3536
}
3637

38+
public IDisposable StartOperation(string operationName)
39+
{
40+
return NullDisposable.Instance;
41+
}
42+
3743
public void TrackMetric(string name, double value, IDictionary<string, string> properties)
3844
{
3945
}
46+
47+
private class NullDisposable : IDisposable
48+
{
49+
public static NullDisposable Instance { get; } = new NullDisposable();
50+
51+
public void Dispose()
52+
{
53+
}
54+
}
4055
}
4156
}

src/Logic/Instrumentation/TelemetryClientWrapper.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4+
using System;
45
using System.Collections.Generic;
56
using Microsoft.ApplicationInsights;
7+
using Microsoft.ApplicationInsights.DataContracts;
68

79
namespace NuGet.Insights
810
{
@@ -44,5 +46,10 @@ public void TrackMetric(string name, double value, IDictionary<string, string> p
4446
{
4547
_inner.TrackMetric(name, value, properties);
4648
}
49+
50+
public IDisposable StartOperation(string operationName)
51+
{
52+
return _inner.StartOperation<RequestTelemetry>(operationName);
53+
}
4754
}
4855
}

src/Website/HostedServices/CachedAdminViewModelService.cs

Lines changed: 38 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,24 @@ public class AdminViewModelCache : IAdminViewModelCache
2323

2424
private readonly IServiceProvider _serviceProvider;
2525
private readonly AdminViewModelCache _cache;
26+
private readonly InitializerHostedService _initializer;
2627
private readonly IOptions<NuGetInsightsWebsiteSettings> _options;
28+
private readonly ITelemetryClient _telemetryClient;
2729
private readonly ILogger<CachedAdminViewModelService> _logger;
2830

2931
public CachedAdminViewModelService(
3032
IServiceProvider serviceProvider,
3133
AdminViewModelCache cache,
34+
InitializerHostedService initializer,
3235
IOptions<NuGetInsightsWebsiteSettings> options,
36+
ITelemetryClient telemetryClient,
3337
ILogger<CachedAdminViewModelService> logger)
3438
{
3539
_serviceProvider = serviceProvider;
3640
_cache = cache;
41+
_initializer = initializer;
3742
_options = options;
43+
_telemetryClient = telemetryClient;
3844
_logger = logger;
3945
}
4046

@@ -45,37 +51,43 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
4551
return;
4652
}
4753

54+
var stopwatch = Stopwatch.StartNew();
4855
while (!stoppingToken.IsCancellationRequested)
4956
{
50-
_cache.Refreshing = true;
51-
_logger.LogInformation("Loading latest admin view model.");
52-
var sw = Stopwatch.StartNew();
53-
try
57+
using (_telemetryClient.StartOperation(nameof(CachedAdminViewModelService)))
5458
{
55-
var asOfTimestamp = DateTimeOffset.UtcNow;
56-
using (var scope = _serviceProvider.CreateScope())
59+
await _initializer.WaitAsync();
60+
61+
_cache.Refreshing = true;
62+
_logger.LogInformation("Loading latest admin view model.");
63+
var sw = Stopwatch.StartNew();
64+
try
5765
{
58-
var factory = scope.ServiceProvider.GetRequiredService<ViewModelFactory>();
59-
var data = await factory.GetAdminViewModelAsync();
60-
_cache.Value = new CachedAdminViewModel(asOfTimestamp, data);
61-
_cache.Settings = scope.ServiceProvider.GetRequiredService<IOptions<NuGetInsightsWebsiteSettings>>().Value;
66+
var asOfTimestamp = DateTimeOffset.UtcNow;
67+
using (var scope = _serviceProvider.CreateScope())
68+
{
69+
var factory = scope.ServiceProvider.GetRequiredService<ViewModelFactory>();
70+
var data = await factory.GetAdminViewModelAsync();
71+
_cache.Value = new CachedAdminViewModel(asOfTimestamp, data);
72+
_cache.Settings = scope.ServiceProvider.GetRequiredService<IOptions<NuGetInsightsWebsiteSettings>>().Value;
73+
}
74+
_logger.LogInformation(
75+
"Latest admin view model loaded after {DurationMs}ms. Sleeping for {SleepMs}ms.",
76+
sw.Elapsed.TotalMilliseconds,
77+
_options.Value.CachedAdminViewModelMaxAge.TotalMilliseconds);
78+
}
79+
catch (Exception ex)
80+
{
81+
_logger.LogError(
82+
ex,
83+
"Failed to load admin view model after {DurationMs}ms. Sleeping for {SleepMs}ms.",
84+
sw.Elapsed.TotalMilliseconds,
85+
_options.Value.CachedAdminViewModelMaxAge.TotalMilliseconds);
86+
}
87+
finally
88+
{
89+
_cache.Refreshing = false;
6290
}
63-
_logger.LogInformation(
64-
"Latest admin view model loaded after {DurationMs}ms. Sleeping for {SleepMs}ms.",
65-
sw.Elapsed.TotalMilliseconds,
66-
_options.Value.CachedAdminViewModelMaxAge.TotalMilliseconds);
67-
}
68-
catch (Exception ex)
69-
{
70-
_logger.LogError(
71-
ex,
72-
"Failed to load admin view model after {DurationMs}ms. Sleeping for {SleepMs}ms.",
73-
sw.Elapsed.TotalMilliseconds,
74-
_options.Value.CachedAdminViewModelMaxAge.TotalMilliseconds);
75-
}
76-
finally
77-
{
78-
_cache.Refreshing = false;
7991
}
8092

8193
await Task.Delay(_options.Value.CachedAdminViewModelMaxAge, stoppingToken);

src/Website/HostedServices/InitializerHostedService.cs

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,33 +15,55 @@ namespace NuGet.Insights.Website
1515
public class InitializerHostedService : BackgroundService
1616
{
1717
private readonly IServiceProvider _serviceProvider;
18+
private readonly ITelemetryClient _telemetryClient;
1819
private readonly ILogger<InitializerHostedService> _logger;
20+
private readonly TaskCompletionSource _taskCompletionSource;
1921

20-
public InitializerHostedService(IServiceProvider serviceProvider, ILogger<InitializerHostedService> logger)
22+
public InitializerHostedService(
23+
IServiceProvider serviceProvider,
24+
ITelemetryClient telemetryClient,
25+
ILogger<InitializerHostedService> logger)
2126
{
2227
_serviceProvider = serviceProvider;
28+
_telemetryClient = telemetryClient;
2329
_logger = logger;
30+
_taskCompletionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
31+
}
32+
33+
public Task WaitAsync()
34+
{
35+
return _taskCompletionSource.Task;
2436
}
2537

2638
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
2739
{
2840
await Task.Yield();
2941

30-
var types = new List<Type>
31-
{
32-
typeof(ControllerInitializer)
33-
};
34-
35-
var initializedTypes = new HashSet<Type>();
36-
using (var scope = _serviceProvider.CreateScope())
42+
try
3743
{
38-
foreach (var type in types)
44+
using (var operation = _telemetryClient.StartOperation(nameof(InitializerHostedService)))
3945
{
40-
stoppingToken.ThrowIfCancellationRequested();
46+
var types = new List<Type>
47+
{
48+
typeof(ControllerInitializer)
49+
};
50+
51+
var initializedTypes = new HashSet<Type>();
52+
using (var scope = _serviceProvider.CreateScope())
53+
{
54+
foreach (var type in types)
55+
{
56+
stoppingToken.ThrowIfCancellationRequested();
4157

42-
await InitializeAsync(scope.ServiceProvider, initializedTypes, type, stoppingToken);
58+
await InitializeAsync(scope.ServiceProvider, initializedTypes, type, stoppingToken);
59+
}
60+
}
4361
}
4462
}
63+
finally
64+
{
65+
_taskCompletionSource.TrySetResult();
66+
}
4567
}
4668

4769
private async Task InitializeAsync(

src/Website/HostedServices/MoveMessagesHostedService.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
5252
while (!stoppingToken.IsCancellationRequested)
5353
{
5454
var moveTask = await _taskQueue.DequeueAsync(stoppingToken);
55+
56+
using var operation = _telemetryClient.StartOperation(nameof(MoveMessagesHostedService));
57+
5558
try
5659
{
5760
await ExecuteMoveTaskAsync(moveTask, stoppingToken);

0 commit comments

Comments
 (0)