diff --git a/src/Aspire.Cli/Commands/RootCommand.cs b/src/Aspire.Cli/Commands/RootCommand.cs index 326c3d68ff3..98c0b9ed9c9 100644 --- a/src/Aspire.Cli/Commands/RootCommand.cs +++ b/src/Aspire.Cli/Commands/RootCommand.cs @@ -27,6 +27,25 @@ public RootCommand(NewCommand newCommand, RunCommand runCommand, AddCommand addC waitForDebuggerOption.Recursive = true; waitForDebuggerOption.DefaultValueFactory = (result) => false; + var otelOption = new Option("--cli-otlp-endpoint"); + otelOption.Description = "Send telemetry to the OpenTelemetry collector"; + otelOption.Validators.Add((result) => { + var otelUrl = result.GetValueOrDefault(); + + if (Uri.TryCreate(otelUrl, UriKind.Absolute, out var otelUri) && (otelUri.Scheme == Uri.UriSchemeHttp || otelUri.Scheme == Uri.UriSchemeHttps)) + { + // If we have a valid URL then we can just return. + return; + } + else + { + result.AddError("The OpenTelemetry URL must be an absolute URI with either HTTP or HTTPS scheme."); + } + }); + otelOption.Recursive = true; + otelOption.Hidden = true; // Hiding for now since this could be confusing about what it does. + Options.Add(otelOption); + #if DEBUG waitForDebuggerOption.Validators.Add((result) => { diff --git a/src/Aspire.Cli/Program.cs b/src/Aspire.Cli/Program.cs index 3a7cb7e944f..d04ce9cebd6 100644 --- a/src/Aspire.Cli/Program.cs +++ b/src/Aspire.Cli/Program.cs @@ -16,6 +16,7 @@ using OpenTelemetry.Trace; #endif +using Spectre.Console; using RootCommand = Aspire.Cli.Commands.RootCommand; namespace Aspire.Cli; @@ -54,12 +55,22 @@ private static IHost BuildApplication(string[] args) tracing.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("aspire-cli")); }); - if (builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"] is {}) + // NOTE: Actual arg validation will take place elsewhere, this is just + // a quick check to make sure that DI is configured correctly. + if (args.IndexOf("--cli-otlp-endpoint") is var otelArgIndex && otelArgIndex != -1) { - // NOTE: If we always enable the OTEL exporter it dramatically - // impacts the CLI in terms of exiting quickly because it - // has to finish sending telemetry. - otelBuilder.UseOtlpExporter(); + // If we have an --cli-otlp-endpoint switch then we need to check that we + // have at least enough args to have a base URL. + if (args.Length == otelArgIndex + 2) + { + var baseUrl = args[otelArgIndex + 1]; + + // If we have enough arguments we need to make sure its a valid URL. + if (Uri.TryCreate(baseUrl, UriKind.Absolute, out var baseUri) && (baseUri.Scheme == Uri.UriSchemeHttp || baseUri.Scheme == Uri.UriSchemeHttps)) + { + otelBuilder.UseOtlpExporter(OpenTelemetry.Exporter.OtlpExportProtocol.Grpc, baseUri); + } + } } #endif