Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…etry-dotnet into metrics
  • Loading branch information
victlu committed May 5, 2021
2 parents 6e6ff21 + c8d8b8c commit 7e7306b
Show file tree
Hide file tree
Showing 20 changed files with 1,401 additions and 13 deletions.
6 changes: 6 additions & 0 deletions OpenTelemetry.sln
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "exception-reporting", "docs
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "customizing-the-sdk", "docs\trace\customizing-the-sdk\customizing-the-sdk.csproj", "{64E3D8BB-93AB-4571-93F7-ED8D64DFFD06}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Diagnostics.Metrics.Temp", "src\System.Diagnostics.Metrics.Temp\System.Diagnostics.Metrics.Temp.csproj", "{4481390E-52F5-46A6-8510-3B1433ABAFE6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -405,6 +407,10 @@ Global
{64E3D8BB-93AB-4571-93F7-ED8D64DFFD06}.Debug|Any CPU.Build.0 = Debug|Any CPU
{64E3D8BB-93AB-4571-93F7-ED8D64DFFD06}.Release|Any CPU.ActiveCfg = Release|Any CPU
{64E3D8BB-93AB-4571-93F7-ED8D64DFFD06}.Release|Any CPU.Build.0 = Release|Any CPU
{4481390E-52F5-46A6-8510-3B1433ABAFE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4481390E-52F5-46A6-8510-3B1433ABAFE6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4481390E-52F5-46A6-8510-3B1433ABAFE6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4481390E-52F5-46A6-8510-3B1433ABAFE6}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
4 changes: 0 additions & 4 deletions src/OpenTelemetry.Api/OpenTelemetry.Api.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,4 @@
<PackageReference Include="System.Reflection.Emit.Lightweight" Version="$(SystemReflectionEmitLightweightPkgVer)" />
</ItemGroup>

<ItemGroup>
<Folder Include="Metrics\" />
</ItemGroup>

</Project>
148 changes: 148 additions & 0 deletions src/OpenTelemetry/Metrics/MeterProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
// <copyright file="MeterProvider.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics.Metrics;
using System.Threading;
using System.Threading.Tasks;

#nullable enable

namespace OpenTelemetry.Metrics
{
public class MeterProvider
: IDisposable
{
private BuildOptions options;
private ConcurrentDictionary<Meter, int> meters;
private MeterListener listener;
private CancellationTokenSource cts;
private Task observerTask;

internal MeterProvider(BuildOptions options)
{
this.options = options;

this.meters = new ConcurrentDictionary<Meter, int>();

this.listener = new MeterListener()
{
InstrumentPublished = (instrument, listener) => this.InstrumentPublished(instrument, listener),
MeasurementsCompleted = (instrument, state) => this.MeasurementsCompleted(instrument, state),
};
this.listener.SetMeasurementEventCallback<double>((i, m, l, c) => this.MeasurementRecorded(i, m, l, c));
this.listener.SetMeasurementEventCallback<float>((i, m, l, c) => this.MeasurementRecorded(i, m, l, c));
this.listener.SetMeasurementEventCallback<long>((i, m, l, c) => this.MeasurementRecorded(i, m, l, c));
this.listener.SetMeasurementEventCallback<int>((i, m, l, c) => this.MeasurementRecorded(i, m, l, c));
this.listener.SetMeasurementEventCallback<short>((i, m, l, c) => this.MeasurementRecorded(i, m, l, c));
this.listener.SetMeasurementEventCallback<byte>((i, m, l, c) => this.MeasurementRecorded(i, m, l, c));

this.listener.Start();

this.cts = new CancellationTokenSource();

var token = this.cts.Token;
this.observerTask = Task.Run(async () =>
{
while (!token.IsCancellationRequested)
{
try
{
await Task.Delay(this.options.ObservationPeriodMilliseconds, token);
}
catch (TaskCanceledException)
{
}

this.listener.RecordObservableInstruments();
}
});
}

public Meter GetMeter(string name, string version)
{
var meter = new Meter(name, version);
this.meters.TryAdd(meter, 0);

return meter;
}

public void Dispose()
{
this.cts.Cancel();
this.observerTask.Wait();
}

internal void InstrumentPublished(Instrument instrument, MeterListener listener)
{
bool isInclude = false;

if (this.options.IncludeMeters != null && this.options.IncludeMeters.Length > 0)
{
foreach (var meterFunc in this.options.IncludeMeters)
{
if (meterFunc(instrument))
{
isInclude = true;
break;
}
}
}
else
{
isInclude = this.meters.TryGetValue(instrument.Meter, out var _);
}

if (isInclude)
{
// Enable this Instrument if it should be included.
listener.EnableMeasurementEvents(instrument, null);

if (this.options.Verbose)
{
Console.WriteLine($"Instrument {instrument.Meter.Name}:{instrument.Name} published.");
}
}
}

internal void MeasurementsCompleted(Instrument instrument, object? state)
{
if (this.options.Verbose)
{
Console.WriteLine($"Instrument {instrument.Meter.Name}:{instrument.Name} completed.");
}
}

internal void MeasurementRecorded<T>(Instrument instrument, T value, ReadOnlySpan<KeyValuePair<string, object?>> attribs, object? state)
{
if (this.options.Verbose)
{
Console.WriteLine($"Instrument {instrument.Meter.Name}:{instrument.Name} recorded {value}.");
}
}

internal class BuildOptions
{
public Func<Instrument, bool>[] IncludeMeters { get; set; } = new Func<Instrument, bool>[0];

public bool Verbose { get; set; } = true;

public int ObservationPeriodMilliseconds { get; set; } = 1000;
}
}
}
56 changes: 56 additions & 0 deletions src/OpenTelemetry/Metrics/MeterProviderBuilderSdk.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// <copyright file="MeterProviderBuilderSdk.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>

using System;
using System.Collections.Generic;
using System.Diagnostics.Metrics;

namespace OpenTelemetry.Metrics
{
public class MeterProviderBuilderSdk
{
private List<Func<Instrument, bool>> includeMeters = new List<Func<Instrument, bool>>();
private MeterProvider.BuildOptions options = new MeterProvider.BuildOptions();

public MeterProviderBuilderSdk()
{
}

public MeterProviderBuilderSdk IncludeInstrument(Func<Instrument, bool> meterFunc)
{
this.includeMeters.Add(meterFunc);
return this;
}

public MeterProviderBuilderSdk SetObservationPeriod(int periodMilli)
{
this.options.ObservationPeriodMilliseconds = periodMilli;
return this;
}

public MeterProviderBuilderSdk Verbose(bool verbose)
{
this.options.Verbose = verbose;
return this;
}

public MeterProvider Build()
{
this.options.IncludeMeters = this.includeMeters.ToArray();
return new MeterProvider(this.options);
}
}
}
6 changes: 1 addition & 5 deletions src/OpenTelemetry/OpenTelemetry.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,7 @@

<ItemGroup>
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Api\OpenTelemetry.Api.csproj" />
</ItemGroup>

<ItemGroup>
<Folder Include="Metrics\Aggregators\" />
<Folder Include="Metrics\Export\" />
<ProjectReference Include="$(RepoRoot)\src\System.Diagnostics.Metrics.Temp\System.Diagnostics.Metrics.Temp.csproj" />
</ItemGroup>

</Project>
98 changes: 98 additions & 0 deletions src/System.Diagnostics.Metrics.Temp/Counter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// <copyright file="Counter.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>

using System.Collections.Generic;

#nullable enable

namespace System.Diagnostics.Metrics
{
/// <summary>
/// The counter is a non-observable Instrument that supports non-negative increments.
/// e.g. Number of completed requests.
/// </summary>
/// <typeparam name="T">TBD.</typeparam>
public sealed class Counter<T> : Instrument<T>
where T : unmanaged
{
internal Counter(Meter meter, string name, string? description, string? unit)
: base(meter, name, description, unit)
{
this.Publish();
}

/// <summary>
/// TBD.
/// </summary>
public void Add(T measurement)
{
this.RecordMeasurement(measurement);
}

/// <summary>
/// TBD.
/// </summary>
public void Add(
T measurement,
KeyValuePair<string, object?> tag1)
{
this.RecordMeasurement(measurement, tag1);
}

/// <summary>
/// TBD.
/// </summary>
public void Add(
T measurement,
KeyValuePair<string, object?> tag1,
KeyValuePair<string, object?> tag2)
{
this.RecordMeasurement(measurement, tag1, tag2);
}

/// <summary>
/// TBD.
/// </summary>
public void Add(
T measurement,
KeyValuePair<string, object?> tag1,
KeyValuePair<string, object?> tag2,
KeyValuePair<string, object?> tag3)
{
this.RecordMeasurement(measurement, tag1, tag2, tag3);
}

/// <summary>
/// TBD.
/// </summary>
public void Add(
T measurement,
ReadOnlySpan<KeyValuePair<string, object?>> tags)
{
this.RecordMeasurement(measurement, tags);
}

/// <summary>
/// TBD.
/// </summary>
public void Add(
T measurement,
params KeyValuePair<string, object?>[] tags)
{
this.RecordMeasurement(measurement, tags);
}
}
}
Loading

0 comments on commit 7e7306b

Please sign in to comment.