зеркало из https://github.com/mozilla/glean.git
Merge pull request #1099 from Dexterp37/csharp_counter_type
Bug 1648418 - Implement the C# Counter Metric
This commit is contained in:
Коммит
562649698f
|
@ -4,6 +4,7 @@
|
|||
|
||||
* C#
|
||||
* Add support for Labeled Strings and Labeled Booleans.
|
||||
* Add support for the Counter metric type and Labeled Counter.
|
||||
|
||||
# v31.6.0 (2020-07-24)
|
||||
|
||||
|
|
|
@ -105,7 +105,25 @@ assert 0 == metrics.stability.crash_count.test_get_num_recorded_errors(
|
|||
|
||||
<div data-lang="C#" class="tab">
|
||||
|
||||
TODO. To be implemented in [bug 1648437](https://bugzilla.mozilla.org/show_bug.cgi?id=1648437).
|
||||
```C#
|
||||
using static Mozilla.YourApplication.GleanMetrics.Stability;
|
||||
Stability.crashCount["uncaught_exception"].Add(); // Adds 1 to the "uncaught_exception" counter.
|
||||
Stability.crashCount["native_code_crash"].Add(3); // Adds 3 to the "native_code_crash" counter.
|
||||
```
|
||||
|
||||
There are test APIs available too:
|
||||
|
||||
```C#
|
||||
using static Mozilla.YourApplication.GleanMetrics.Stability;
|
||||
// Was anything recorded?
|
||||
Assert.True(Stability.crashCount["uncaught_exception"].TestHasValue());
|
||||
Assert.True(Stability.crashCount["native_code_crash"].TestHasValue());
|
||||
// Do the counters have the expected values?
|
||||
Assert.Equal(1, Stability.crashCount["uncaught_exception"].TestGetValue());
|
||||
Assert.Equal(3, Stability.crashCount["native_code_crash"].TestGetValue());
|
||||
// Were there any invalid labels?
|
||||
Assert.Equal(0, Stability.crashCount.TestGetNumRecordedErrors(ErrorType.InvalidLabel));
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
@ -215,6 +215,38 @@ namespace Mozilla.Glean.FFI
|
|||
[DllImport(SharedGleanLibrary, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern byte glean_boolean_test_has_value(UInt64 metric_id, string storage_name);
|
||||
|
||||
|
||||
// Counter
|
||||
|
||||
[DllImport(SharedGleanLibrary, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern UInt64 glean_new_counter_metric(
|
||||
string category,
|
||||
string name,
|
||||
string[] send_in_pings,
|
||||
Int32 send_in_pings_len,
|
||||
Int32 lifetime,
|
||||
bool disabled
|
||||
);
|
||||
|
||||
[DllImport(SharedGleanLibrary, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern void glean_destroy_counter_metric(IntPtr handle);
|
||||
|
||||
[DllImport(SharedGleanLibrary, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern void glean_counter_add(UInt64 metric_id, Int32 amount);
|
||||
|
||||
[DllImport(SharedGleanLibrary, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern Int32 glean_counter_test_get_value(UInt64 metric_id, string storage_name);
|
||||
|
||||
[DllImport(SharedGleanLibrary, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern bool glean_counter_test_has_value(UInt64 metric_id, string storage_name);
|
||||
|
||||
[DllImport(SharedGleanLibrary, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern Int32 glean_counter_test_get_num_recorded_errors(
|
||||
UInt64 metric_id,
|
||||
Int32 error_type,
|
||||
String storage_name
|
||||
);
|
||||
|
||||
// Uuid
|
||||
|
||||
[DllImport(SharedGleanLibrary, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
|
@ -314,6 +346,29 @@ namespace Mozilla.Glean.FFI
|
|||
string storage_name
|
||||
);
|
||||
|
||||
// Labeled Counter
|
||||
|
||||
[DllImport(SharedGleanLibrary, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern UInt64 glean_new_labeled_counter_metric(
|
||||
string category,
|
||||
string name,
|
||||
string[] send_in_pings,
|
||||
Int32 send_in_pings_len,
|
||||
Int32 lifetime,
|
||||
bool disabled,
|
||||
string[] labels,
|
||||
Int32 label_count
|
||||
);
|
||||
|
||||
[DllImport(SharedGleanLibrary, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern UInt64 glean_labeled_counter_metric_get(UInt64 handle, string label);
|
||||
|
||||
[DllImport(SharedGleanLibrary, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern Int32 glean_labeled_counter_test_get_num_recorded_errors(
|
||||
UInt64 metric_id,
|
||||
Int32 error_type,
|
||||
string storage_name
|
||||
);
|
||||
|
||||
// Labeled Boolean
|
||||
|
||||
|
@ -337,7 +392,7 @@ namespace Mozilla.Glean.FFI
|
|||
UInt64 metric_id,
|
||||
Int32 error_type,
|
||||
string storage_name
|
||||
);
|
||||
);
|
||||
|
||||
// Labeled string
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ namespace Mozilla.Glean.Private
|
|||
/// <summary>
|
||||
/// Set a boolean value.
|
||||
/// </summary>
|
||||
/// <param name="value"> This is a user defined boolean value.
|
||||
/// <param name="value"> This is a user defined boolean value.</param>
|
||||
public void Set(bool value)
|
||||
{
|
||||
if (disabled)
|
||||
|
|
|
@ -0,0 +1,144 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
using Mozilla.Glean.FFI;
|
||||
using System;
|
||||
|
||||
namespace Mozilla.Glean.Private
|
||||
{
|
||||
/// <summary>
|
||||
/// This implements the developer facing API for recording counter metrics.
|
||||
///
|
||||
/// Instances of this class type are automatically generated by the parsers at build time,
|
||||
/// allowing developers to record values that were previously registered in the metrics.yaml file.
|
||||
///
|
||||
/// The internal constructor is only used by [LabeledMetricType] directly.
|
||||
/// </summary>
|
||||
public sealed class CounterMetricType : ILabeledSubmetricInterface
|
||||
{
|
||||
private bool disabled;
|
||||
private string[] sendInPings;
|
||||
private UInt64 handle;
|
||||
|
||||
/// <summary>
|
||||
/// The public constructor used by automatically generated metrics.
|
||||
/// </summary>
|
||||
public CounterMetricType(
|
||||
bool disabled,
|
||||
string category,
|
||||
Lifetime lifetime,
|
||||
string name,
|
||||
string[] sendInPings
|
||||
) : this(0, disabled, sendInPings)
|
||||
{
|
||||
handle = LibGleanFFI.glean_new_counter_metric(
|
||||
category: category,
|
||||
name: name,
|
||||
send_in_pings: sendInPings,
|
||||
send_in_pings_len: sendInPings.Length,
|
||||
lifetime: (int)lifetime,
|
||||
disabled: disabled);
|
||||
}
|
||||
|
||||
internal CounterMetricType(
|
||||
UInt64 handle,
|
||||
bool disabled,
|
||||
string[] sendInPings
|
||||
)
|
||||
{
|
||||
this.disabled = disabled;
|
||||
this.sendInPings = sendInPings;
|
||||
this.handle = handle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add to counter value.
|
||||
/// </summary>
|
||||
/// <param name="amount">this is the amount to increment the counter by, defaulting to
|
||||
/// 1 if called without parameters.</param>
|
||||
public void Add(Int32 amount = 1)
|
||||
{
|
||||
if (disabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Dispatchers.LaunchAPI(() => {
|
||||
AddSync(amount);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add to counter value synchronously.
|
||||
///
|
||||
/// This is only to be used within the Glean SDK.
|
||||
/// </summary>
|
||||
/// <param name="amount">this is the amount to increment the counter by, defaulting to 1
|
||||
/// if called without parameters.</param>
|
||||
internal void AddSync(Int32 amount)
|
||||
{
|
||||
if (disabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LibGleanFFI.glean_counter_add(handle, amount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether a value is stored for the metric for testing purposes only. This function will
|
||||
/// attempt to await the last task (if any) writing to the the metric's storage engine before
|
||||
/// returning a value.
|
||||
/// </summary>
|
||||
/// <param name="pingName">represents the name of the ping to retrieve the metric for Defaults
|
||||
/// to the first value in `sendInPings`</param>
|
||||
/// <returns>true if metric value exists, otherwise false</returns>
|
||||
public bool TestHasValue(string pingName = null)
|
||||
{
|
||||
Dispatchers.AssertInTestingMode();
|
||||
|
||||
string ping = pingName ?? sendInPings[0];
|
||||
return LibGleanFFI.glean_counter_test_has_value(handle, ping);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the stored value for testing purposes only. This function will attempt to await the
|
||||
/// last task (if any) writing to the the metric's storage engine before returning a value.
|
||||
/// @throws [NullPointerException] if no value is stored
|
||||
/// </summary>
|
||||
/// <param name="pingName">represents the name of the ping to retrieve the metric for.
|
||||
/// Defaults to the first value in `sendInPings`</param>
|
||||
/// <returns>value of the stored metric</returns>
|
||||
/// <exception cref="System.NullReferenceException">Thrown when the metric contains no value</exception>
|
||||
public Int32 TestGetValue(string pingName = null)
|
||||
{
|
||||
Dispatchers.AssertInTestingMode();
|
||||
|
||||
if (!TestHasValue(pingName))
|
||||
{
|
||||
throw new NullReferenceException();
|
||||
}
|
||||
|
||||
string ping = pingName ?? sendInPings[0];
|
||||
return LibGleanFFI.glean_counter_test_get_value(handle, ping);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of errors recorded for the given metric.
|
||||
/// </summary>
|
||||
/// <param name="errorType">the type of the error recorded.</param>
|
||||
/// <param name="pingName">represents the name of the ping to retrieve the metric for.
|
||||
/// Defaults to the first value in `sendInPings`.</param>
|
||||
/// <returns>the number of errors recorded for the metric.</returns>
|
||||
public Int32 TestGetNumRecordedErrors(Testing.ErrorType errorType, string pingName = null)
|
||||
{
|
||||
Dispatchers.AssertInTestingMode();
|
||||
|
||||
string ping = pingName ?? sendInPings[0];
|
||||
return LibGleanFFI.glean_counter_test_get_num_recorded_errors(
|
||||
handle, (int)errorType, ping
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -59,6 +59,9 @@ namespace Mozilla.Glean.Private
|
|||
case BooleanMetricType _:
|
||||
metricTypeInstantiator = LibGleanFFI.glean_new_labeled_boolean_metric;
|
||||
break;
|
||||
case CounterMetricType _:
|
||||
metricTypeInstantiator = LibGleanFFI.glean_new_labeled_counter_metric;
|
||||
break;
|
||||
case StringMetricType _:
|
||||
metricTypeInstantiator = LibGleanFFI.glean_new_labeled_string_metric;
|
||||
break;
|
||||
|
@ -110,6 +113,11 @@ namespace Mozilla.Glean.Private
|
|||
UInt64 handle = LibGleanFFI.glean_labeled_boolean_metric_get(this.handle, label);
|
||||
return (T)(ILabeledSubmetricInterface)new BooleanMetricType(handle, disabled, sendInPings);
|
||||
}
|
||||
case CounterMetricType _:
|
||||
{
|
||||
UInt64 handle = LibGleanFFI.glean_labeled_counter_metric_get(this.handle, label);
|
||||
return (T)(ILabeledSubmetricInterface)new CounterMetricType(handle, disabled, sendInPings);
|
||||
}
|
||||
case StringMetricType _:
|
||||
{
|
||||
UInt64 handle = LibGleanFFI.glean_labeled_string_metric_get(this.handle, label);
|
||||
|
@ -141,6 +149,10 @@ namespace Mozilla.Glean.Private
|
|||
{
|
||||
return LibGleanFFI.glean_labeled_boolean_test_get_num_recorded_errors(handle, (int)errorType, ping);
|
||||
}
|
||||
case CounterMetricType _:
|
||||
{
|
||||
return LibGleanFFI.glean_labeled_counter_test_get_num_recorded_errors(handle, (int)errorType, ping);
|
||||
}
|
||||
case StringMetricType _:
|
||||
{
|
||||
return LibGleanFFI.glean_labeled_string_test_get_num_recorded_errors(handle, (int)errorType, ping);
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
using Mozilla.Glean.Testing;
|
||||
using System;
|
||||
using System.IO;
|
||||
using Xunit;
|
||||
using static Mozilla.Glean.Glean;
|
||||
|
||||
namespace Mozilla.Glean.Tests.Metrics
|
||||
{
|
||||
public class CounterMetricTypeTest
|
||||
{
|
||||
public CounterMetricTypeTest()
|
||||
{
|
||||
// Get a random test directory just for this single test.
|
||||
string tempDataDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
|
||||
|
||||
// In xUnit, the constructor will be called before each test. This
|
||||
// feels like a natural place to initialize / reset Glean.
|
||||
GleanInstance.Reset(
|
||||
applicationId: "org.mozilla.csharp.tests",
|
||||
applicationVersion: "1.0-test",
|
||||
uploadEnabled: true,
|
||||
configuration: new Configuration(),
|
||||
dataDir: tempDataDir
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void APISavesToStorage()
|
||||
{
|
||||
Private.CounterMetricType counterMetric = new Private.CounterMetricType(
|
||||
category: "telemetry",
|
||||
disabled: false,
|
||||
lifetime: Private.Lifetime.Application,
|
||||
name: "counter_metric",
|
||||
sendInPings: new string[] { "store1" }
|
||||
);
|
||||
|
||||
Assert.False(counterMetric.TestHasValue());
|
||||
|
||||
// Add to the counter a couple of times with a little delay. The first call will check
|
||||
// calling add() without parameters to test increment by 1.
|
||||
counterMetric.Add();
|
||||
|
||||
// Check that the count was incremented and properly recorded.
|
||||
Assert.True(counterMetric.TestHasValue());
|
||||
Assert.Equal(1, counterMetric.TestGetValue());
|
||||
|
||||
counterMetric.Add(10);
|
||||
// Check that count was incremented and properly recorded. This second call will check
|
||||
// calling add() with 10 to test increment by other amount
|
||||
Assert.True(counterMetric.TestHasValue());
|
||||
Assert.Equal(11, counterMetric.TestGetValue());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DisabledCountersMustNotRecordData()
|
||||
{
|
||||
Private.CounterMetricType counterMetric = new Private.CounterMetricType(
|
||||
category: "telemetry",
|
||||
disabled: true,
|
||||
lifetime: Private.Lifetime.Application,
|
||||
name: "counter_metric",
|
||||
sendInPings: new string[] { "store1" }
|
||||
);
|
||||
|
||||
// Attempt to store the counter.
|
||||
counterMetric.Add();
|
||||
// Check that nothing was recorded.
|
||||
Assert.False(counterMetric.TestHasValue(), "Counters must not be recorded if they are disabled");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestGetValueThrows()
|
||||
{
|
||||
Private.CounterMetricType counterMetric = new Private.CounterMetricType(
|
||||
category: "telemetry",
|
||||
disabled: true,
|
||||
lifetime: Private.Lifetime.Application,
|
||||
name: "counter_metric",
|
||||
sendInPings: new string[] { "store1" }
|
||||
);
|
||||
Assert.Throws<NullReferenceException>(() => counterMetric.TestGetValue());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void APISavesToSecondaryPings()
|
||||
{
|
||||
Private.CounterMetricType counterMetric = new Private.CounterMetricType(
|
||||
category: "telemetry",
|
||||
disabled: false,
|
||||
lifetime: Private.Lifetime.Application,
|
||||
name: "counter_metric",
|
||||
sendInPings: new string[] { "store1", "store2" }
|
||||
);
|
||||
|
||||
// Add to the counter a couple of times with a little delay. The first call will check
|
||||
// calling add() without parameters to test increment by 1.
|
||||
counterMetric.Add();
|
||||
|
||||
// Check that the count was incremented and properly recorded for the second ping.
|
||||
Assert.True(counterMetric.TestHasValue("store2"));
|
||||
Assert.Equal(1, counterMetric.TestGetValue("store2"));
|
||||
|
||||
counterMetric.Add(10);
|
||||
// Check that count was incremented and properly recorded for the second ping.
|
||||
// This second call will check calling add() with 10 to test increment by other amount
|
||||
Assert.True(counterMetric.TestHasValue("store2"));
|
||||
Assert.Equal(11, counterMetric.TestGetValue("store2"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NegativeValuesAreNotCounted()
|
||||
{
|
||||
Private.CounterMetricType counterMetric = new Private.CounterMetricType(
|
||||
category: "telemetry",
|
||||
disabled: false,
|
||||
lifetime: Private.Lifetime.Application,
|
||||
name: "counter_metric",
|
||||
sendInPings: new string[] { "store1" }
|
||||
);
|
||||
|
||||
// Increment to 1 (initial value)
|
||||
counterMetric.Add();
|
||||
|
||||
// Check that the count was incremented
|
||||
Assert.True(counterMetric.TestHasValue("store1"));
|
||||
Assert.Equal(1, counterMetric.TestGetValue("store1"));
|
||||
|
||||
counterMetric.Add(-10);
|
||||
// Check that count was NOT incremented.
|
||||
Assert.True(counterMetric.TestHasValue("store1"));
|
||||
Assert.Equal(1, counterMetric.TestGetValue("store1"));
|
||||
Assert.Equal(1, counterMetric.TestGetNumRecordedErrors(ErrorType.InvalidValue));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
using Mozilla.Glean.Private;
|
||||
using Mozilla.Glean.Testing;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Xunit;
|
||||
using static Mozilla.Glean.Glean;
|
||||
|
@ -13,11 +14,11 @@ namespace Mozilla.Glean.Tests.Metrics
|
|||
{
|
||||
public class LabeledMetricTypeTest
|
||||
{
|
||||
// Get a random test directory just for this single test.
|
||||
string TempDataDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
|
||||
|
||||
public LabeledMetricTypeTest()
|
||||
{
|
||||
// Get a random test directory just for this single test.
|
||||
string tempDataDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
|
||||
|
||||
// In xUnit, the constructor will be called before each test. This
|
||||
// feels like a natural place to initialize / reset Glean.
|
||||
GleanInstance.Reset(
|
||||
|
@ -25,38 +26,201 @@ namespace Mozilla.Glean.Tests.Metrics
|
|||
applicationVersion: "1.0-test",
|
||||
uploadEnabled: true,
|
||||
configuration: new Configuration(),
|
||||
dataDir: tempDataDir
|
||||
dataDir: TempDataDir
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestLabeledCounterType()
|
||||
{
|
||||
// TODO: Placeholder. Implement in bug 1648437 by converting the Kotlin test.
|
||||
CounterMetricType counterMetric = new CounterMetricType(
|
||||
disabled: false,
|
||||
category: "telemetry",
|
||||
lifetime: Lifetime.Application,
|
||||
name: "labeled_counter_metric",
|
||||
sendInPings: new string[] { "metrics" }
|
||||
);
|
||||
|
||||
var labeledCounterMetric = new LabeledMetricType<CounterMetricType>(
|
||||
disabled: false,
|
||||
category: "telemetry",
|
||||
lifetime: Lifetime.Application,
|
||||
name: "labeled_counter_metric",
|
||||
sendInPings: new string[] { "metrics" },
|
||||
submetric: counterMetric
|
||||
);
|
||||
|
||||
labeledCounterMetric["label1"].Add(1);
|
||||
labeledCounterMetric["label2"].Add(2);
|
||||
|
||||
// Record a regular non-labeled counter. This isn't normally
|
||||
// possible with the generated code because the subMetric is private,
|
||||
// but it's useful to test here that it works.
|
||||
counterMetric.Add(3);
|
||||
|
||||
Assert.True(labeledCounterMetric["label1"].TestHasValue());
|
||||
Assert.Equal(1, labeledCounterMetric["label1"].TestGetValue());
|
||||
|
||||
Assert.True(labeledCounterMetric["label2"].TestHasValue());
|
||||
Assert.Equal(2, labeledCounterMetric["label2"].TestGetValue());
|
||||
|
||||
Assert.True(counterMetric.TestHasValue());
|
||||
Assert.Equal(3, counterMetric.TestGetValue());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestOtherLabelWithPredefinedLabels()
|
||||
{
|
||||
// TODO: Placeholder. Implement in bug 1648437 by converting the Kotlin test.
|
||||
CounterMetricType counterMetric = new CounterMetricType(
|
||||
disabled: false,
|
||||
category: "telemetry",
|
||||
lifetime: Lifetime.Application,
|
||||
name: "labeled_counter_metric",
|
||||
sendInPings: new string[] { "metrics" }
|
||||
);
|
||||
|
||||
var labeledCounterMetric = new LabeledMetricType<CounterMetricType>(
|
||||
disabled: false,
|
||||
category: "telemetry",
|
||||
lifetime: Lifetime.Application,
|
||||
name: "labeled_counter_metric",
|
||||
sendInPings: new string[] { "metrics" },
|
||||
submetric: counterMetric,
|
||||
labels: new HashSet<string>() { "foo", "bar", "baz" }
|
||||
);
|
||||
|
||||
labeledCounterMetric["foo"].Add(1);
|
||||
labeledCounterMetric["foo"].Add(2);
|
||||
labeledCounterMetric["bar"].Add(1);
|
||||
labeledCounterMetric["not_there"].Add(1);
|
||||
labeledCounterMetric["also_not_there"].Add(1);
|
||||
labeledCounterMetric["not_me"].Add(1);
|
||||
|
||||
Assert.Equal(3, labeledCounterMetric["foo"].TestGetValue());
|
||||
Assert.Equal(1, labeledCounterMetric["bar"].TestGetValue());
|
||||
Assert.False(labeledCounterMetric["baz"].TestHasValue());
|
||||
// The rest all lands in the __other__ bucket
|
||||
Assert.Equal(3, labeledCounterMetric["not_there"].TestGetValue());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestOtherLabelWithoutPredefinedLabels()
|
||||
{
|
||||
// TODO: Placeholder. Implement in bug 1648437 by converting the Kotlin test.
|
||||
CounterMetricType counterMetric = new CounterMetricType(
|
||||
disabled: false,
|
||||
category: "telemetry",
|
||||
lifetime: Lifetime.Application,
|
||||
name: "labeled_counter_metric",
|
||||
sendInPings: new string[] { "metrics" }
|
||||
);
|
||||
|
||||
var labeledCounterMetric = new LabeledMetricType<CounterMetricType>(
|
||||
disabled: false,
|
||||
category: "telemetry",
|
||||
lifetime: Lifetime.Application,
|
||||
name: "labeled_counter_metric",
|
||||
sendInPings: new string[] { "metrics" },
|
||||
submetric: counterMetric
|
||||
);
|
||||
|
||||
for (int i = 0; i <= 20; i++)
|
||||
{
|
||||
labeledCounterMetric[$"label_{i}"].Add(1);
|
||||
}
|
||||
// Go back and record in one of the real labels again
|
||||
labeledCounterMetric["label_0"].Add(1);
|
||||
|
||||
Assert.Equal(2, labeledCounterMetric["label_0"].TestGetValue());
|
||||
for (int i = 1; i <= 15; i++)
|
||||
{
|
||||
Assert.Equal(1, labeledCounterMetric[$"label_{i}"].TestGetValue());
|
||||
}
|
||||
Assert.Equal(5, labeledCounterMetric["__other__"].TestGetValue());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestOtherLabelWithoutPredefinedLabelsBeforeGleanInits()
|
||||
{
|
||||
// TODO: Placeholder. Implement in bug 1648437 by converting the Kotlin test.
|
||||
CounterMetricType counterMetric = new CounterMetricType(
|
||||
disabled: false,
|
||||
category: "telemetry",
|
||||
lifetime: Lifetime.Application,
|
||||
name: "labeled_counter_metric",
|
||||
sendInPings: new string[] { "metrics" }
|
||||
);
|
||||
|
||||
var labeledCounterMetric = new LabeledMetricType<CounterMetricType>(
|
||||
disabled: false,
|
||||
category: "telemetry",
|
||||
lifetime: Lifetime.Application,
|
||||
name: "labeled_counter_metric",
|
||||
sendInPings: new string[] { "metrics" },
|
||||
submetric: counterMetric
|
||||
);
|
||||
|
||||
// Make sure Glean isn't initialized, and turn task queueing on
|
||||
GleanInstance.TestDestroyGleanHandle();
|
||||
Dispatchers.QueueInitialTasks = true;
|
||||
|
||||
for (int i = 0; i <= 20; i++)
|
||||
{
|
||||
labeledCounterMetric[$"label_{i}"].Add(1);
|
||||
}
|
||||
// Go back and record in one of the real labels again
|
||||
labeledCounterMetric["label_0"].Add(1);
|
||||
|
||||
// Initialize glean
|
||||
GleanInstance.Initialize(
|
||||
applicationId: "org.mozilla.csharp.tests",
|
||||
applicationVersion: "1.0-test",
|
||||
uploadEnabled: true,
|
||||
configuration: new Configuration(),
|
||||
dataDir: TempDataDir
|
||||
);
|
||||
|
||||
Assert.Equal(2, labeledCounterMetric["label_0"].TestGetValue());
|
||||
for (int i = 1; i <= 15; i++)
|
||||
{
|
||||
Assert.Equal(1, labeledCounterMetric[$"label_{i}"].TestGetValue());
|
||||
}
|
||||
Assert.Equal(5, labeledCounterMetric["__other__"].TestGetValue());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EnsureInvalidLabelsOnLabeledCounterGoToOther()
|
||||
{
|
||||
// TODO: Placeholder. Implement in bug 1648437 by converting the Kotlin test.
|
||||
CounterMetricType counterMetric = new CounterMetricType(
|
||||
disabled: false,
|
||||
category: "telemetry",
|
||||
lifetime: Lifetime.Application,
|
||||
name: "labeled_counter_metric",
|
||||
sendInPings: new string[] { "metrics" }
|
||||
);
|
||||
|
||||
var labeledCounterMetric = new LabeledMetricType<CounterMetricType>(
|
||||
disabled: false,
|
||||
category: "telemetry",
|
||||
lifetime: Lifetime.Application,
|
||||
name: "labeled_counter_metric",
|
||||
sendInPings: new string[] { "metrics" },
|
||||
submetric: counterMetric
|
||||
);
|
||||
|
||||
labeledCounterMetric["notSnakeCase"].Add(1);
|
||||
labeledCounterMetric[""].Add(1);
|
||||
labeledCounterMetric["with/slash"].Add(1);
|
||||
labeledCounterMetric["this_string_has_more_than_thirty_characters"].Add(1);
|
||||
|
||||
Assert.Equal(
|
||||
4,
|
||||
labeledCounterMetric.TestGetNumRecordedErrors(
|
||||
ErrorType.InvalidLabel
|
||||
)
|
||||
);
|
||||
Assert.Equal(
|
||||
4,
|
||||
labeledCounterMetric["__other__"].TestGetValue()
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
Загрузка…
Ссылка в новой задаче