Skip to content

Commit

Permalink
[gh-1150] Re-add feature tracking as server-side metrics
Browse files Browse the repository at this point in the history
  • Loading branch information
ashmind committed Jan 5, 2024
1 parent e0939b3 commit 376ccd7
Show file tree
Hide file tree
Showing 43 changed files with 1,148 additions and 971 deletions.
16 changes: 15 additions & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ csharp_new_line_before_open_brace = none
csharp_style_var_for_built_in_types = true:warning
csharp_style_var_when_type_is_apparent = true:warning
csharp_style_var_elsewhere = true:warning
csharp_style_namespace_declarations=file_scoped:warning

dotnet_style_readonly_field = true:warning

Expand All @@ -29,4 +30,17 @@ dotnet_diagnostic.CA1822.severity = none
dotnet_diagnostic.IDE0005.severity = warning

# IDE0090: 'new' expression can be simplified.
dotnet_diagnostic.IDE0090.severity = warning
dotnet_diagnostic.IDE0090.severity = warning

# IDE0300: Use collection expression for array
# IDE0301: Use collection expression for empty
# IDE0302: Use collection expression for stackalloc
# IDE0303: Use collection expression for Create()
# IDE0304: Use collection expression for builder
# IDE0305: Use collection expression for fluent
dotnet_diagnostic.IDE0300.severity = warning
dotnet_diagnostic.IDE0301.severity = warning
dotnet_diagnostic.IDE0302.severity = warning
dotnet_diagnostic.IDE0303.severity = warning
dotnet_diagnostic.IDE0304.severity = warning
dotnet_diagnostic.IDE0305.severity = warning
10 changes: 0 additions & 10 deletions source/Server/Caching/CachingMetrics.cs

This file was deleted.

32 changes: 18 additions & 14 deletions source/Server/Caching/CachingModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,25 @@
using SharpLab.Server.Caching.Internal;
using SharpLab.Server.Common;

namespace SharpLab.Server.Caching {
[UsedImplicitly]
public class CachingModule : Module {
protected override void Load(ContainerBuilder builder) {
var webAppName = EnvironmentHelper.GetRequiredEnvironmentVariable("SHARPLAB_WEBAPP_NAME");
var branchId = webAppName.StartsWith("sl-") ? webAppName : null;
namespace SharpLab.Server.Caching;

builder.RegisterType<ResultCacheBuilder>()
.As<IResultCacheBuilder>()
.WithParameter("branchId", branchId)
.SingleInstance();
[UsedImplicitly]
public class CachingModule : Module {
protected override void Load(ContainerBuilder builder) {
var webAppName = EnvironmentHelper.GetRequiredEnvironmentVariable("SHARPLAB_WEBAPP_NAME");
var branchId = webAppName.StartsWith("sl-") ? webAppName : null;

builder.RegisterType<ResultCacher>()
.As<IResultCacher>()
.SingleInstance();
}
builder.RegisterType<ResultCacheBuilder>()
.As<IResultCacheBuilder>()
.WithParameter("branchId", branchId)
.SingleInstance();

builder.RegisterType<ResultCacher>()
.As<IResultCacher>()
.SingleInstance();

builder.RegisterType<CachingTracker>()
.As<ICachingTracker>()
.SingleInstance();
}
}
22 changes: 22 additions & 0 deletions source/Server/Caching/CachingTracker.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using SharpLab.Server.Monitoring;

namespace SharpLab.Server.Caching;

public class CachingTracker : ICachingTracker {
private readonly IMetricMonitor _cacheableRequestCountMonitor;
private readonly IMetricMonitor _noCacheRequestCountMonitor;
private readonly IMetricMonitor _blobUploadRequestCountMonitor;
private readonly IMetricMonitor _blobUploadErrorCountMonitor;

public CachingTracker(MetricMonitorFactory createMonitor) {
_cacheableRequestCountMonitor = createMonitor("caching", "Caching: Cacheable Requests");
_noCacheRequestCountMonitor = createMonitor("caching", "Caching: No-Cache Requests");
_blobUploadRequestCountMonitor = createMonitor("caching", "Caching: Blob Upload Requests");
_blobUploadErrorCountMonitor = createMonitor("caching", "Caching: Blob Upload Errors");
}

public void TrackCacheableRequest() => _cacheableRequestCountMonitor.Track(1);
public void TrackNoCacheRequest() => _noCacheRequestCountMonitor.Track(1);
public void TrackBlobUploadRequest() => _blobUploadRequestCountMonitor.Track(1);
public void TrackBlobUploadError() => _blobUploadErrorCountMonitor.Track(1);
}
8 changes: 8 additions & 0 deletions source/Server/Caching/ICachingTracker.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace SharpLab.Server.Caching;

public interface ICachingTracker {
void TrackBlobUploadError();
void TrackBlobUploadRequest();
void TrackCacheableRequest();
void TrackNoCacheRequest();
}
153 changes: 79 additions & 74 deletions source/Server/Common/CommonModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,79 +8,84 @@
using SharpLab.Server.Common.Languages;
using SharpLab.Server.Compilation;

namespace SharpLab.Server.Common {
[UsedImplicitly]
public class CommonModule : Module {
protected override void Load(ContainerBuilder builder) {
RegisterExternals(builder);

builder.RegisterInstance(MemoryPoolSlim<byte>.Shared);

builder.RegisterType<ExceptionLogFilter>()
.As<IExceptionLogFilter>()
.SingleInstance();

builder.RegisterType<AssemblyPathCollector>()
.As<IAssemblyPathCollector>()
.SingleInstance();

builder.RegisterType<PreCachedAssemblyResolver>()
.As<ICSharpCode.Decompiler.Metadata.IAssemblyResolver>()
.As<Mono.Cecil.IAssemblyResolver>()
.SingleInstance();

builder.RegisterType<LocalAssemblyDocumentationResolver>()
.As<IAssemblyDocumentationResolver>()
.SingleInstance();

builder.RegisterType<CSharpAdapter>()
.As<ILanguageAdapter>()
.SingleInstance();

builder.RegisterType<CSharpTopLevelProgramSupport>()
.As<ICSharpTopLevelProgramSupport>()
.SingleInstance();

builder.RegisterType<VisualBasicAdapter>()
.As<ILanguageAdapter>()
.SingleInstance();

builder.RegisterType<FSharpAdapter>()
.As<ILanguageAdapter>()
.SingleInstance();

builder.RegisterType<ILAdapter>()
.As<ILanguageAdapter>()
.SingleInstance();

RegisterConfiguration(builder);
}

private void RegisterConfiguration(ContainerBuilder builder) {
builder.RegisterType<LocalSecretsClient>()
.As<ISecretsClient>()
.SingleInstance()
.PreserveExistingDefaults();

builder.RegisterType<LocalFeatureFlagClient>()
.As<IFeatureFlagClient>()
.SingleInstance()
.PreserveExistingDefaults();
}

private void RegisterExternals(ContainerBuilder builder) {
builder.RegisterInstance(new RecyclableMemoryStreamManager())
.AsSelf();

// older approach, needs to be updated to use factory now
builder.RegisterInstance<Func<HttpClient>>(() => new HttpClient())
.As<Func<HttpClient>>()
.SingleInstance()
.PreserveExistingDefaults(); // allows tests and other overrides

builder.RegisterType<PortablePdbReaderProvider>()
.As<ISymbolReaderProvider>()
.SingleInstance();
}
namespace SharpLab.Server.Common;
[UsedImplicitly]
public class CommonModule : Module {
protected override void Load(ContainerBuilder builder) {
RegisterExternals(builder);

builder.RegisterInstance(MemoryPoolSlim<byte>.Shared);

builder.RegisterType<ExceptionLogFilter>()
.As<IExceptionLogFilter>()
.SingleInstance();

builder.RegisterType<AssemblyPathCollector>()
.As<IAssemblyPathCollector>()
.SingleInstance();

builder.RegisterType<PreCachedAssemblyResolver>()
.As<ICSharpCode.Decompiler.Metadata.IAssemblyResolver>()
.As<Mono.Cecil.IAssemblyResolver>()
.SingleInstance();

builder.RegisterType<LocalAssemblyDocumentationResolver>()
.As<IAssemblyDocumentationResolver>()
.SingleInstance();

builder.RegisterType<CSharpAdapter>()
.As<ILanguageAdapter>()
.SingleInstance();

builder.RegisterType<CSharpTopLevelProgramSupport>()
.As<ICSharpTopLevelProgramSupport>()
.SingleInstance();

builder.RegisterType<VisualBasicAdapter>()
.As<ILanguageAdapter>()
.SingleInstance();

builder.RegisterType<FSharpAdapter>()
.As<ILanguageAdapter>()
.SingleInstance();

builder.RegisterType<ILAdapter>()
.As<ILanguageAdapter>()
.SingleInstance();

RegisterConfiguration(builder);

var webAppName = EnvironmentHelper.GetRequiredEnvironmentVariable("SHARPLAB_WEBAPP_NAME");
builder.RegisterType<FeatureTracker>()
.As<IFeatureTracker>()
.SingleInstance()
.WithParameter("webAppName", webAppName);
}

private void RegisterConfiguration(ContainerBuilder builder) {
builder.RegisterType<LocalSecretsClient>()
.As<ISecretsClient>()
.SingleInstance()
.PreserveExistingDefaults();

builder.RegisterType<LocalFeatureFlagClient>()
.As<IFeatureFlagClient>()
.SingleInstance()
.PreserveExistingDefaults();
}

private void RegisterExternals(ContainerBuilder builder) {
builder.RegisterInstance(new RecyclableMemoryStreamManager())
.AsSelf();

// older approach, needs to be updated to use factory now
builder.RegisterInstance<Func<HttpClient>>(() => new HttpClient())
.As<Func<HttpClient>>()
.SingleInstance()
.PreserveExistingDefaults(); // allows tests and other overrides

builder.RegisterType<PortablePdbReaderProvider>()
.As<ISymbolReaderProvider>()
.SingleInstance();
}
}
51 changes: 51 additions & 0 deletions source/Server/Common/FeatureTracker.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using SharpLab.Server.Monitoring;
using System.Collections.Generic;
using System.Linq;

namespace SharpLab.Server.Common;

public class FeatureTracker : IFeatureTracker {
private readonly IMetricMonitor _branchMonitor;
private readonly IReadOnlyDictionary<string, IMetricMonitor> _languageMetricMonitors;
private readonly IReadOnlyDictionary<string, IMetricMonitor> _targetMetricMonitors;
private readonly IMetricMonitor _optimizeDebugMonitor;
private readonly IMetricMonitor _optimizeReleaseMonitor;

public FeatureTracker(MetricMonitorFactory createMonitor, string webAppName) {
_branchMonitor = createMonitor("feature", $"Branch: {webAppName}");
_languageMetricMonitors = LanguageNames.All.ToDictionary(
name => name,
name => createMonitor("feature", $"Language: {name}")
);
_targetMetricMonitors = TargetNames.All.ToDictionary(
name => name,
name => createMonitor("feature", $"Target: {name}")
);

_optimizeDebugMonitor = createMonitor("feature", "Optimize: Debug");
_optimizeReleaseMonitor = createMonitor("feature", "Optimize: Release");
}

public void TrackBranch() {
_branchMonitor.Track(1);
}

public void TrackLanguage(string languageName) {
if (_languageMetricMonitors.TryGetValue(languageName, out var metricMonitor))
metricMonitor.Track(1);
}

public void TrackTarget(string targetName) {
if (_targetMetricMonitors.TryGetValue(targetName, out var metricMonitor))
metricMonitor.Track(1);
}

public void TrackOptimize(string? optimize) {
var monitor = optimize switch {
Optimize.Debug => _optimizeDebugMonitor,
Optimize.Release => _optimizeReleaseMonitor,
_ => null
};
monitor?.Track(1);
}
}
8 changes: 8 additions & 0 deletions source/Server/Common/IFeatureTracker.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace SharpLab.Server.Common;

public interface IFeatureTracker {
void TrackBranch();
void TrackLanguage(string languageName);
void TrackTarget(string targetName);
void TrackOptimize(string? optimize);
}
21 changes: 10 additions & 11 deletions source/Server/Common/ILanguageAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,17 @@
using MirrorSharp.Advanced;
using SharpLab.Server.Common.Internal;

namespace SharpLab.Server.Common {
public interface ILanguageAdapter {
string LanguageName { get; }
namespace SharpLab.Server.Common;
public interface ILanguageAdapter {
string LanguageName { get; }

void SlowSetup(MirrorSharpOptions options);
void SetOptimize(IWorkSession session, string optimize);
void SetOptionsForTarget(IWorkSession session, string target);
void SlowSetup(MirrorSharpOptions options);
void SetOptimize(IWorkSession session, string optimize);
void SetOptionsForTarget(IWorkSession session, string target);

ImmutableArray<int> GetMethodParameterLines(IWorkSession session, int lineInMethod, int columnInMethod);
ImmutableArray<string?> GetCallArgumentIdentifiers(IWorkSession session, int callStartLine, int callStartColumn);
ImmutableArray<int> GetMethodParameterLines(IWorkSession session, int lineInMethod, int columnInMethod);
ImmutableArray<string?> GetCallArgumentIdentifiers(IWorkSession session, int callStartLine, int callStartColumn);

// Note: in some cases this Task is never resolved (e.g. if VB is never used)
AssemblyReferenceDiscoveryTask AssemblyReferenceDiscoveryTask { get; }
}
// Note: in some cases this Task is never resolved (e.g. if VB is never used)
AssemblyReferenceDiscoveryTask AssemblyReferenceDiscoveryTask { get; }
}
19 changes: 12 additions & 7 deletions source/Server/Common/LanguageNames.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
using System.Collections.Immutable;
using CodeAnalysis = Microsoft.CodeAnalysis;

namespace SharpLab.Server.Common {
public class LanguageNames {
public const string CSharp = CodeAnalysis.LanguageNames.CSharp;
public const string VisualBasic = CodeAnalysis.LanguageNames.VisualBasic;
public const string FSharp = CodeAnalysis.LanguageNames.FSharp;
public const string IL = "IL";
}
namespace SharpLab.Server.Common;
public class LanguageNames {
public const string CSharp = CodeAnalysis.LanguageNames.CSharp;
public const string VisualBasic = CodeAnalysis.LanguageNames.VisualBasic;
public const string FSharp = CodeAnalysis.LanguageNames.FSharp;
public const string IL = "IL";


public static readonly ImmutableArray<string> All = [
CSharp, VisualBasic, FSharp, IL
];
}
Loading

0 comments on commit 376ccd7

Please sign in to comment.