Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,10 @@ public static IResourceBuilder<OpenTelemetryCollectorResource> AddOpenTelemetryC

var isHttpsEnabled = !settings.ForceNonSecureReceiver && url.StartsWith("https", StringComparison.OrdinalIgnoreCase);

var dashboardOtlpEndpoint = ReplaceLocalhostWithContainerHost(url, builder.Configuration);

var resource = new OpenTelemetryCollectorResource(name);
var resourceBuilder = builder.AddResource(resource)
.WithImage(settings.CollectorImage, settings.CollectorTag)
.WithEnvironment("ASPIRE_ENDPOINT", dashboardOtlpEndpoint)
.WithEnvironment("ASPIRE_ENDPOINT", new HostUrl(url))
.WithEnvironment("ASPIRE_API_KEY", builder.Configuration[DashboardOtlpApiKeyVariableName]);

if (settings.EnableGrpcEndpoint)
Expand All @@ -53,8 +51,11 @@ public static IResourceBuilder<OpenTelemetryCollectorResource> AddOpenTelemetryC
if (!settings.ForceNonSecureReceiver && isHttpsEnabled && builder.ExecutionContext.IsRunMode && builder.Environment.IsDevelopment())
{
resourceBuilder.RunWithHttpsDevCertificate();
var certFilePath = Path.Combine(DevCertHostingExtensions.DEV_CERT_BIND_MOUNT_DEST_DIR, DevCertHostingExtensions.CERT_FILE_NAME);
var certKeyPath = Path.Combine(DevCertHostingExtensions.DEV_CERT_BIND_MOUNT_DEST_DIR, DevCertHostingExtensions.CERT_KEY_FILE_NAME);

// Not using `Path.Combine` as we MUST use unix style paths in the container
var certFilePath = $"{DevCertHostingExtensions.DEV_CERT_BIND_MOUNT_DEST_DIR}/{DevCertHostingExtensions.CERT_FILE_NAME}";
var certKeyPath = $"{DevCertHostingExtensions.DEV_CERT_BIND_MOUNT_DEST_DIR}/{DevCertHostingExtensions.CERT_KEY_FILE_NAME}";

if (settings.EnableHttpEndpoint)
{
resourceBuilder.WithArgs(
Expand All @@ -78,19 +79,23 @@ public static IResourceBuilder<OpenTelemetryCollectorResource> AddOpenTelemetryC
/// <returns></returns>
public static IResourceBuilder<OpenTelemetryCollectorResource> WithAppForwarding(this IResourceBuilder<OpenTelemetryCollectorResource> builder)
{
builder.AddEnvironmentVariablesEventHook()
.WithFirstStartup();
builder.ApplicationBuilder.Eventing.Subscribe<BeforeStartEvent>((evt, ct) =>
{
var logger = evt.Services.GetRequiredService<ResourceLoggerService>().GetLogger(builder.Resource);
var otelSenders = evt.Model.Resources
.OfType<IResourceWithEnvironment>()
.Where(x => x.HasAnnotationOfType<OtlpExporterAnnotation>());

return builder;
}
foreach (var otelSender in otelSenders)
{
var otelSenderBuilder = builder.ApplicationBuilder.CreateResourceBuilder(otelSender);
otelSenderBuilder.WithOpenTelemetryCollectorRouting(builder);
}

private static string ReplaceLocalhostWithContainerHost(string value, IConfiguration configuration)
{
var hostName = configuration["AppHost:ContainerHostname"] ?? "host.docker.internal";
return Task.CompletedTask;
});

return value.Replace("localhost", hostName, StringComparison.OrdinalIgnoreCase)
.Replace("127.0.0.1", hostName)
.Replace("[::1]", hostName);
return builder;
}

/// <summary>
Expand All @@ -106,73 +111,4 @@ public static IResourceBuilder<OpenTelemetryCollectorResource> WithConfig(this I
.WithArgs($"--config=/config/{configFileInfo.Name}");
}

/// <summary>
/// Sets up the OnBeforeResourceStarted event to add a wait annotation to all resources that have the OtlpExporterAnnotation
/// </summary>
/// <param name="builder"></param>
/// <returns></returns>
private static IResourceBuilder<OpenTelemetryCollectorResource> WithFirstStartup(this IResourceBuilder<OpenTelemetryCollectorResource> builder)
{
builder.OnBeforeResourceStarted((collectorResource, beforeStartedEvent, cancellationToken) =>
{
var logger = beforeStartedEvent.Services.GetRequiredService<ResourceLoggerService>().GetLogger(collectorResource);
var appModel = beforeStartedEvent.Services.GetRequiredService<DistributedApplicationModel>();
var resources = appModel.GetProjectResources();

foreach (var resourceItem in resources.Where(r => r.HasAnnotationOfType<OtlpExporterAnnotation>()))
{
resourceItem.Annotations.Add(new WaitAnnotation(collectorResource, WaitType.WaitUntilHealthy));
}
return Task.CompletedTask;
});
return builder;
}

/// <summary>
/// Sets up the OnResourceEndpointsAllocated event to add/update the OTLP environment variables for the collector to the various resources
/// </summary>
/// <param name="builder"></param>
private static IResourceBuilder<OpenTelemetryCollectorResource> AddEnvironmentVariablesEventHook(this IResourceBuilder<OpenTelemetryCollectorResource> builder)
{
builder.OnResourceEndpointsAllocated((collectorResource, allocatedEvent, cancellationToken) =>
{
var logger = allocatedEvent.Services.GetRequiredService<ResourceLoggerService>().GetLogger(collectorResource);
var appModel = allocatedEvent.Services.GetRequiredService<DistributedApplicationModel>();
var resources = appModel.GetProjectResources();

var grpcEndpoint = collectorResource.GetEndpoint(collectorResource.GrpcEndpoint.EndpointName);
var httpEndpoint = collectorResource.GetEndpoint(collectorResource.HttpEndpoint.EndpointName);

if (!resources.Any())
{
logger.LogInformation("No resources to add Environment Variables to");
}

foreach (var resourceItem in resources.Where(r => r.HasAnnotationOfType<OtlpExporterAnnotation>()))
{
logger.LogDebug("Forwarding Telemetry for {name} to the collector", resourceItem.Name);
if (resourceItem is null) continue;

resourceItem.Annotations.Add(new EnvironmentCallbackAnnotation(context =>
{
var protocol = context.EnvironmentVariables.GetValueOrDefault("OTEL_EXPORTER_OTLP_PROTOCOL", "");
var endpoint = protocol.ToString() == "http/protobuf" ? httpEndpoint : grpcEndpoint;

if (endpoint is null)
{
logger.LogWarning("No {protocol} endpoint on the collector for {resourceName} to use",
protocol, resourceItem.Name);
return;
}

context.EnvironmentVariables.Remove("OTEL_EXPORTER_OTLP_ENDPOINT");
context.EnvironmentVariables.Add("OTEL_EXPORTER_OTLP_ENDPOINT", endpoint.Url);
}));
}

return Task.CompletedTask;
});

return builder;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,9 @@ public void ContainerHasAspireEnvironmentVariables()

Assert.Contains("ASPIRE_ENDPOINT", context.EnvironmentVariables.Keys);
Assert.Contains("ASPIRE_API_KEY", context.EnvironmentVariables.Keys);
Assert.Equal("http://host.docker.internal:18889", context.EnvironmentVariables["ASPIRE_ENDPOINT"]);

var url = Assert.IsType<HostUrl>(context.EnvironmentVariables["ASPIRE_ENDPOINT"]);
Assert.Equal("http://localhost:18889", url.Url);
Assert.NotNull(context.EnvironmentVariables["ASPIRE_API_KEY"]);
}

Expand Down
Loading