Development kits
ShareAspace is delivered with a set of development kits (DevKits) that support the implementation of extensions, integrations, and custom logic. These DevKits are distributed as NuGet packages and are intended to be referenced from custom projects during development.
Each DevKit targets a specific extension scenario, such as external events, tasks, validations, or mapping logic. The table below provides an overview of the available DevKits and their intended use.
Available development kits
| Dev kit | Description |
|---|---|
Eurostep.ModelFramework.DevKit.Mapping.1.9.0.xyz.nupkg |
Development kit for the ShareAspace mapping framework (see Mapping framework) |
Eurostep.ModelFramework.DevKit.Mapping.Testing.1.9.0.xyz.nupkg |
Development kit for building unit tests against mapping implemented using the ShareAspace mapping framework. |
Eurostep.ModelFramework.DevKit.Toolbox.1.9.0.xyz.nupkg |
Development kit for the ShareAspace SoftType toolbox. |
Eurostep.SAS.DevKit.External.Extension.1.9.0.xyz.nupkg |
Development kit with convenience libraries for using the ShareAspace REST APIs. |
Eurostep.SAS.DevKit.External.Extension.ExternalEvent.1.9.0.xyz.nupkg |
Development kit for implementing external event handlers (see External extensions) |
Eurostep.SAS.DevKit.External.Extension.ExternalTask.1.9.0.xyz.nupkg |
Development kit for implementing external tasks (see External extensions) |
Eurostep.SAS.DevKit.External.Extension.ExternalValidation.1.9.0.xyz.nupkg |
Development kit for implementing external event validators (see External extensions) |
Eurostep.SAS.DevKit.External.Extension.FileConverter.1.9.0.xyz.nupkg |
Development kit for implementing CAD conversion. |
Eurostep.SAS.DevKit.External.Extension.FilePreview.1.9.0.xyz.nupkg |
Development kit for implementing custom file preview generators (see External extensions) |
Eurostep.SAS.DevKit.External.Extension.FullTextIndexing.1.9.0.xyz.nupkg |
Development kit for implementing custom full text indexing (see External extensions) |
Eurostep.SAS.DevKit.External.Extension.FullTextSearch.1.9.0.xyz.nupkg |
Development kit for implementing custom full text search (see External extensions) |
Eurostep.SAS.DevKit.External.Extension.Mail.1.9.0.xyz.nupkg |
Development kit for implementing custom email handling (see External extensions) |
Eurostep.SAS.DevKit.External.Logging.ShareAspace.1.9.0.xyz.nupkg |
Development kit for for reporting extension log information back to ShareAspace. (see External extensions) |
OpenTelemetry (OTEL) and Application Insights in custom extension
ShareAspace provides built‑in support for OpenTelemetry (OTEL) for logging, tracing, and metrics. When developing custom external extensions, it is recommended to use the same telemetry stack to ensure consistent observability and integration with the ShareAspace platform.
For .NET‑based external extensions, OpenTelemetry can be enabled by adding the required NuGet dependencies and configuring the application during startup. The same configuration can optionally be extended to export telemetry data to Azure Application Insights.
Required NuGet packages
<PackageReference Include="Azure.Monitor.OpenTelemetry.AspNetCore" />
<PackageReference Include="Microsoft.Extensions.Http.Resilience" />
<PackageReference Include="Microsoft.Extensions.ServiceDiscovery" />
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" />
<PackageReference Include="OpenTelemetry.Instrumentation.Http" />
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" />
These packages enable:
- OTEL logging, tracing, and metrics.
- Automatic instrumentation for ASP.NET Core, HTTP clients, and runtime metrics.
- Export of telemetry data via the OTLP protocol.
- Optional export to Azure Monitor / Application Insights.
Configuring OpenTelemetry in an external extension
The following example demonstrates how to enable OpenTelemetry in an external extension that uses the ExternalEvent DevKit. The configuration is encapsulated in reusable extension methods that can be shared across multiple services.
Common service defaults and OpenTelemetry configuration
Add the following helper class to your solution. It configures logging, metrics, tracing, health checks, and OTLP or Azure Monitor exporters based on configuration.
using Azure.Monitor.OpenTelemetry.AspNetCore;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using OpenTelemetry.Exporter;
using OpenTelemetry.Logs;
using OpenTelemetry.Metrics;
using OpenTelemetry.Trace;
using System.Security.Cryptography.X509Certificates;
namespace Microsoft.Extensions.Hosting;
// Adds common .NET Aspire services: service discovery, resilience, health checks, and OpenTelemetry.
// This project should be referenced by each service project in your solution.
// To learn more about using this project, see https://aka.ms/dotnet/aspire/service-defaults
public static class Extensions
{
public static IHostApplicationBuilder AddServiceDefaults(this IHostApplicationBuilder builder)
{
builder.ConfigureOpenTelemetry();
builder.AddDefaultHealthChecks();
builder.Services.AddServiceDiscovery();
builder.Services.ConfigureHttpClientDefaults(http =>
{
// Turn on resilience by default
http.AddStandardResilienceHandler();
// Turn on service discovery by default
http.AddServiceDiscovery();
});
return builder;
}
public static IHostApplicationBuilder ConfigureOpenTelemetry(this IHostApplicationBuilder builder)
{
builder.Logging.ClearProviders();
builder.Logging.AddOpenTelemetry(logging =>
{
logging.IncludeFormattedMessage = true;
logging.IncludeScopes = true;
});
builder.Services.AddOpenTelemetry()
.WithMetrics(metrics =>
{
metrics.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddRuntimeInstrumentation();
})
.WithTracing(tracing =>
{
tracing.AddAspNetCoreInstrumentation()
// Uncomment the following line to enable gRPC instrumentation (requires the OpenTelemetry.Instrumentation.GrpcNetClient package)
//.AddGrpcClientInstrumentation()
.AddHttpClientInstrumentation();
});
builder.AddOpenTelemetryExporters();
return builder;
}
private static IHostApplicationBuilder AddOpenTelemetryExporters(this IHostApplicationBuilder builder)
{
var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]);
var useOtlpClientCert = !string.IsNullOrWhiteSpace(builder.Configuration["X_OTEL_EXPORTER_OTLP_CLIENT_PFX"]);
var otlpClientCert = builder.Configuration["X_OTEL_EXPORTER_OTLP_CLIENT_PFX"];
var otlpClientPassword = builder.Configuration["X_OTEL_EXPORTER_OTLP_CLIENT_PASSWORD"];
X509Certificate2? clientCertificate = null;
if (useOtlpExporter)
{
var openTelemetryBuilder = builder.Services.AddOpenTelemetry();
if (useOtlpClientCert)
{
clientCertificate = X509CertificateLoader.LoadPkcs12FromFile(otlpClientCert, otlpClientPassword);
}
openTelemetryBuilder.WithLogging(b => b.AddOtlpExporter(opt => opt.HttpClientFactory =
HttpClientFactoryWithClientCertOptional(useOtlpClientCert, clientCertificate, opt)));
openTelemetryBuilder.WithMetrics(b => b.AddOtlpExporter(opt => opt.HttpClientFactory =
HttpClientFactoryWithClientCertOptional(useOtlpClientCert, clientCertificate, opt)));
openTelemetryBuilder.WithTracing(b => b.AddOtlpExporter(opt => opt.HttpClientFactory =
HttpClientFactoryWithClientCertOptional(useOtlpClientCert, clientCertificate, opt)));
if (useOtlpClientCert)
{
builder.Services.AddHttpClient("OtlpTraceExporter", (provider, client) => { })
.ConfigurePrimaryHttpMessageHandler(() => CreateClientCertEnabledHandler(clientCertificate));
builder.Services.AddHttpClient("OtlpMetricExporter", (provider, client) => { })
.ConfigurePrimaryHttpMessageHandler(() => CreateClientCertEnabledHandler(clientCertificate));
}
}
if (!string.IsNullOrEmpty(builder.Configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"]))
{
builder.Services.AddOpenTelemetry()
.UseAzureMonitor();
}
return builder;
}
private static Func<HttpClient> HttpClientFactoryWithClientCertOptional(bool useOtlpClientCert,
X509Certificate2? clientCertificate, OtlpExporterOptions opt)
{
return () =>
{
var handler = useOtlpClientCert
? CreateClientCertEnabledHandler(clientCertificate)
: new HttpClientHandler();
return new HttpClient(handler) { Timeout = TimeSpan.FromMilliseconds(opt.TimeoutMilliseconds) };
};
}
private static HttpMessageHandler CreateClientCertEnabledHandler(X509Certificate cert)
{
var handler = new HttpClientHandler();
handler.ClientCertificates.Add(cert);
handler.ClientCertificateOptions = ClientCertificateOption.Automatic;
return handler;
}
public static IHostApplicationBuilder AddDefaultHealthChecks(this IHostApplicationBuilder builder)
{
builder.Services.AddHealthChecks()
// Add a default liveness check to ensure app is responsive
.AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]);
return builder;
}
}
This setup ensures:
- Logs are emitted through OpenTelemetry instead of default .NET logging providers.
- Metrics and traces are automatically collected.
- Exporters are enabled based on configuration values.
Enabling telemetry in the extension startup
Once the service defaults are defined, enable them in the extension’s startup code by calling
AddServiceDefaults() on the application builder.
Example startup configuration for an external extension:
using Eurostep.SAS.External.Extension;
using Microsoft.AspNetCore.Server.Kestrel.Core;
var builder = WebApplication.CreateBuilder();
builder.AddServiceDefaults();
var services = builder.Services;
services.AddRouting();
services.AddHttpClient();
services.AddNovaExternalExtensions();
var app = builder.Build();
var env = builder.Environment;
app.UseForwardedHeaders();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseNovaExternalExtensions("");
await app.RunAsync();
Configuration using OTLP (ShareAspace OTEL collector)
Telemetry exporters are configured using standard OpenTelemetry environment variables.
The following example shows a typical appsettings.json configuration when exporting
telemetry data to the ShareAspace OTEL collector (or other OTEL collector).
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"NovaConfig": {
"SymmetricKey": "_APISYMKEY_"
},
"OTEL_SERVICE_NAME": "My.Custom.Extension",
"OTEL_EXPORTER_OTLP_ENDPOINT": "_OTELCOLLECTORGRPCURI_",
"OTEL_EXPORTER_OTLP_PROTOCOL": "grpc",
"OTEL_DOTNET_EXPERIMENTAL_ASPNETCORE_DISABLE_URL_QUERY_REDACTION": "true",
"OTEL_DOTNET_EXPERIMENTAL_HTTPCLIENT_DISABLE_URL_QUERY_REDACTION": "true",
"OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES": "true",
"OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EXCEPTION_LOG_ATTRIBUTES": "true",
"OTEL_DOTNET_EXPERIMENTAL_OTLP_RETRY": "in_memory"
}
When these settings are present, the extension exports logs, metrics, and traces to the configured OTLP endpoint.
Using Azure Application Insights instead of OTLP
If you want to send telemetry data to Azure Application Insights instead of the ShareAspace OTEL file logger and collector, replace the OTLP‑specific settings with an Application Insights connection string.
Remove the following settings:
"OTEL_EXPORTER_OTLP_ENDPOINT": "_OTELCOLLECTORGRPCURI_",
"OTEL_EXPORTER_OTLP_PROTOCOL": "grpc",
"OTEL_DOTNET_EXPERIMENTAL_ASPNETCORE_DISABLE_URL_QUERY_REDACTION": "true",
"OTEL_DOTNET_EXPERIMENTAL_HTTPCLIENT_DISABLE_URL_QUERY_REDACTION": "true",
"OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES": "true",
"OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EXCEPTION_LOG_ATTRIBUTES": "true",
"OTEL_DOTNET_EXPERIMENTAL_OTLP_RETRY": "in_memory"
And add the following setting instead:
"APPLICATIONINSIGHTS_CONNECTION_STRING": "InstrumentationKey=REDACTED;IngestionEndpoint=REDACTED;LiveEndpoint=REDACTED;ApplicationId=REDACTED"
When this connection string is present, the Azure Monitor OpenTelemetry exporter is automatically enabled, and all telemetry data is sent to Application Insights.