Skip to content

Commit 40a2301

Browse files
authored
Merge pull request #9 from Ai4c-AI/langfuse
Langfuse
2 parents 5fe6e6b + 2fe8b0d commit 40a2301

32 files changed

+963
-179
lines changed

BotSharp.sln

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
3-
# Visual Studio Version 17
4-
VisualStudioVersion = 17.6.33712.159
3+
# Visual Studio Version 18
4+
VisualStudioVersion = 18.0.11205.157 d18.0
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Infrastructure", "Infrastructure", "{E29DC6C4-5E57-48C5-BCB0-6B8F84782749}"
77
EndProject
@@ -149,8 +149,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.Plugin.ExcelHandle
149149
EndProject
150150
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.Plugin.GiteeAI", "src\Plugins\BotSharp.Plugin.GiteeAI\BotSharp.Plugin.GiteeAI.csproj", "{50B57066-3267-1D10-0F72-D2F5CC494F2C}"
151151
EndProject
152-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.Plugin.ImageHandler", "src\Plugins\BotSharp.Plugin.ImageHandler\BotSharp.Plugin.ImageHandler.csproj", "{242F2D93-FCCE-4982-8075-F3052ECCA92C}"
153-
EndProject
154152
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.Plugin.FuzzySharp", "src\Plugins\BotSharp.Plugin.FuzzySharp\BotSharp.Plugin.FuzzySharp.csproj", "{E7C243B9-E751-B3B4-8F16-95C76CA90D31}"
155153
EndProject
156154
Global
@@ -633,14 +631,6 @@ Global
633631
{50B57066-3267-1D10-0F72-D2F5CC494F2C}.Release|Any CPU.Build.0 = Release|Any CPU
634632
{50B57066-3267-1D10-0F72-D2F5CC494F2C}.Release|x64.ActiveCfg = Release|Any CPU
635633
{50B57066-3267-1D10-0F72-D2F5CC494F2C}.Release|x64.Build.0 = Release|Any CPU
636-
{242F2D93-FCCE-4982-8075-F3052ECCA92C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
637-
{242F2D93-FCCE-4982-8075-F3052ECCA92C}.Debug|Any CPU.Build.0 = Debug|Any CPU
638-
{242F2D93-FCCE-4982-8075-F3052ECCA92C}.Debug|x64.ActiveCfg = Debug|Any CPU
639-
{242F2D93-FCCE-4982-8075-F3052ECCA92C}.Debug|x64.Build.0 = Debug|Any CPU
640-
{242F2D93-FCCE-4982-8075-F3052ECCA92C}.Release|Any CPU.ActiveCfg = Release|Any CPU
641-
{242F2D93-FCCE-4982-8075-F3052ECCA92C}.Release|Any CPU.Build.0 = Release|Any CPU
642-
{242F2D93-FCCE-4982-8075-F3052ECCA92C}.Release|x64.ActiveCfg = Release|Any CPU
643-
{242F2D93-FCCE-4982-8075-F3052ECCA92C}.Release|x64.Build.0 = Release|Any CPU
644634
{E7C243B9-E751-B3B4-8F16-95C76CA90D31}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
645635
{E7C243B9-E751-B3B4-8F16-95C76CA90D31}.Debug|Any CPU.Build.0 = Debug|Any CPU
646636
{E7C243B9-E751-B3B4-8F16-95C76CA90D31}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -721,7 +711,6 @@ Global
721711
{0428DEAA-E4FE-4259-A6D8-6EDD1A9D0702} = {51AFE054-AE99-497D-A593-69BAEFB5106F}
722712
{FC63C875-E880-D8BB-B8B5-978AB7B62983} = {51AFE054-AE99-497D-A593-69BAEFB5106F}
723713
{50B57066-3267-1D10-0F72-D2F5CC494F2C} = {D5293208-2BEF-42FC-A64C-5954F61720BA}
724-
{242F2D93-FCCE-4982-8075-F3052ECCA92C} = {51AFE054-AE99-497D-A593-69BAEFB5106F}
725714
{E7C243B9-E751-B3B4-8F16-95C76CA90D31} = {51AFE054-AE99-497D-A593-69BAEFB5106F}
726715
EndGlobalSection
727716
GlobalSection(ExtensibilityGlobals) = postSolution

Directory.Packages.props

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
66
</PropertyGroup>
77
<ItemGroup>
8+
<PackageVersion Include="DeviceId" Version="6.9.0" />
9+
<PackageVersion Include="DeviceId.Linux" Version="6.9.0" />
10+
<PackageVersion Include="DeviceId.Mac" Version="6.9.0" />
11+
<PackageVersion Include="DeviceId.Windows" Version="6.9.0" />
12+
<PackageVersion Include="DeviceId.Windows.Wmi" Version="6.9.0" />
813
<PackageVersion Include="CsvHelper" Version="33.1.0" />
914
<PackageVersion Include="FuzzySharp" Version="2.0.2" />
1015
<PackageVersion Include="EntityFramework" Version="6.4.4" />
@@ -27,8 +32,8 @@
2732
<PackageVersion Include="System.ComponentModel.Annotations" Version="5.0.0" />
2833
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="8.14.0" />
2934
<PackageVersion Include="System.Memory.Data" Version="8.0.0" />
30-
<PackageVersion Include="System.Text.Json" Version="8.0.5" />
31-
<PackageVersion Include="System.Reactive" Version="6.0.1" />
35+
<PackageVersion Include="System.Text.Json" Version="9.0.11" />
36+
<PackageVersion Include="System.Reactive" Version="6.0.1" />
3237
<PackageVersion Include="Serilog.Sinks.Console" Version="6.1.1" />
3338
<PackageVersion Include="Serilog.Extensions.Logging" Version="9.0.2" />
3439
<PackageVersion Include="Serilog.Sinks.File" Version="7.0.0" />
@@ -48,7 +53,7 @@
4853
<PackageVersion Include="Whisper.net.Runtime" Version="1.8.1" />
4954
<PackageVersion Include="NCrontab" Version="3.3.3" />
5055
<PackageVersion Include="Azure.AI.OpenAI" Version="2.5.0-beta.1" />
51-
<PackageVersion Include="OpenAI" Version="2.6.0" />
56+
<PackageVersion Include="OpenAI" Version="2.5.0" />
5257
<PackageVersion Include="MailKit" Version="4.14.1" />
5358
<PackageVersion Include="Microsoft.Data.Sqlite" Version="10.0.0" />
5459
<PackageVersion Include="MySql.Data" Version="9.5.0" />
@@ -117,8 +122,10 @@
117122
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0" />
118123
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="10.0.0" />
119124
<PackageVersion Include="Shouldly" Version="4.3.0" />
120-
<PackageVersion Include="ModelContextProtocol" Version="0.1.0-preview.11" />
121-
<PackageVersion Include="ModelContextProtocol.AspNetCore" Version="0.1.0-preview.11" />
125+
<PackageVersion Include="ModelContextProtocol.Core" Version="0.4.0-preview.3" />
126+
<PackageVersion Include="ModelContextProtocol" Version="0.4.0-preview.3" />
127+
<PackageVersion Include="ModelContextProtocol.AspNetCore" Version="0.4.0-preview.3" />
128+
<PackageVersion Include="Langfuse.OpenTelemetry" Version="1.0.0" />
122129
</ItemGroup>
123130
<ItemGroup>
124131
<PackageVersion Include="BotSharp.Core" Version="$(BotSharpVersion)" />

src/BotSharp.AppHost/Properties/launchSettings.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"applicationUrl": "https://localhost:17248;http://localhost:15140",
99
"environmentVariables": {
1010
"ASPNETCORE_ENVIRONMENT": "Development",
11+
"ASPIRE_ALLOW_UNSECURED_TRANSPORT": "true",
1112
"DOTNET_ENVIRONMENT": "Development",
1213
"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21247",
1314
"DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22140"
@@ -20,6 +21,7 @@
2021
"applicationUrl": "http://localhost:15140",
2122
"environmentVariables": {
2223
"ASPNETCORE_ENVIRONMENT": "Development",
24+
"ASPIRE_ALLOW_UNSECURED_TRANSPORT": "true",
2325
"DOTNET_ENVIRONMENT": "Development",
2426
"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:19185",
2527
"DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20069"

src/BotSharp.ServiceDefaults/BotSharp.ServiceDefaults.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
44
<TargetFramework>net8.0</TargetFramework>
@@ -20,6 +20,7 @@
2020
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" />
2121
<PackageReference Include="OpenTelemetry.Instrumentation.Http" />
2222
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" />
23+
<PackageReference Include="Langfuse.OpenTelemetry" />
2324
</ItemGroup>
2425

2526
</Project>

src/BotSharp.ServiceDefaults/Extensions.cs

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using BotSharp.Langfuse;
2+
using Langfuse.OpenTelemetry;
23
using Microsoft.AspNetCore.Builder;
34
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
45
using Microsoft.Extensions.Configuration;
@@ -100,10 +101,11 @@ public static IHostApplicationBuilder ConfigureOpenTelemetry(this IHostApplicati
100101
.AddService("apiservice", serviceVersion: "1.0.0")
101102
)
102103
.AddSource("BotSharp")
104+
.AddSource("BotSharp.Server")
103105
.AddSource("BotSharp.Abstraction.Diagnostics")
104-
.AddSource("BotSharp.Core.Routing.Executor");
105-
106-
tracing.AddAspNetCoreInstrumentation()
106+
.AddSource("BotSharp.Core.Routing.Executor")
107+
.AddLangfuseExporter(builder.Configuration)
108+
.AddAspNetCoreInstrumentation()
107109
// Uncomment the following line to enable gRPC instrumentation (requires the OpenTelemetry.Instrumentation.GrpcNetClient package)
108110
//.AddGrpcClientInstrumentation()
109111
.AddHttpClientInstrumentation()
@@ -115,7 +117,7 @@ public static IHostApplicationBuilder ConfigureOpenTelemetry(this IHostApplicati
115117
// options.Headers = $"Authorization=Basic {base64EncodedAuth}";
116118
//})
117119
;
118-
120+
119121

120122
});
121123

@@ -134,26 +136,27 @@ private static IHostApplicationBuilder AddOpenTelemetryExporters(this IHostAppli
134136
{
135137
builder.Services.Configure<OpenTelemetryLoggerOptions>(logging => logging.AddOtlpExporter());
136138
builder.Services.ConfigureOpenTelemetryMeterProvider(metrics => metrics.AddOtlpExporter());
137-
if (useLangfuse)
138-
{
139-
var publicKey = langfuseSection.GetValue<string>(nameof(LangfuseSettings.PublicKey)) ?? string.Empty;
140-
var secretKey = langfuseSection.GetValue<string>(nameof(LangfuseSettings.SecretKey)) ?? string.Empty;
141-
var host = langfuseSection.GetValue<string>(nameof(LangfuseSettings.Host)) ?? string.Empty;
142-
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes($"{publicKey}:{secretKey}");
143-
string base64EncodedAuth = Convert.ToBase64String(plainTextBytes);
144-
145-
builder.Services.ConfigureOpenTelemetryTracerProvider(tracing => tracing.AddOtlpExporter(options =>
146-
{
147-
options.Endpoint = new Uri(host);
148-
options.Protocol = OtlpExportProtocol.HttpProtobuf;
149-
options.Headers = $"Authorization=Basic {base64EncodedAuth}";
150-
})
151-
);
152-
}
153-
else
154-
{
139+
//if (useLangfuse)
140+
//{
141+
// var publicKey = langfuseSection.GetValue<string>(nameof(LangfuseSettings.PublicKey)) ?? string.Empty;
142+
// var secretKey = langfuseSection.GetValue<string>(nameof(LangfuseSettings.SecretKey)) ?? string.Empty;
143+
// var host = langfuseSection.GetValue<string>(nameof(LangfuseSettings.Host)) ?? string.Empty;
144+
// var plainTextBytes = System.Text.Encoding.UTF8.GetBytes($"{publicKey}:{secretKey}");
145+
// string base64EncodedAuth = Convert.ToBase64String(plainTextBytes);
146+
147+
// builder.Services.ConfigureOpenTelemetryTracerProvider(tracing => tracing.AddOtlpExporter(options =>
148+
// {
149+
// options.Endpoint = new Uri(host);
150+
// options.Protocol = OtlpExportProtocol.HttpProtobuf;
151+
// options.Headers = $"Authorization=Basic {base64EncodedAuth}";
152+
// })
153+
// );
154+
155+
//}
156+
//else
157+
//{
155158
builder.Services.ConfigureOpenTelemetryTracerProvider(tracing => tracing.AddOtlpExporter());
156-
}
159+
//}
157160
}
158161

159162
// Uncomment the following lines to enable the Azure Monitor exporter (requires the Azure.Monitor.OpenTelemetry.AspNetCore package)

src/Infrastructure/BotSharp.Abstraction/BotSharp.Abstraction.csproj

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@
4040
<PackageReference Include="Serilog.Sinks.Console" />
4141
<PackageReference Include="Serilog.Sinks.File" />
4242
<PackageReference Include="Rougamo.Fody" />
43+
<PackageReference Include="ModelContextProtocol" />
44+
<PackageReference Include="DeviceId" />
45+
<PackageReference Include="DeviceId.Linux" />
46+
<PackageReference Include="DeviceId.Mac" />
47+
<PackageReference Include="DeviceId.Windows" />
48+
<PackageReference Include="DeviceId.Windows.Wmi" />
4349
</ItemGroup>
44-
4550
</Project>
Lines changed: 24 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,33 @@
11
// Copyright (c) Microsoft. All rights reserved.
22

3-
using System;
4-
using System.Collections.Generic;
3+
using BotSharp.Abstraction.Diagnostics.Telemetry;
54
using System.Diagnostics;
65
using System.Diagnostics.CodeAnalysis;
7-
using System.Runtime.CompilerServices;
8-
using System.Threading;
9-
using System.Threading.Tasks;
106

117
namespace BotSharp.Abstraction.Diagnostics;
128

9+
/// <summary>
10+
/// Model diagnostics helper class that provides a set of methods to trace model activities with the OTel semantic conventions.
11+
/// This class contains experimental features and may change in the future.
12+
/// To enable these features, set one of the following switches to true:
13+
/// `BotSharp.Experimental.GenAI.EnableOTelDiagnostics`
14+
/// `BotSharp.Experimental.GenAI.EnableOTelDiagnosticsSensitive`
15+
/// Or set the following environment variables to true:
16+
/// `BOTSHARP_EXPERIMENTAL_GENAI_ENABLE_OTEL_DIAGNOSTICS`
17+
/// `BOTSHARP_EXPERIMENTAL_GENAI_ENABLE_OTEL_DIAGNOSTICS_SENSITIVE`
18+
/// </summary>
1319
[ExcludeFromCodeCoverage]
14-
public static class ActivityExtensions
20+
public static class ActivityExtensions
1521
{
22+
private const string EnableDiagnosticsSwitch = "BotSharp.Experimental.GenAI.EnableOTelDiagnostics";
23+
private const string EnableSensitiveEventsSwitch = "BotSharp.Experimental.GenAI.EnableOTelDiagnosticsSensitive";
24+
private const string EnableDiagnosticsEnvVar = "BOTSHARP_EXPERIMENTAL_GENAI_ENABLE_OTEL_DIAGNOSTICS";
25+
private const string EnableSensitiveEventsEnvVar = "BOTSHARP_EXPERIMENTAL_GENAI_ENABLE_OTEL_DIAGNOSTICS_SENSITIVE";
26+
27+
public static readonly bool s_enableDiagnostics = AppContextSwitchHelper.GetConfigValue(EnableDiagnosticsSwitch, EnableDiagnosticsEnvVar);
28+
public static readonly bool s_enableSensitiveEvents = AppContextSwitchHelper.GetConfigValue(EnableSensitiveEventsSwitch, EnableSensitiveEventsEnvVar);
29+
30+
1631
/// <summary>
1732
/// Starts an activity with the appropriate tags for a kernel function execution.
1833
/// </summary>
@@ -21,9 +36,9 @@ public static class ActivityExtensions
2136
const string OperationName = "execute_tool";
2237

2338
return source.StartActivityWithTags($"{OperationName} {functionName}", [
24-
new KeyValuePair<string, object?>("gen_ai.operation.name", OperationName),
25-
new KeyValuePair<string, object?>("gen_ai.tool.name", functionName),
26-
new KeyValuePair<string, object?>("gen_ai.tool.description", functionDescription)
39+
new KeyValuePair<string, object?>(TelemetryConstants.ModelDiagnosticsTags.Operation, OperationName),
40+
new KeyValuePair<string, object?>(TelemetryConstants.ModelDiagnosticsTags.ToolName, functionName),
41+
new KeyValuePair<string, object?>(TelemetryConstants.ModelDiagnosticsTags.ToolDescription, functionDescription)
2742
], ActivityKind.Internal);
2843
}
2944

@@ -42,8 +57,6 @@ public static Activity SetTags(this Activity activity, ReadOnlySpan<KeyValuePair
4257
{
4358
activity.SetTag(tag.Key, tag.Value);
4459
}
45-
;
46-
4760
return activity;
4861
}
4962

@@ -69,51 +82,4 @@ public static Activity SetError(this Activity activity, Exception exception)
6982
activity.SetStatus(ActivityStatusCode.Error, exception.Message);
7083
return activity;
7184
}
72-
73-
public static async IAsyncEnumerable<TResult> RunWithActivityAsync<TResult>(
74-
Func<Activity?> getActivity,
75-
Func<IAsyncEnumerable<TResult>> operation,
76-
[EnumeratorCancellation] CancellationToken cancellationToken)
77-
{
78-
using var activity = getActivity();
79-
80-
ConfiguredCancelableAsyncEnumerable<TResult> result;
81-
82-
try
83-
{
84-
result = operation().WithCancellation(cancellationToken).ConfigureAwait(false);
85-
}
86-
catch (Exception ex) when (activity is not null)
87-
{
88-
activity.SetError(ex);
89-
throw;
90-
}
91-
92-
var resultEnumerator = result.ConfigureAwait(false).GetAsyncEnumerator();
93-
94-
try
95-
{
96-
while (true)
97-
{
98-
try
99-
{
100-
if (!await resultEnumerator.MoveNextAsync())
101-
{
102-
break;
103-
}
104-
}
105-
catch (Exception ex) when (activity is not null)
106-
{
107-
activity.SetError(ex);
108-
throw;
109-
}
110-
111-
yield return resultEnumerator.Current;
112-
}
113-
}
114-
finally
115-
{
116-
await resultEnumerator.DisposeAsync();
117-
}
118-
}
11985
}

src/Infrastructure/BotSharp.Abstraction/Diagnostics/AppContextSwitchHelper.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
13
using System;
24
using System.Diagnostics.CodeAnalysis;
35

4-
namespace BotSharp.Abstraction.Diagnostics;
6+
namespace BotSharp.Abstraction.Diagnostics;
57

68
/// <summary>
79
/// Helper class to get app context switch value
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
namespace BotSharp.Abstraction.Diagnostics;
2+
3+
public class BotSharpOTelOptions
4+
{
5+
public const string DefaultName = "BotSharp.Server";
6+
7+
public string Name { get; set; } = DefaultName;
8+
9+
public string Version { get; set; } = "4.0.0";
10+
11+
public bool IsTelemetryEnabled { get; set; } = true;
12+
}

0 commit comments

Comments
 (0)