add aspire for otel
This commit is contained in:
13
tools/AppHost/AppHost.cs
Normal file
13
tools/AppHost/AppHost.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using AppHost;
|
||||
using Projects;
|
||||
|
||||
var builder = DistributedApplication.CreateBuilder(args);
|
||||
|
||||
//var photino = builder.AddProject<SharpIDE_Photino>("photino");
|
||||
|
||||
builder.AddGodot("../../src/SharpIDE.Godot/SharpIDE.Godot.csproj", "sharpide-godot")
|
||||
.WithOtlpExporter();
|
||||
|
||||
var appHost = builder.Build();
|
||||
|
||||
await appHost.RunAsync();
|
||||
19
tools/AppHost/AppHost.csproj
Normal file
19
tools/AppHost/AppHost.csproj
Normal file
@@ -0,0 +1,19 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<Sdk Name="Aspire.AppHost.Sdk" Version="9.5.0"/>
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsAspireHost>true</IsAspireHost>
|
||||
<UserSecretsId>c8b6b3c2-8acc-412d-9d58-38b990d2f79f</UserSecretsId>
|
||||
<ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Aspire.Hosting.AppHost" Version="9.5.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
156
tools/AppHost/GodotExtensions.cs
Normal file
156
tools/AppHost/GodotExtensions.cs
Normal file
@@ -0,0 +1,156 @@
|
||||
using Aspire.Hosting.Lifecycle;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace AppHost;
|
||||
|
||||
// https://github.com/maddymontaquila/Godot-SnakeCS/blob/maddy/aspire/AppHost/GodotExtensions.cs
|
||||
public static class GodotExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds a Godot project to the application model.
|
||||
/// </summary>
|
||||
/// <param name="builder">The distributed application builder.</param>
|
||||
/// <param name="projectPath">The path to the Godot project file (.godot).</param>
|
||||
/// <param name="name">The name of the resource.</param>
|
||||
/// <param name="args">Optional arguments to pass to the Godot executable.</param>
|
||||
/// <returns>A reference to the Godot project resource.</returns>
|
||||
public static IResourceBuilder<ExecutableResource> AddGodot(
|
||||
this IDistributedApplicationBuilder builder,
|
||||
string projectPath,
|
||||
string? name = null,
|
||||
params string[] args)
|
||||
{
|
||||
name ??= Path.GetFileNameWithoutExtension(projectPath);
|
||||
var projectDirectory = Path.GetDirectoryName(projectPath) ?? ".";
|
||||
var godotPath = GetGodotExecutablePath();
|
||||
|
||||
// Build the arguments list
|
||||
var arguments = new List<string>
|
||||
{
|
||||
"--path",
|
||||
projectDirectory,
|
||||
//"--verbose"
|
||||
};
|
||||
|
||||
// Add any custom args
|
||||
arguments.AddRange(args);
|
||||
|
||||
// Create a standard ExecutableResource (since custom ones don't seem to work well)
|
||||
var godotResource = builder.AddExecutable(
|
||||
name: name,
|
||||
command: godotPath,
|
||||
workingDirectory: projectDirectory,
|
||||
args: arguments.ToArray());
|
||||
//.WithEnvironment("OTEL_EXPORTER_OTLP_ENDPOINT", Environment.GetEnvironmentVariable("OTEL_EXPORTER_OTLP_ENDPOINT") ?? throw new InvalidOperationException("OTEL_EXPORTER_OTLP_ENDPOINT environment variable is not set"));
|
||||
|
||||
// Add a lifecycle hook to handle building before startup
|
||||
builder.Services.AddSingleton<IDistributedApplicationLifecycleHook>(sp =>
|
||||
new GodotBuildHook(
|
||||
projectPath,
|
||||
projectDirectory,
|
||||
sp.GetRequiredService<ILogger<GodotBuildHook>>()));
|
||||
|
||||
return godotResource;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Godot executable path based on the current platform.
|
||||
/// </summary>
|
||||
private static string GetGodotExecutablePath()
|
||||
{
|
||||
// First check for GODOT environment variable
|
||||
var godotPath = Environment.GetEnvironmentVariable("GODOT");
|
||||
if (!string.IsNullOrWhiteSpace(godotPath))
|
||||
{
|
||||
return godotPath;
|
||||
}
|
||||
|
||||
// Fallback to platform-specific defaults
|
||||
if (OperatingSystem.IsMacOS())
|
||||
{
|
||||
return "godot";
|
||||
}
|
||||
else if (OperatingSystem.IsWindows())
|
||||
{
|
||||
return "godot.exe";
|
||||
}
|
||||
else if (OperatingSystem.IsLinux())
|
||||
{
|
||||
return "godot";
|
||||
}
|
||||
|
||||
throw new PlatformNotSupportedException("Current platform is not supported for Godot execution.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lifecycle hook to build the Godot project before launching
|
||||
/// </summary>
|
||||
private class GodotBuildHook : IDistributedApplicationLifecycleHook
|
||||
{
|
||||
private readonly string _projectPath;
|
||||
private readonly string _projectDirectory;
|
||||
private readonly ILogger<GodotBuildHook> _logger;
|
||||
|
||||
public GodotBuildHook(string projectPath, string projectDirectory, ILogger<GodotBuildHook> logger)
|
||||
{
|
||||
_projectPath = projectPath;
|
||||
_projectDirectory = projectDirectory;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task BeforeStartAsync(DistributedApplicationModel appModel, CancellationToken cancellationToken = default)
|
||||
{
|
||||
_logger.LogInformation("Building Godot project: {ProjectPath}", _projectPath);
|
||||
|
||||
// Execute dotnet build on the project
|
||||
var buildProcess = new System.Diagnostics.Process
|
||||
{
|
||||
StartInfo = new System.Diagnostics.ProcessStartInfo
|
||||
{
|
||||
FileName = "dotnet",
|
||||
Arguments = $"build \"{_projectPath}\" --configuration Debug",
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
WorkingDirectory = _projectDirectory
|
||||
}
|
||||
};
|
||||
|
||||
buildProcess.OutputDataReceived += (sender, e) =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(e.Data))
|
||||
{
|
||||
_logger.LogInformation("[Godot Build] {Data}", e.Data);
|
||||
}
|
||||
};
|
||||
|
||||
buildProcess.ErrorDataReceived += (sender, e) =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(e.Data))
|
||||
{
|
||||
_logger.LogError("[Godot Build] {Data}", e.Data);
|
||||
}
|
||||
};
|
||||
|
||||
buildProcess.Start();
|
||||
buildProcess.BeginOutputReadLine();
|
||||
buildProcess.BeginErrorReadLine();
|
||||
await buildProcess.WaitForExitAsync(cancellationToken);
|
||||
|
||||
if (buildProcess.ExitCode != 0)
|
||||
{
|
||||
_logger.LogError("Failed to build Godot project: {ProjectPath}", _projectPath);
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.LogInformation("Successfully built Godot project: {ProjectPath}", _projectPath);
|
||||
}
|
||||
|
||||
public Task AfterStartAsync(DistributedApplicationModel appModel, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
18
tools/AppHost/Properties/launchSettings.json
Normal file
18
tools/AppHost/Properties/launchSettings.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||
"profiles": {
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "https://localhost:17042",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development",
|
||||
"DOTNET_ENVIRONMENT": "Development",
|
||||
"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21295",
|
||||
"DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22130",
|
||||
"GODOT": "C:/Users/Matthew/Documents/Godot/4.5/Godot_v4.5-stable_mono_win64.exe"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
8
tools/AppHost/appsettings.Development.json
Normal file
8
tools/AppHost/appsettings.Development.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
9
tools/AppHost/appsettings.json
Normal file
9
tools/AppHost/appsettings.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning",
|
||||
"Aspire.Hosting.Dcp": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsAspireSharedProject>true</IsAspireSharedProject>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" />
|
||||
<PackageReference Include="OpenTelemetry.Extensions.Hosting" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.Http" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
45
tools/AspNetCoreServiceDefaults/GodotServiceDefaults.cs
Normal file
45
tools/AspNetCoreServiceDefaults/GodotServiceDefaults.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using OpenTelemetry;
|
||||
using OpenTelemetry.Metrics;
|
||||
using OpenTelemetry.Resources;
|
||||
using OpenTelemetry.Trace;
|
||||
|
||||
namespace Microsoft.Extensions.Hosting;
|
||||
|
||||
public static class GodotServiceDefaults
|
||||
{
|
||||
private static TracerProvider _tracerProvider;
|
||||
private static MeterProvider _meterProvider;
|
||||
public static void AddServiceDefaults()
|
||||
{
|
||||
var endpoint = Environment.GetEnvironmentVariable("OTEL_EXPORTER_OTLP_ENDPOINT");
|
||||
if (endpoint is null)
|
||||
{
|
||||
Console.WriteLine("OTEL_EXPORTER_OTLP_ENDPOINT is not set, skipping OpenTelemetry setup.");
|
||||
return;
|
||||
}
|
||||
var endpointUri = new Uri(endpoint!);
|
||||
var resource = ResourceBuilder.CreateDefault()
|
||||
.AddService("sharpide-godot");
|
||||
|
||||
_tracerProvider = Sdk.CreateTracerProviderBuilder()
|
||||
.SetResourceBuilder(resource)
|
||||
.AddSource("SharpIde")
|
||||
.AddOtlpExporter(options =>
|
||||
{
|
||||
options.Endpoint = endpointUri;
|
||||
options.Protocol = OpenTelemetry.Exporter.OtlpExportProtocol.Grpc;
|
||||
})
|
||||
.Build();
|
||||
|
||||
_meterProvider = Sdk.CreateMeterProviderBuilder()
|
||||
.SetResourceBuilder(resource)
|
||||
.AddMeter("SharpIde")
|
||||
.AddRuntimeInstrumentation()
|
||||
.AddOtlpExporter(options =>
|
||||
{
|
||||
options.Endpoint = endpointUri;
|
||||
options.Protocol = OpenTelemetry.Exporter.OtlpExportProtocol.Grpc;
|
||||
})
|
||||
.Build();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user