Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/EmulatorPolicyChecklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ Track progress of emulator policy handler implementation. Each policy needs a ha
| ⬜ | CacheLookup | CacheLookupHandler.cs | Store interaction | `emulator/cache-lookup` |
| ⬜ | CacheStore | CacheStoreHandler.cs | Store interaction | `emulator/cache-store` |
| ⬜ | Cors | CorsHandler.cs | Context mutation | `emulator/cors` |
| | EmitMetric | EmitMetricHandler.cs | No-op + callbacks | `emulator/emit-metric` |
| | EmitMetric | EmitMetricHandler.cs | No-op + callbacks | `emulator/emit-metric` |
| ⬜ | ForwardRequest | ForwardRequestHandler.cs | External service mock | `emulator/forward-request` |
| ⬜ | JsonP | JsonPHandler.cs | Context mutation | `emulator/jsonp` |
| ⬜ | JsonToXml | JsonToXmlHandle.cs | No-op + callbacks | `emulator/json-to-xml` |
Expand Down
3 changes: 3 additions & 0 deletions src/Testing/Document/TestDocumentExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ public static ResponseExampleStore SetupResponseExampleStore(this TestDocument d
public static LoggerStore SetupLoggerStore(this TestDocument document) =>
document.Context.LoggerStore;

public static MetricStore SetupMetricStore(this TestDocument document) =>
document.Context.MetricStore;

public static RateLimitStore SetupRateLimitStore(this TestDocument document) =>
document.Context.RateLimitStore;
}
12 changes: 12 additions & 0 deletions src/Testing/Emulator/Data/EmittedMetric.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using Microsoft.Azure.ApiManagement.PolicyToolkit.Authoring;

namespace Microsoft.Azure.ApiManagement.PolicyToolkit.Testing.Emulator.Data;

public record EmittedMetric(
string Name,
double Value,
string? Namespace,
MetricDimensionConfig[] Dimensions);
13 changes: 13 additions & 0 deletions src/Testing/Emulator/Data/MetricStore.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System.Collections.Immutable;

namespace Microsoft.Azure.ApiManagement.PolicyToolkit.Testing.Emulator.Data;

public class MetricStore
{
internal readonly IList<EmittedMetric> MetricsInternal = new List<EmittedMetric>();

public ImmutableArray<EmittedMetric> Metrics => MetricsInternal.ToImmutableArray();
}
9 changes: 8 additions & 1 deletion src/Testing/Emulator/Policies/EmitMetricHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the MIT License.

using Microsoft.Azure.ApiManagement.PolicyToolkit.Authoring;
using Microsoft.Azure.ApiManagement.PolicyToolkit.Testing.Emulator.Data;

namespace Microsoft.Azure.ApiManagement.PolicyToolkit.Testing.Emulator.Policies;

Expand All @@ -16,6 +17,12 @@ internal class EmitMetricHandler : PolicyHandler<EmitMetricConfig>

protected override void Handle(GatewayContext context, EmitMetricConfig config)
{
throw new NotImplementedException();
var metric = new EmittedMetric(
config.Name,
config.Value ?? 1,
config.Namespace,
config.Dimensions);

context.MetricStore.MetricsInternal.Add(metric);
}
}
1 change: 1 addition & 0 deletions src/Testing/GatewayContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public class GatewayContext : MockExpressionContext
internal readonly CacheStore CacheStore = new();
internal readonly ResponseExampleStore ResponseExampleStore = new();
internal readonly LoggerStore LoggerStore = new();
internal readonly MetricStore MetricStore = new();
internal readonly RateLimitStore RateLimitStore = new();

public GatewayContext()
Expand Down
145 changes: 145 additions & 0 deletions test/Test.Testing/Emulator/Policies/EmitMetricTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using Microsoft.Azure.ApiManagement.PolicyToolkit.Authoring;
using Microsoft.Azure.ApiManagement.PolicyToolkit.Testing;
using Microsoft.Azure.ApiManagement.PolicyToolkit.Testing.Document;

namespace Test.Emulator.Emulator.Policies;

[TestClass]
public class EmitMetricTests
{
class SimpleEmitMetric : IDocument
{
public void Inbound(IInboundContext context)
{
context.EmitMetric(new EmitMetricConfig
{
Name = "my-metric",
Value = 1,
Dimensions = [new MetricDimensionConfig { Name = "region", Value = "west" }]
});
}

public void Outbound(IOutboundContext context)
{
context.EmitMetric(new EmitMetricConfig
{
Name = "outbound-metric",
Value = 2.5,
Dimensions = [new MetricDimensionConfig { Name = "status" }]
});
}

public void OnError(IOnErrorContext context)
{
context.EmitMetric(new EmitMetricConfig
{
Name = "error-metric",
Value = 1,
Dimensions = [new MetricDimensionConfig { Name = "error-type" }]
});
}
}

class MultiEmitMetric : IDocument
{
public void Inbound(IInboundContext context)
{
context.EmitMetric(new EmitMetricConfig
{
Name = "metric-a",
Dimensions = [new MetricDimensionConfig { Name = "dim" }]
});
context.EmitMetric(new EmitMetricConfig
{
Name = "metric-b",
Value = 5,
Dimensions = [new MetricDimensionConfig { Name = "dim" }]
});
}
}

[TestMethod]
public void EmitMetric_Inbound()
{
var test = new SimpleEmitMetric().AsTestDocument();

test.RunInbound();

var metrics = test.SetupMetricStore().Metrics;
metrics.Should().HaveCount(1);
metrics[0].Name.Should().Be("my-metric");
metrics[0].Value.Should().Be(1);
metrics[0].Dimensions.Should().HaveCount(1);
metrics[0].Dimensions[0].Name.Should().Be("region");
}

[TestMethod]
public void EmitMetric_Outbound()
{
var test = new SimpleEmitMetric().AsTestDocument();

test.RunOutbound();

var metrics = test.SetupMetricStore().Metrics;
metrics.Should().HaveCount(1);
metrics[0].Name.Should().Be("outbound-metric");
metrics[0].Value.Should().Be(2.5);
}

[TestMethod]
public void EmitMetric_OnError()
{
var test = new SimpleEmitMetric().AsTestDocument();

test.RunOnError();

var metrics = test.SetupMetricStore().Metrics;
metrics.Should().HaveCount(1);
metrics[0].Name.Should().Be("error-metric");
}

[TestMethod]
public void EmitMetric_DefaultValueIsOne()
{
var test = new MultiEmitMetric().AsTestDocument();

test.RunInbound();

var metrics = test.SetupMetricStore().Metrics;
metrics[0].Value.Should().Be(1);
}

[TestMethod]
public void EmitMetric_MultipleMetricsCollected()
{
var test = new MultiEmitMetric().AsTestDocument();

test.RunInbound();

var metrics = test.SetupMetricStore().Metrics;
metrics.Should().HaveCount(2);
metrics[0].Name.Should().Be("metric-a");
metrics[1].Name.Should().Be("metric-b");
metrics[1].Value.Should().Be(5);
}

[TestMethod]
public void EmitMetric_Callback()
{
var test = new SimpleEmitMetric().AsTestDocument();
var callbackExecuted = false;
test.SetupInbound().EmitMetric().WithCallback((_, config) =>
{
callbackExecuted = true;
config.Name.Should().Be("my-metric");
});

test.RunInbound();

callbackExecuted.Should().BeTrue();
test.SetupMetricStore().Metrics.Should().BeEmpty();
}
}
Loading