diff --git a/Autometrics Samples.sln b/Autometrics Samples.sln
deleted file mode 100644
index 83c7d88..0000000
--- a/Autometrics Samples.sln
+++ /dev/null
@@ -1,37 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 17
-VisualStudioVersion = 17.5.33627.172
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Autometrics.Samples.ConsoleApp", "examples\Autometrics.Samples.ConsoleApp\Autometrics.Samples.ConsoleApp.csproj", "{7905F97A-78BA-4B43-9E31-AA52E1E2338E}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Autometrics.Samples.Library", "examples\Autometrics.Samples.Library\Autometrics.Samples.Library.csproj", "{F6692CF6-2DD5-4F09-BD97-5CF125AF2DC6}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Autometrics.Samples.WebApp", "examples\Autometrics.Samples.WebApp\Autometrics.Samples.WebApp.csproj", "{05CD2671-F249-40A7-A775-294018BF673B}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {7905F97A-78BA-4B43-9E31-AA52E1E2338E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {7905F97A-78BA-4B43-9E31-AA52E1E2338E}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {7905F97A-78BA-4B43-9E31-AA52E1E2338E}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {7905F97A-78BA-4B43-9E31-AA52E1E2338E}.Release|Any CPU.Build.0 = Release|Any CPU
- {F6692CF6-2DD5-4F09-BD97-5CF125AF2DC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {F6692CF6-2DD5-4F09-BD97-5CF125AF2DC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {F6692CF6-2DD5-4F09-BD97-5CF125AF2DC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {F6692CF6-2DD5-4F09-BD97-5CF125AF2DC6}.Release|Any CPU.Build.0 = Release|Any CPU
- {05CD2671-F249-40A7-A775-294018BF673B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {05CD2671-F249-40A7-A775-294018BF673B}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {05CD2671-F249-40A7-A775-294018BF673B}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {05CD2671-F249-40A7-A775-294018BF673B}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {7B5D2BC5-3197-4A76-A94E-468600181D0C}
- EndGlobalSection
-EndGlobal
diff --git a/Autometrics-CS.sln b/Autometrics-CS.sln
index 052462d..703ba0d 100644
--- a/Autometrics-CS.sln
+++ b/Autometrics-CS.sln
@@ -15,24 +15,57 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Autometrics.Instrumentation.Tests", "src\Autometrics.Instrumentation.Tests\Autometrics.Instrumentation.Tests.csproj", "{93EAE891-CAB6-47D4-80A8-B151A423FDA6}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{12A476A7-0753-4A7E-BFA9-6D2701B34E89}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Autometrics.Samples.ConsoleApp", "examples\Autometrics.Samples.ConsoleApp\Autometrics.Samples.ConsoleApp.csproj", "{488AB5DF-36E4-4992-B9A7-8C2E6D188CDC}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Autometrics.Samples.Library", "examples\Autometrics.Samples.Library\Autometrics.Samples.Library.csproj", "{8EDA190B-A429-4BB9-949F-4507870F3275}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Autometrics.Samples.WebApp", "examples\Autometrics.Samples.WebApp\Autometrics.Samples.WebApp.csproj", "{99E9E740-B530-4B7F-9598-C044E669F56E}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
+ Local Release|Any CPU = Local Release|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A220D3AC-D7FC-4CCA-BC38-F209691851C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A220D3AC-D7FC-4CCA-BC38-F209691851C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A220D3AC-D7FC-4CCA-BC38-F209691851C2}.Local Release|Any CPU.ActiveCfg = Local Release|Any CPU
+ {A220D3AC-D7FC-4CCA-BC38-F209691851C2}.Local Release|Any CPU.Build.0 = Local Release|Any CPU
{A220D3AC-D7FC-4CCA-BC38-F209691851C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A220D3AC-D7FC-4CCA-BC38-F209691851C2}.Release|Any CPU.Build.0 = Release|Any CPU
{93EAE891-CAB6-47D4-80A8-B151A423FDA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{93EAE891-CAB6-47D4-80A8-B151A423FDA6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {93EAE891-CAB6-47D4-80A8-B151A423FDA6}.Local Release|Any CPU.ActiveCfg = Local Release|Any CPU
+ {93EAE891-CAB6-47D4-80A8-B151A423FDA6}.Local Release|Any CPU.Build.0 = Local Release|Any CPU
{93EAE891-CAB6-47D4-80A8-B151A423FDA6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{93EAE891-CAB6-47D4-80A8-B151A423FDA6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {488AB5DF-36E4-4992-B9A7-8C2E6D188CDC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {488AB5DF-36E4-4992-B9A7-8C2E6D188CDC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {488AB5DF-36E4-4992-B9A7-8C2E6D188CDC}.Local Release|Any CPU.ActiveCfg = Local Release|Any CPU
+ {488AB5DF-36E4-4992-B9A7-8C2E6D188CDC}.Local Release|Any CPU.Build.0 = Local Release|Any CPU
+ {488AB5DF-36E4-4992-B9A7-8C2E6D188CDC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8EDA190B-A429-4BB9-949F-4507870F3275}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8EDA190B-A429-4BB9-949F-4507870F3275}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8EDA190B-A429-4BB9-949F-4507870F3275}.Local Release|Any CPU.ActiveCfg = Local Release|Any CPU
+ {8EDA190B-A429-4BB9-949F-4507870F3275}.Local Release|Any CPU.Build.0 = Local Release|Any CPU
+ {8EDA190B-A429-4BB9-949F-4507870F3275}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {99E9E740-B530-4B7F-9598-C044E669F56E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {99E9E740-B530-4B7F-9598-C044E669F56E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {99E9E740-B530-4B7F-9598-C044E669F56E}.Local Release|Any CPU.ActiveCfg = Local Release|Any CPU
+ {99E9E740-B530-4B7F-9598-C044E669F56E}.Local Release|Any CPU.Build.0 = Local Release|Any CPU
+ {99E9E740-B530-4B7F-9598-C044E669F56E}.Release|Any CPU.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {488AB5DF-36E4-4992-B9A7-8C2E6D188CDC} = {12A476A7-0753-4A7E-BFA9-6D2701B34E89}
+ {8EDA190B-A429-4BB9-949F-4507870F3275} = {12A476A7-0753-4A7E-BFA9-6D2701B34E89}
+ {99E9E740-B530-4B7F-9598-C044E669F56E} = {12A476A7-0753-4A7E-BFA9-6D2701B34E89}
+ EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {422C978E-1479-4996-B5D7-B494E97E3B45}
EndGlobalSection
diff --git a/examples/Autometrics.Samples.ConsoleApp/Autometrics.Samples.ConsoleApp.csproj b/examples/Autometrics.Samples.ConsoleApp/Autometrics.Samples.ConsoleApp.csproj
index 6a0af5f..b23c946 100644
--- a/examples/Autometrics.Samples.ConsoleApp/Autometrics.Samples.ConsoleApp.csproj
+++ b/examples/Autometrics.Samples.ConsoleApp/Autometrics.Samples.ConsoleApp.csproj
@@ -8,6 +8,7 @@
1.0.2.1
+ Debug;Release;Local Release
@@ -18,7 +19,7 @@
-
+
diff --git a/examples/Autometrics.Samples.ConsoleApp/ConsoleMetrics.cs b/examples/Autometrics.Samples.ConsoleApp/ConsoleMetrics.cs
index f5226a3..ce639a7 100644
--- a/examples/Autometrics.Samples.ConsoleApp/ConsoleMetrics.cs
+++ b/examples/Autometrics.Samples.ConsoleApp/ConsoleMetrics.cs
@@ -11,6 +11,9 @@ public static void GenerateActivity()
// Create a meter provider with the console exporter connected to the Autometrics.Instrumentation meter
using var meterProvider = Sdk.CreateMeterProviderBuilder()
.AddMeter("Autometrics.Instrumentation")
+ .AddView(
+ instrumentName: "function.calls.duration",
+ new ExplicitBucketHistogramConfiguration { Boundaries = new double[] { 0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1, 2.5, 5, 7.5, 10 } })
.AddConsoleExporter()
.Build();
diff --git a/examples/Autometrics.Samples.ConsoleApp/OtelCollector.cs b/examples/Autometrics.Samples.ConsoleApp/OtelCollector.cs
index 7ccebcc..2eee1a5 100644
--- a/examples/Autometrics.Samples.ConsoleApp/OtelCollector.cs
+++ b/examples/Autometrics.Samples.ConsoleApp/OtelCollector.cs
@@ -11,6 +11,9 @@ public static void GenerateActivity()
// Create a meter provider with the Otlp exporter connected to the Autometrics.Instrumentation
using var meterProvider = Sdk.CreateMeterProviderBuilder()
.AddMeter("Autometrics.Instrumentation")
+ .AddView(
+ instrumentName: "function.calls.duration",
+ new ExplicitBucketHistogramConfiguration { Boundaries = new double[] { 0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1, 2.5, 5, 7.5, 10 } })
.AddOtlpExporter()
.Build();
diff --git a/examples/Autometrics.Samples.ConsoleApp/Program.cs b/examples/Autometrics.Samples.ConsoleApp/Program.cs
index b737dca..6afea6f 100644
--- a/examples/Autometrics.Samples.ConsoleApp/Program.cs
+++ b/examples/Autometrics.Samples.ConsoleApp/Program.cs
@@ -15,6 +15,9 @@ private static void Main(string[] args)
Console.WriteLine("6. Exit");
Console.Write("Enter the option number: ");
+ //set the environment variable for the service name, yuo can also use OTEL_SERVICE_NAME
+ System.Environment.SetEnvironmentVariable("AUTOMETRICS_SERVICE_NAME", "Console Simulator!");
+
if (int.TryParse(Console.ReadLine(), out int option))
{
switch (option)
diff --git a/examples/Autometrics.Samples.ConsoleApp/ScrapableMetrics.cs b/examples/Autometrics.Samples.ConsoleApp/ScrapableMetrics.cs
index bc8da49..4fe7cb4 100644
--- a/examples/Autometrics.Samples.ConsoleApp/ScrapableMetrics.cs
+++ b/examples/Autometrics.Samples.ConsoleApp/ScrapableMetrics.cs
@@ -11,10 +11,13 @@ public static void GenerateActivity()
// Create a meter provider with the console exporter connected to the Autometrics.Instrumentation meter
using var meterProvider = Sdk.CreateMeterProviderBuilder()
.AddMeter("Autometrics.Instrumentation")
+ .AddView(
+ instrumentName: "function.calls.duration",
+ new ExplicitBucketHistogramConfiguration { Boundaries = new double[] { 0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1, 2.5, 5, 7.5, 10 } })
.AddPrometheusHttpListener(
options =>
{
- options.UriPrefixes = new string[] { "http://localhost:9090/" };
+ options.UriPrefixes = new string[] { "http://localhost:9091/" };
})
.Build();
diff --git a/examples/Autometrics.Samples.Library/Autometrics.Samples.Library.csproj b/examples/Autometrics.Samples.Library/Autometrics.Samples.Library.csproj
index 652385b..9561a46 100644
--- a/examples/Autometrics.Samples.Library/Autometrics.Samples.Library.csproj
+++ b/examples/Autometrics.Samples.Library/Autometrics.Samples.Library.csproj
@@ -4,10 +4,11 @@
net6.0
enable
enable
+ Debug;Release;Local Release
-
+
diff --git a/examples/Autometrics.Samples.WebApp/Autometrics.Samples.WebApp.csproj b/examples/Autometrics.Samples.WebApp/Autometrics.Samples.WebApp.csproj
index c1ee348..31a7f73 100644
--- a/examples/Autometrics.Samples.WebApp/Autometrics.Samples.WebApp.csproj
+++ b/examples/Autometrics.Samples.WebApp/Autometrics.Samples.WebApp.csproj
@@ -4,6 +4,7 @@
net6.0
enable
enable
+ Debug;Release;Local Release
@@ -12,7 +13,8 @@
-
+
+
diff --git a/examples/Autometrics.Samples.WebApp/Program.cs b/examples/Autometrics.Samples.WebApp/Program.cs
index 2efa887..4e408f1 100644
--- a/examples/Autometrics.Samples.WebApp/Program.cs
+++ b/examples/Autometrics.Samples.WebApp/Program.cs
@@ -11,6 +11,10 @@
// Additional configuration or other exporters can be added here
builder.AddOtlpExporter();
builder.AddMeter("Autometrics.Instrumentation");
+ builder.AddView(
+ instrumentName: "function.calls.duration",
+ new ExplicitBucketHistogramConfiguration { Boundaries = new double[] { 0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1, 2.5, 5, 7.5, 10 } }
+ );
});
var app = builder.Build();
diff --git a/src/Autometrics.Instrumentation.Tests/Autometrics.Instrumentation.Tests.csproj b/src/Autometrics.Instrumentation.Tests/Autometrics.Instrumentation.Tests.csproj
index 362c3da..0126c47 100644
--- a/src/Autometrics.Instrumentation.Tests/Autometrics.Instrumentation.Tests.csproj
+++ b/src/Autometrics.Instrumentation.Tests/Autometrics.Instrumentation.Tests.csproj
@@ -7,6 +7,7 @@
false
true
+ Debug;Release;Local Release
diff --git a/src/Autometrics.Instrumentation.Tests/Utils/MetricReading.cs b/src/Autometrics.Instrumentation.Tests/Utils/MetricReading.cs
index 159b6e8..7803432 100644
--- a/src/Autometrics.Instrumentation.Tests/Utils/MetricReading.cs
+++ b/src/Autometrics.Instrumentation.Tests/Utils/MetricReading.cs
@@ -31,7 +31,7 @@ public MetricReading(string metricName, T reading, KeyValuePair
case "result":
Result = tag.Value?.ToString();
break;
- case "caller":
+ case "caller.function":
Caller = tag.Value?.ToString();
break;
case "objectiveName":
diff --git a/src/Autometrics.Instrumentation/Aspects/AutometricsAspect.cs b/src/Autometrics.Instrumentation/Aspects/AutometricsAspect.cs
index 0ca6352..a2313f9 100644
--- a/src/Autometrics.Instrumentation/Aspects/AutometricsAspect.cs
+++ b/src/Autometrics.Instrumentation/Aspects/AutometricsAspect.cs
@@ -1,11 +1,8 @@
using AspectInjector.Broker;
using Autometrics.Instrumentation.Attributes;
using Autometrics.Instrumentation.SLO;
-using System;
-using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
-using System.Text;
using System.Text.RegularExpressions;
namespace Autometrics.Instrumentation.Aspects
@@ -18,10 +15,6 @@ namespace Autometrics.Instrumentation.Aspects
[Aspect(Scope.Global)]
public class AutometricsAspect
{
- // Aspect Injection renames methods, if we get a renamed one it will look like this: __a$_around_SaferMethod_100663303_o
- // We need a regex to identify these methods
- private static readonly string renamedMethodRegex = @"^__a\$_around_(?.*)_\d{5,10}_o$";
-
///
/// This is the method that will be injected into the target method, it will wrap the target method in a try/catch block and record the duration of the method call
/// If any exceptions are thrown, they will be rethrown after the duration is recorded and a result of error tagged on the metric
@@ -40,18 +33,21 @@ public object HandleMethod(
[Argument(Source.Triggers)] Attribute[] triggers)
{
Stopwatch stopwatch = new Stopwatch();
- stopwatch.Start();
bool success = false;
// We'll start with our objective as null, but if the trigger has one we'll use it
Objective? slo = null;
+ string? serviceName = null;
if (triggers.Length > 0 && triggers[0] is AutometricsAttribute attribute)
{
slo = attribute.SLO;
+ serviceName = attribute.GetServiceName();
}
try
{
+ // start the stopwatch, call the method, stop the stopwatch to record the duration
+ stopwatch.Start();
object result = method(arguments);
success = true;
return result;
@@ -64,50 +60,9 @@ public object HandleMethod(
finally
{
stopwatch.Stop();
- MetricCounters.RecordFunctionCall(stopwatch.Elapsed.TotalSeconds, methodName, success, metadata.DeclaringType.FullName, GetCallingMethodName(metadata), slo);
+ CallingMethod caller = new CallingMethod(metadata);
+ MetricCounters.RecordFunctionCall(stopwatch.Elapsed.TotalSeconds, methodName, success, metadata.DeclaringType.FullName, caller, serviceName, slo);
}
}
-
- ///
- /// This resolves the name of the calling method, and if the calling method was renamed by AspectInjector, it will attempt to return the original name via regex
- ///
- /// The metadata from AspectInjector
- ///
- private static string? GetCallingMethodName(MethodBase method)
- {
- var stackTrace = new StackTrace();
- var stackFrames = stackTrace.GetFrames();
- MethodBase callingMethod = null;
-
- if (stackFrames == null)
- {
- return null;
- }
-
- for (int i = 0; i < stackFrames.Length; i++)
- {
- if (stackFrames[i].GetMethod() == method)
- {
- // The calling method is the one before the current method in the stack
- callingMethod = i + 1 < stackFrames.Length ? stackFrames[i + 1].GetMethod() : null;
- }
- }
-
- // If the calling method isn't null, match it to our regex to see if it's a renamed method, then return the original name
- if (callingMethod != null)
- {
- var match = Regex.Match(callingMethod.Name, renamedMethodRegex, RegexOptions.Compiled);
- if (match.Success)
- {
- return match.Groups["originalMethodName"].Value;
- }
- else
- {
- return callingMethod.Name;
- }
- }
-
- return null;
- }
}
-}
+}
\ No newline at end of file
diff --git a/src/Autometrics.Instrumentation/Attributes/AutometricsAttribute.cs b/src/Autometrics.Instrumentation/Attributes/AutometricsAttribute.cs
index c21d97d..9f0af99 100644
--- a/src/Autometrics.Instrumentation/Attributes/AutometricsAttribute.cs
+++ b/src/Autometrics.Instrumentation/Attributes/AutometricsAttribute.cs
@@ -17,20 +17,38 @@ public class AutometricsAttribute : Attribute
/// Service-Level Objectives (SLOs) Spec
///
public Objective? SLO { get; }
+ public string EntryAssemblyName { get; private set; }
public AutometricsAttribute()
{
SLO = null;
+ EntryAssemblyName = GetAssemblyName();
}
public AutometricsAttribute(string objectiveName, ObjectivePercentile objectivePercentile, ObjectiveLatency objectiveLatencyThreshold, ObjectiveType objectiveType = ObjectiveType.SuccessAndLatency)
{
SLO = new Objective(objectiveName, objectivePercentile, objectiveLatencyThreshold, objectiveType);
+ EntryAssemblyName = GetAssemblyName();
}
public AutometricsAttribute(string objectiveName, ObjectivePercentile objectivePercentile)
{
SLO = new Objective(objectiveName, objectivePercentile);
+ EntryAssemblyName = GetAssemblyName();
+ }
+
+ private string GetAssemblyName()
+ {
+ return Assembly.GetEntryAssembly()?.GetName().Name ?? "Unknown";
+ }
+
+ ///
+ /// Gets the ServiceName, starting at the Attribule level, then the Environment Variable, then the EntryAssemblyName
+ ///
+ ///
+ public string GetServiceName()
+ {
+ return Environment.GetEnvironmentVariable("AUTOMETRICS_SERVICE_NAME") ?? Environment.GetEnvironmentVariable("OTEL_SERVICE_NAME") ?? EntryAssemblyName;
}
}
diff --git a/src/Autometrics.Instrumentation/Attributes/CallingMethod.cs b/src/Autometrics.Instrumentation/Attributes/CallingMethod.cs
new file mode 100644
index 0000000..9874515
--- /dev/null
+++ b/src/Autometrics.Instrumentation/Attributes/CallingMethod.cs
@@ -0,0 +1,78 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace Autometrics.Instrumentation.Attributes
+{
+ internal class CallingMethod
+ {
+ // Aspect Injection renames methods, if we get a renamed one it will look like this: __a$_around_SaferMethod_100663303_o
+ // We need a regex to identify these methods
+ private static readonly Regex _methodRegex = new Regex(@"^__a\$_around_(?.*)_\d{5,10}_o$", RegexOptions.Compiled);
+
+ public CallingMethod(MethodBase method)
+ {
+ try
+ {
+ SetCallingMethod(method);
+ }
+ catch
+ {
+ HasMethodData = false;
+ }
+ }
+
+ public string? MethodModule { get; set; }
+ public string? MethodName { get; set; }
+ public bool HasMethodData { get; internal set; } = false;
+
+ ///
+ /// This resolves the name of the calling method, and if the calling method was renamed by AspectInjector, it will attempt to return the original name via regex
+ ///
+ /// The metadata from AspectInjector
+ ///
+ private void SetCallingMethod(MethodBase method)
+ {
+ var stackTrace = new StackTrace();
+ var stackFrames = stackTrace.GetFrames();
+ MethodBase callingMethod = null;
+
+ if (stackFrames == null)
+ {
+ MethodModule = null;
+ MethodName = null;
+ return;
+ }
+
+ int length = stackFrames.Length;
+ for (int i = 0; i < length; i++)
+ {
+ if (stackFrames[i].GetMethod() == method)
+ {
+ // The calling method is the one before the current method in the stack
+ callingMethod = i + 1 < length ? stackFrames[i + 1].GetMethod() : null;
+ }
+ }
+
+ // If the calling method isn't null, match it to our regex to see if it's a renamed method, then return the original name
+ if (callingMethod != null)
+ {
+ HasMethodData = true;
+ var match = _methodRegex.Match(callingMethod.Name);
+ if (match.Success)
+ {
+ MethodName = match.Groups["originalMethodName"].Value;
+ }
+ else
+ {
+ MethodName = callingMethod.Name;
+ }
+
+ MethodModule = callingMethod.Module.Name;
+ }
+ }
+ }
+}
diff --git a/src/Autometrics.Instrumentation/Autometrics.Instrumentation.csproj b/src/Autometrics.Instrumentation/Autometrics.Instrumentation.csproj
index d786c6f..78e32ca 100644
--- a/src/Autometrics.Instrumentation/Autometrics.Instrumentation.csproj
+++ b/src/Autometrics.Instrumentation/Autometrics.Instrumentation.csproj
@@ -5,23 +5,23 @@
10.0
enable
enable
- 0.0.1.0
True
Autometrics, P2P-Nathan
https://github.com/autometrics-dev
Autometrics Instrumentation
- 0.1.0-alpha1
+ 0.2.0-beta
A .NET instrumentation of the Autometrics (https://github.com/autometrics-dev) observability micro-framework. It makes it quick and easy to instrument your code to collect standardized metrics, including function call counts, durations, and build information.
- README.md
- This is the initial Alpha release of Autometrics for .NET
+ Autometrics_README.md
+ This is the initial Beta release of Autometrics for .NET
LICENSE.txt
True
snupkg
autometrics_logo.png
+ Debug;Release;Local Release
-
+
@@ -38,7 +38,7 @@
True
\
-
+
True
\
diff --git a/src/Autometrics.Instrumentation/README.md b/src/Autometrics.Instrumentation/Autometrics_README.md
similarity index 100%
rename from src/Autometrics.Instrumentation/README.md
rename to src/Autometrics.Instrumentation/Autometrics_README.md
diff --git a/src/Autometrics.Instrumentation/MetricCounters.cs b/src/Autometrics.Instrumentation/MetricCounters.cs
index f3ef199..62583db 100644
--- a/src/Autometrics.Instrumentation/MetricCounters.cs
+++ b/src/Autometrics.Instrumentation/MetricCounters.cs
@@ -1,4 +1,5 @@
-using Autometrics.Instrumentation.SLO;
+using Autometrics.Instrumentation.Attributes;
+using Autometrics.Instrumentation.SLO;
using System.Diagnostics.Metrics;
using System.Reflection;
@@ -66,23 +67,24 @@ static MetricCounters()
/// The name of the function tracked
/// A string value of "ok" or "error" based on the outcome
/// optional caller data
- internal static void RecordFunctionCall(double duration, string functionName, bool success, string declaringType, string? caller, Objective? slo)
+ internal static void RecordFunctionCall(double duration, string functionName, bool success, string declaringType, CallingMethod caller, string? serviceName, Objective? slo)
{
List> callTags = new List>
{
new KeyValuePair("function", functionName),
new KeyValuePair("module", declaringType),
- new KeyValuePair("result", success ? "ok" : "error")
+ new KeyValuePair("result", success ? "ok" : "error"),
+ new KeyValuePair("service.name", serviceName)
};
- if (caller != null)
+ if (caller.HasMethodData)
{
- callTags.Add(new KeyValuePair("caller", caller));
+ callTags.Add(new KeyValuePair("caller.function", caller.MethodName));
+ callTags.Add(new KeyValuePair("caller.module", caller.MethodModule));
}
if (slo != null)
{
-
functionCallCount.Add(1, slo.GetCallCountTags(callTags));
functionCallDuration.Record(duration, slo.GetCallDurationTags(callTags));
}
@@ -103,6 +105,13 @@ internal static void RecordFunctionCall(double duration, string functionName, bo
{
Dictionary buildTags = new Dictionary();
+ // if our environmental variables are not null, use that as the service name
+ string? serviceName = Environment.GetEnvironmentVariable("AUTOMETRICS_SERVICE_NAME") ?? Environment.GetEnvironmentVariable("OTEL_SERVICE_NAME");
+ if (serviceName != null)
+ {
+ buildTags.Add("service.name", serviceName);
+ }
+
AssemblyName? assemblyName = assembly?.GetName();
AssemblyInformationalVersionAttribute assemblyInformationalVersionAttribute = assembly.GetCustomAttribute();
if (assemblyName != null)
diff --git a/src/Autometrics.Instrumentation/SLO/Objective.cs b/src/Autometrics.Instrumentation/SLO/Objective.cs
index 6e5dfa1..7fafc7d 100644
--- a/src/Autometrics.Instrumentation/SLO/Objective.cs
+++ b/src/Autometrics.Instrumentation/SLO/Objective.cs
@@ -47,12 +47,16 @@ public Objective(string objectiveName, ObjectivePercentile objectivePercentile,
///
public KeyValuePair[] GetCallCountTags(List> callTags)
{
+ List> countTags = new List>();
+
if (ObjectiveType == ObjectiveType.SuccessRate || ObjectiveType == ObjectiveType.SuccessAndLatency)
{
- callTags.Add(new KeyValuePair("objective.name", ObjectiveName));
- callTags.Add(new KeyValuePair("objective.percentile", ((double)ObjectivePercentile / 10)));
+ countTags.Add(new KeyValuePair("objective.name", ObjectiveName));
+ countTags.Add(new KeyValuePair("objective.percentile", ((double)ObjectivePercentile / 10)));
}
- return callTags.ToArray();
+
+ countTags.AddRange(callTags);
+ return countTags.ToArray();
}
///
@@ -62,13 +66,17 @@ public Objective(string objectiveName, ObjectivePercentile objectivePercentile,
///
public KeyValuePair[] GetCallDurationTags(List> callTags)
{
+ List> durationTags = new List>();
+
if (ObjectiveType == ObjectiveType.LatencyThreshold || ObjectiveType == ObjectiveType.SuccessAndLatency)
{
- callTags.Add(new KeyValuePair("objective.name", ObjectiveName));
- callTags.Add(new KeyValuePair("objective.percentile", (double)ObjectivePercentile / 10));
- callTags.Add(new KeyValuePair("objective.latency_threshold", (double)ObjectiveLatencyThreshold / 1000));
+ durationTags.Add(new KeyValuePair("objective.name", ObjectiveName));
+ durationTags.Add(new KeyValuePair("objective.percentile", (double)ObjectivePercentile / 10));
+ durationTags.Add(new KeyValuePair("objective.latency_threshold", (double)ObjectiveLatencyThreshold / 1000));
}
- return callTags.ToArray();
+
+ durationTags.AddRange(callTags);
+ return durationTags.ToArray();
}
}
}
\ No newline at end of file