diff --git a/documentation/docs/developer-guide/logging/opentelemetry.md b/documentation/docs/developer-guide/logging/opentelemetry.md new file mode 100644 index 0000000000..c42850a601 --- /dev/null +++ b/documentation/docs/developer-guide/logging/opentelemetry.md @@ -0,0 +1,98 @@ +# Open Telemetry logging + +- Scroll down to [setup](#setup) for the settings + +## Why OpenTelemetry? + +OpenTelemetry has emerged as a powerful and +standardized solution to address the challenges of observability in modern, +distributed systems. + +OpenTelemetry is an open-source project that provides a set of APIs, libraries, agents, +and instrumentation to enable observability in cloud-native applications. + +Observability, in the context of software systems, +refers to the ability to understand and measure how well a system is operating. +It involves collecting and analyzing data related to key aspects such as traces, +metrics, and logs. OpenTelemetry focuses on two primary pillars of observability: +tracing and metrics. + +### Distributed Tracing: +OpenTelemetry allows developers to trace requests as they traverse +through various services in a distributed environment. +This helps identify performance bottlenecks, understand dependencies between services, +and diagnose issues across the entire application stack. +By providing a standardized way to instrument code and capture trace data, +OpenTelemetry simplifies the process of generating insights into the flow of requests in complex, +microservices-based architectures. + +### Metrics Collection: +Monitoring the health and performance of applications involves the collection of metrics. +OpenTelemetry provides a consistent API for capturing metrics from different parts of an application. +Metrics such as latency, error rates, and resource utilization +can be collected and analyzed to gain a comprehensive view of application behavior. +This information is invaluable for proactive issue detection, capacity planning, and overall system optimization. + +OpenTelemetry supports multiple programming languages and integrates seamlessly with various observability backends, +including popular solutions like Prometheus, Jaeger, and Grafana. + +Its adaptability and community-driven development make it a versatile choice for organizations seeking +to implement observability in their applications, regardless of the technology stack they use. + +In conclusion, OpenTelemetry plays a pivotal role in the modern software development landscape by providing +a standardized and extensible framework for observability. +Its ability to capture distributed traces and metrics empowers developers and operators to +gain deep insights into the performance and behavior of their applications, +facilitating efficient troubleshooting and continuous improvement. + +## Setup +The following settings can be used: + +### json configuration + +use for example this file name: appsettings.machinename.json + +### Order of appsettings patch files + +1. You can use `appsettings.json` inside the application folder to set base settings. + The order of this files is used to get the values from the appsettings + - `/bin/Debug/net6.0/appsettings.patch.json` + - `/bin/Debug/net6.0/appsettings.default.json` + - `/bin/Debug/net6.0/appsettings.computername.patch.json` + - `/bin/Debug/net6.0/appsettings.json` + - `/bin/Debug/net6.0/appsettings.computername.json` + +```json +{ + "app" : { + "OpenTelemetry": { + "TracesEndpoint": "http://test", + "MetricsEndpoint": null, + "LogsEndpoint": null + } + } +} +``` + + +### Environment variables + +```bash +"app__OpenTelemetry__TracesEndpoint": "https://otlp.eu01.nr-data.net:4318/v1/traces", +"app__OpenTelemetry__MetricsEndpoint": "https://otlp.eu01.nr-data.net:4318/v1/metrics", +"app__OpenTelemetry__LogsEndpoint": "https://otlp.eu01.nr-data.net:4318/v1/logs", +"app__OpenTelemetry__Header": "api-key=EXAMPLE_KEY", +"app__OpenTelemetry__ServiceName": "starsky-dev", +``` + +### Use a valid url +The properties assume that the Url is valid. It should start with http or https + +``` +Unhandled exception. System.UriFormatException: Invalid URI: The format of the URI could not be determined. +at System.Uri.CreateThis(String uri, Boolean dontEscape, UriKind uriKind, UriCreationOptions& creationOptions) +at System.Uri..ctor(String uriString) +at starsky.foundation.webtelemetry.Extensions.OpenTelemetryExtension.<>c__DisplayClass0_0. +b__4(OtlpExporterOptions o) in ..Extensions/OpenTelemetryExtension.cs:line 48 +``` + diff --git a/documentation/docs/developer-guide/logging/readme.md b/documentation/docs/developer-guide/logging/readme.md index 0e6867c27d..abb4126ee7 100644 --- a/documentation/docs/developer-guide/logging/readme.md +++ b/documentation/docs/developer-guide/logging/readme.md @@ -4,6 +4,9 @@ sidebar_position: 20 # Logging +## Open Telemetry logging +See [Open Telemetry logging](opentelemetry.md) + ## Desktop logs For the desktop app the logs are stored in following location: diff --git a/history.md b/history.md index c2414ccb85..316a2497b3 100644 --- a/history.md +++ b/history.md @@ -36,7 +36,8 @@ Semantic Versioning 2.0.0 is from version 0.1.6+ ## List of versions ## version 0.5.15 _(Unreleased)_ - 2024-01-? {#v0.5.15} -- no changes yet + +- [x] (Added) _Back-end_ Add support for OpenTelemetry (server side only) (PR #1323) ## version 0.5.14 - 2023-12-29 {#v0.5.14} diff --git a/starsky/starsky.foundation.platform/Helpers/AppSettingsCompareHelper.cs b/starsky/starsky.foundation.platform/Helpers/AppSettingsCompareHelper.cs index 44e2ce3e5c..7cc9b5aa0b 100644 --- a/starsky/starsky.foundation.platform/Helpers/AppSettingsCompareHelper.cs +++ b/starsky/starsky.foundation.platform/Helpers/AppSettingsCompareHelper.cs @@ -33,11 +33,42 @@ public static List Compare(AppSettings sourceIndexItem, object? updateOb CompareMultipleSingleItems(propertyB, propertyInfoFromA, sourceIndexItem, updateObject, differenceList); CompareMultipleListDictionary(propertyB, propertyInfoFromA, sourceIndexItem, updateObject, differenceList); + CompareMultipleObjects(propertyB, propertyInfoFromA, sourceIndexItem, updateObject, differenceList); } return differenceList; } + private static void CompareMultipleObjects(PropertyInfo propertyB, PropertyInfo propertyInfoFromA, AppSettings sourceIndexItem, object updateObject, List differenceList) + { + if (propertyInfoFromA.PropertyType == typeof(OpenTelemetrySettings) && propertyB.PropertyType == typeof(OpenTelemetrySettings)) + { + var oldObjectValue = (OpenTelemetrySettings?)propertyInfoFromA.GetValue(sourceIndexItem, null); + var newObjectValue = (OpenTelemetrySettings?)propertyB.GetValue(updateObject, null); + CompareOpenTelemetrySettingsObject(propertyB.Name, sourceIndexItem, oldObjectValue, newObjectValue, differenceList); + } + } + + private static void CompareOpenTelemetrySettingsObject(string propertyName, AppSettings? sourceIndexItem, + OpenTelemetrySettings? oldKeyValuePairStringStringValue, + OpenTelemetrySettings? newKeyValuePairStringStringValue, ICollection differenceList) + { + if ( oldKeyValuePairStringStringValue == null || + newKeyValuePairStringStringValue == null || + // compare lists + JsonSerializer.Serialize(oldKeyValuePairStringStringValue) == + JsonSerializer.Serialize(newKeyValuePairStringStringValue) || + // default options + JsonSerializer.Serialize(newKeyValuePairStringStringValue) == + JsonSerializer.Serialize(new OpenTelemetrySettings())) + { + return; + } + + sourceIndexItem?.GetType().GetProperty(propertyName)?.SetValue(sourceIndexItem, newKeyValuePairStringStringValue, null); + differenceList.Add(propertyName.ToLowerInvariant()); + } + private static void CompareMultipleSingleItems(PropertyInfo propertyB, PropertyInfo propertyInfoFromA, AppSettings sourceIndexItem, object updateObject, diff --git a/starsky/starsky.foundation.platform/Models/AppSettings.cs b/starsky/starsky.foundation.platform/Models/AppSettings.cs index 4d15b3a4d9..73946ff904 100644 --- a/starsky/starsky.foundation.platform/Models/AppSettings.cs +++ b/starsky/starsky.foundation.platform/Models/AppSettings.cs @@ -879,6 +879,9 @@ private string AssemblyDirectoryReplacer(string value) /// public bool? ExiftoolSkipDownloadOnStartup { get; set; } = false; + public OpenTelemetrySettings OpenTelemetry { get; set; } = + new OpenTelemetrySettings(); + /// AppSettings duplicated /// /// Duplicate this item in memory. AND remove _databaseConnection @@ -927,9 +930,43 @@ public AppSettings CloneToDisplay() } } + ReplaceOpenTelemetryData(appSettings); + return appSettings; } + private static void ReplaceOpenTelemetryData(AppSettings appSettings) + { + if ( appSettings.OpenTelemetry == null ) + { + return; + } + + if (!string.IsNullOrEmpty(appSettings.OpenTelemetry.Header) ) + { + appSettings.OpenTelemetry.Header = + CloneToDisplaySecurityWarning; + } + + if (!string.IsNullOrEmpty(appSettings.OpenTelemetry.MetricsHeader) ) + { + appSettings.OpenTelemetry.MetricsHeader = + CloneToDisplaySecurityWarning; + } + + if (!string.IsNullOrEmpty(appSettings.OpenTelemetry.LogsHeader) ) + { + appSettings.OpenTelemetry.LogsHeader = + CloneToDisplaySecurityWarning; + } + + if (!string.IsNullOrEmpty(appSettings.OpenTelemetry.TracesHeader) ) + { + appSettings.OpenTelemetry.TracesHeader = + CloneToDisplaySecurityWarning; + } + } + private static void ReplaceAppSettingsPublishProfilesCloneToDisplay(AppSettingsPublishProfiles value) { if ( !string.IsNullOrEmpty(value.Path) && value.Path != AppSettingsPublishProfiles.GetDefaultPath() ) diff --git a/starsky/starsky.foundation.platform/Models/OpenTelemetrySettings.cs b/starsky/starsky.foundation.platform/Models/OpenTelemetrySettings.cs new file mode 100644 index 0000000000..2fdbe8cf06 --- /dev/null +++ b/starsky/starsky.foundation.platform/Models/OpenTelemetrySettings.cs @@ -0,0 +1,44 @@ +namespace starsky.foundation.platform.Models; + +public class OpenTelemetrySettings +{ + public string Header { get; set; } + + public string ServiceName { get; set; } + public string TracesEndpoint { get; set; } + public string TracesHeader { get; set; } + + public string MetricsEndpoint { get; set; } + public string MetricsHeader { get; set; } + + public string LogsEndpoint { get; set; } + public string LogsHeader { get; set; } + + public string GetServiceName() + { + return string.IsNullOrWhiteSpace(ServiceName) + ? "Starsky" + : ServiceName ; + } + + public string GetLogsHeader() + { + return string.IsNullOrWhiteSpace(LogsHeader) + ? Header + : LogsHeader; + } + + public string GetMetricsHeader() + { + return string.IsNullOrWhiteSpace(MetricsHeader) + ? Header + : MetricsHeader; + } + + public string GetTracesHeader() + { + return string.IsNullOrWhiteSpace(TracesHeader) + ? Header + : TracesHeader; + } +} diff --git a/starsky/starsky.foundation.webtelemetry/Extensions/OpenTelemetryExtension.cs b/starsky/starsky.foundation.webtelemetry/Extensions/OpenTelemetryExtension.cs new file mode 100644 index 0000000000..3fb7a94de9 --- /dev/null +++ b/starsky/starsky.foundation.webtelemetry/Extensions/OpenTelemetryExtension.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Runtime.CompilerServices; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; +using OpenTelemetry.Exporter; +using OpenTelemetry.Metrics; +using OpenTelemetry.Resources; +using OpenTelemetry.Trace; +using starsky.foundation.platform.Models; + +[assembly: InternalsVisibleTo("starskytest")] +namespace starsky.foundation.webtelemetry.Extensions; + +public static class OpenTelemetryExtension +{ + /// + /// Add Metrics & Monitoring for OpenTelemetry + /// + /// collection service + /// to use for OpenTelemetry keys and info + public static void AddOpenTelemetryMonitoring( + this IServiceCollection services, AppSettings appSettings) + { + var telemetryBuilder = services.AddOpenTelemetry() + .ConfigureResource(resource => resource.AddService( + serviceNamespace: appSettings.OpenTelemetry.GetServiceName(), + serviceName: appSettings.OpenTelemetry.GetServiceName(), + serviceVersion: Assembly.GetEntryAssembly()?.GetName().Version + ?.ToString(), + serviceInstanceId: Environment.MachineName + ).AddAttributes(new Dictionary + { + { + "deployment.environment", + Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? string.Empty + } + })); + + if ( !string.IsNullOrWhiteSpace(appSettings.OpenTelemetry.TracesEndpoint) ) + { + telemetryBuilder.WithTracing(tracing => tracing + .AddAspNetCoreInstrumentation(o => o.Filter = FilterPath) + .AddOtlpExporter( + o => + { + o.Endpoint = + new Uri(appSettings.OpenTelemetry.TracesEndpoint); + o.Protocol = OtlpExportProtocol.HttpProtobuf; + o.Headers = appSettings.OpenTelemetry.GetTracesHeader(); + } + ).SetResourceBuilder( + ResourceBuilder.CreateDefault() + .AddService(appSettings.OpenTelemetry.GetServiceName()) + ) + ); + } + + if ( string.IsNullOrWhiteSpace( + appSettings.OpenTelemetry.MetricsEndpoint) ) + { + return; + } + + telemetryBuilder.WithMetrics(metrics => + metrics.AddAspNetCoreInstrumentation() + .AddRuntimeInstrumentation() + .AddHttpClientInstrumentation() + .AddOtlpExporter( + o => + { + o.Endpoint = new Uri(appSettings.OpenTelemetry.MetricsEndpoint); + o.Protocol = OtlpExportProtocol.HttpProtobuf; + o.Headers = appSettings.OpenTelemetry.GetMetricsHeader(); + }) + .SetResourceBuilder( + ResourceBuilder.CreateDefault() + .AddService(appSettings.OpenTelemetry.GetServiceName()) + ) + ); + } + + internal static bool FilterPath(HttpContext context) + { + if ( (context.Request.Path.Value?.EndsWith("/realtime") == true || + context.Request.Path.Value?.EndsWith("/api/health") == true || + context.Request.Path.Value?.EndsWith("/api/health/details") == true || + context.Request.Path.Value?.EndsWith("/api/open-telemetry/trace") == true) + && context.Response.StatusCode == 200) + { + return false; + } + + if ( context.Request.Path.Value?.EndsWith("/api/index") == true + && context.Response.StatusCode == 401) + { + return false; + } + + return true; + } +} diff --git a/starsky/starsky.foundation.webtelemetry/Helpers/SetupLogging.cs b/starsky/starsky.foundation.webtelemetry/Helpers/SetupLogging.cs index 5f4ac1961c..040e8ce6aa 100644 --- a/starsky/starsky.foundation.webtelemetry/Helpers/SetupLogging.cs +++ b/starsky/starsky.foundation.webtelemetry/Helpers/SetupLogging.cs @@ -1,6 +1,10 @@ +using System; using System.Diagnostics.CodeAnalysis; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using OpenTelemetry.Exporter; +using OpenTelemetry.Logs; +using OpenTelemetry.Resources; using starsky.foundation.platform.Interfaces; using starsky.foundation.platform.Models; using starsky.foundation.platform.Services; @@ -10,14 +14,32 @@ namespace starsky.foundation.webtelemetry.Helpers public static class SetupLogging { [SuppressMessage("Usage", "S4792:Make sure that this logger's configuration is safe.")] - public static void AddApplicationInsightsLogging(this IServiceCollection services, AppSettings appSettings) + public static void AddTelemetryLogging(this IServiceCollection services, AppSettings appSettings) { services.AddLogging(logging => { logging.ClearProviders(); logging.AddConsole(); - - // Skip when is Development + + if ( !string.IsNullOrEmpty(appSettings.OpenTelemetry.LogsEndpoint) ) + { + logging.AddOpenTelemetry(builder => + builder.AddOtlpExporter( + "logging", + options => + { + options.Protocol = OtlpExportProtocol.HttpProtobuf; + options.Headers = appSettings.OpenTelemetry.GetLogsHeader(); + options.Endpoint = new Uri(appSettings.OpenTelemetry.LogsEndpoint); + }) + .SetResourceBuilder( + ResourceBuilder.CreateDefault() + .AddService(appSettings.OpenTelemetry.GetServiceName()) + ) + ); + } + + // Remove when ApplicationInsights is phased out if (appSettings.ApplicationInsightsLog != true || string.IsNullOrWhiteSpace(appSettings.ApplicationInsightsConnectionString)) return; @@ -27,6 +49,8 @@ public static void AddApplicationInsightsLogging(this IServiceCollection service telemetryConfiguration.ConnectionString = appSettings.ApplicationInsightsConnectionString; }, _ => { }); + // End Remove when ApplicationInsights is phased out + }); services.AddScoped(); diff --git a/starsky/starsky.foundation.webtelemetry/Services/ApplicationInsightsJsHelper.cs b/starsky/starsky.foundation.webtelemetry/Services/ApplicationInsightsJsHelper.cs index 7fcd438f51..0f953370ab 100644 --- a/starsky/starsky.foundation.webtelemetry/Services/ApplicationInsightsJsHelper.cs +++ b/starsky/starsky.foundation.webtelemetry/Services/ApplicationInsightsJsHelper.cs @@ -8,6 +8,9 @@ namespace starsky.foundation.webtelemetry.Services { + /// + /// Remove when App insights is phased out + /// [Service(InjectionLifetime = InjectionLifetime.Scoped)] public sealed class ApplicationInsightsJsHelper { diff --git a/starsky/starsky.foundation.webtelemetry/Services/FilterStatusCodesInitializer.cs b/starsky/starsky.foundation.webtelemetry/Services/FilterStatusCodesInitializer.cs index e855300027..3bfedecbf8 100644 --- a/starsky/starsky.foundation.webtelemetry/Services/FilterStatusCodesInitializer.cs +++ b/starsky/starsky.foundation.webtelemetry/Services/FilterStatusCodesInitializer.cs @@ -5,6 +5,10 @@ namespace starsky.foundation.webtelemetry.Services { + /// + /// App Insights Filter Status Codes Initializer + /// Remove when App insights is phased out + /// [Service(typeof(ITelemetryInitializer), InjectionLifetime = InjectionLifetime.Singleton)] public sealed class FilterStatusCodesInitializer : ITelemetryInitializer { diff --git a/starsky/starsky.foundation.webtelemetry/Services/TelemetryService.cs b/starsky/starsky.foundation.webtelemetry/Services/TelemetryService.cs index ac49b129af..2531eb2d4d 100644 --- a/starsky/starsky.foundation.webtelemetry/Services/TelemetryService.cs +++ b/starsky/starsky.foundation.webtelemetry/Services/TelemetryService.cs @@ -7,6 +7,9 @@ namespace starsky.foundation.webtelemetry.Services { + /// + /// Remove when App insights is phased out + /// [Service(typeof(ITelemetryService), InjectionLifetime = InjectionLifetime.Singleton)] public sealed class TelemetryService : ITelemetryService { diff --git a/starsky/starsky.foundation.webtelemetry/starsky.foundation.webtelemetry.csproj b/starsky/starsky.foundation.webtelemetry/starsky.foundation.webtelemetry.csproj index f17f8cff49..cc8776c41b 100644 --- a/starsky/starsky.foundation.webtelemetry/starsky.foundation.webtelemetry.csproj +++ b/starsky/starsky.foundation.webtelemetry/starsky.foundation.webtelemetry.csproj @@ -23,6 +23,14 @@ + + + + + + + + diff --git a/starsky/starsky/Controllers/HealthController.cs b/starsky/starsky/Controllers/HealthController.cs index c3feb0cec3..c693f8ab27 100644 --- a/starsky/starsky/Controllers/HealthController.cs +++ b/starsky/starsky/Controllers/HealthController.cs @@ -168,6 +168,7 @@ private static HealthView CreateHealthEntryLog(HealthReport result) [AllowAnonymous] public IActionResult ApplicationInsights() { + // Remove when ApplicationInsights is phased out return Content(_applicationInsightsJsHelper.ScriptPlain, "application/javascript"); } diff --git a/starsky/starsky/Properties/default-init-launchSettings.json b/starsky/starsky/Properties/default-init-launchSettings.json index 34c8eede26..c31f279aa8 100644 --- a/starsky/starsky/Properties/default-init-launchSettings.json +++ b/starsky/starsky/Properties/default-init-launchSettings.json @@ -15,10 +15,10 @@ "app__NoAccountLocalhost": "false", "app__IsAccountRegisterOpen": "true", "app__SyncOnStartup": "false", - "_app__storageFolder": "remove prefix underscore", - "_app__dependenciesFolder": "remove prefix underscore", - "_app__ApplicationInsightsConnectionString": "remove prefix underscore", - "_app__DatabaseConnection": "Server=localhost;port=12838;database=starsky;uid=starsky;pwd=ad12dc47-a411-4dce-92b3-2649a755426c;maximumpoolsize=30;", + "___app__storageFolder": "remove prefix underscores ___ and update value", + "___app__dependenciesFolder": "remove prefix underscores ___and update value", + "___app__ApplicationInsightsConnectionString": "remove prefix underscores ___ and update value", + "___app__DatabaseConnection": "Server=localhost;port=12838;database=starsky;uid=starsky;pwd=ad12dc47-a411-4dce-92b3-2649a755426c;maximumpoolsize=30;", "app__DatabaseType": "Sqlite", "app__ApplicationInsightsDatabaseTracking": "true", "app__ApplicationInsightsLog": "true", @@ -27,7 +27,12 @@ "app__DemoUnsafeDeleteStorageFolder": "false", "app__useSystemTrash": "true", "app__accountRolesByEmailRegisterOverwrite__demo@qdraw.nl": "Administrator", - "app__ThumbnailGenerationIntervalInMinutes": "15" + "app__ThumbnailGenerationIntervalInMinutes": "15", + "___app__OpenTelemetry__TracesEndpoint": "http://localhost:4318/v1/traces", + "___app__OpenTelemetry__MetricsEndpoint": "http://localhost:4318/v1/metrics", + "___app__OpenTelemetry__LogsEndpoint": "http://localhost:4318/v1/logs", + "___app__OpenTelemetry__Header": "api-key=test", + "___app__OpenTelemetry__ServiceName": "starsky-dev" } } } diff --git a/starsky/starsky/Startup.cs b/starsky/starsky/Startup.cs index dddc1a132b..adfa4e5ec9 100644 --- a/starsky/starsky/Startup.cs +++ b/starsky/starsky/Startup.cs @@ -71,9 +71,10 @@ public void ConfigureServices(IServiceCollection services) // Detect Application Insights (used in next SetupDatabaseTypes) services.AddMonitoring(_appSettings); + services.AddOpenTelemetryMonitoring(_appSettings); // LoggerFactory - services.AddApplicationInsightsLogging(_appSettings); + services.AddTelemetryLogging(_appSettings); var foundationDatabaseName = typeof(ApplicationDbContext).Assembly.FullName?.Split(",").FirstOrDefault(); new SetupDatabaseTypes(_appSettings,services).BuilderDb(foundationDatabaseName); diff --git a/starsky/starsky/appsettings.json b/starsky/starsky/appsettings.json index bcf3f1f57a..279fb6552e 100644 --- a/starsky/starsky/appsettings.json +++ b/starsky/starsky/appsettings.json @@ -64,6 +64,11 @@ "SyncOnStartup": "true", "DemoUnsafeDeleteStorageFolder" : "false", "useSystemTrash": "true", + "OpenTelemetry": { + "TracesEndpoint": null, + "MetricsEndpoint": null, + "LogsEndpoint": null + }, "publishProfiles": { "_default": [ { diff --git a/starsky/starsky/clientapp/src/shared/cookie/get-cookie.spec.ts b/starsky/starsky/clientapp/src/shared/cookie/get-cookie.spec.ts new file mode 100644 index 0000000000..0ef3ebd7eb --- /dev/null +++ b/starsky/starsky/clientapp/src/shared/cookie/get-cookie.spec.ts @@ -0,0 +1,42 @@ +import { GetCookie } from "./get-cookie"; + +describe("GetCookie function", () => { + // Test case 1: Cookie with the specified name exists + test("should return the value of the cookie when it exists", () => { + // Mock document.cookie to simulate the presence of the cookie + document.cookie = "yourCookieName=yourCookieValue; path=/"; + + // Call the function and assert the result + expect(GetCookie("yourCookieName")).toBe("yourCookieValue"); + }); + + // Test case 2: Cookie with the specified name does not exist + test('should return "" when the cookie does not exist', () => { + // Mock document.cookie to simulate an empty cookie + document.cookie = ""; + + // Call the function and assert the result + expect(GetCookie("nonExistentCookie")).toBe(""); + }); + + // Test case 3: Cookie with the specified name has an empty value + test("should return an empty string when the cookie value is empty", () => { + // Mock document.cookie to simulate a cookie with an empty value + document.cookie = "emptyCookie=; path=/"; + + // Call the function and assert the result + expect(GetCookie("emptyCookie")).toBe(""); + }); + + // Test case 4: Cookie with the specified name has special characters + test("should return the correct value when the cookie value has special characters", () => { + // Mock document.cookie to simulate a cookie with special characters + document.cookie = + "specialCookie=%24%25%5E%26%2A%28%29%3D%2B%7B%7D%5B%5D%3B%3A%40%23%21%7C%3C%3E%2C%2F%3F; path=/"; + + // Call the function and assert the result + expect(GetCookie("specialCookie")).toBe( + "%24%25%5E%26%2A%28%29%3D%2B%7B%7D%5B%5D%3B%3A%40%23%21%7C%3C%3E%2C%2F%3F" + ); + }); +}); diff --git a/starsky/starsky/clientapp/src/shared/cookie/get-cookie.ts b/starsky/starsky/clientapp/src/shared/cookie/get-cookie.ts new file mode 100644 index 0000000000..2cfe72771e --- /dev/null +++ b/starsky/starsky/clientapp/src/shared/cookie/get-cookie.ts @@ -0,0 +1,6 @@ +export function GetCookie(name: string): string { + const regex = new RegExp("(^| )" + name + "=([^;]+)"); + const match = regex.exec(document.cookie); + if (match) return match[2]; + return ""; +} diff --git a/starsky/starsky/clientapp/src/shared/fetch-post.spec.ts b/starsky/starsky/clientapp/src/shared/fetch-post.spec.ts index f2ec4c2a11..60fb6dea95 100644 --- a/starsky/starsky/clientapp/src/shared/fetch-post.spec.ts +++ b/starsky/starsky/clientapp/src/shared/fetch-post.spec.ts @@ -15,7 +15,7 @@ describe("fetch-post", () => { headers: { Accept: "application/json", "Content-Type": "application/x-www-form-urlencoded", - "X-XSRF-TOKEN": "X-XSRF-TOKEN" + "X-XSRF-TOKEN": "" }, method: "post" }); @@ -36,7 +36,7 @@ describe("fetch-post", () => { headers: { Accept: "application/json", "Content-Type": "application/x-www-form-urlencoded", - "X-XSRF-TOKEN": "X-XSRF-TOKEN" + "X-XSRF-TOKEN": "" }, method: "post" }); @@ -62,7 +62,7 @@ describe("fetch-post", () => { headers: { Accept: "application/json", "Content-Type": "application/x-www-form-urlencoded", - "X-XSRF-TOKEN": "X-XSRF-TOKEN" + "X-XSRF-TOKEN": "" }, method: "post" }); @@ -81,7 +81,7 @@ describe("fetch-post", () => { headers: { Accept: "application/json", "Content-Type": "application/x-www-form-urlencoded", - "X-XSRF-TOKEN": "X-XSRF-TOKEN" + "X-XSRF-TOKEN": "" }, method: "post" }); diff --git a/starsky/starsky/clientapp/src/shared/fetch-post.ts b/starsky/starsky/clientapp/src/shared/fetch-post.ts index 2bf1d4ff4c..aa90edd515 100644 --- a/starsky/starsky/clientapp/src/shared/fetch-post.ts +++ b/starsky/starsky/clientapp/src/shared/fetch-post.ts @@ -1,24 +1,17 @@ import { IConnectionDefault } from "../interfaces/IConnectionDefault"; - +import { GetCookie } from "./cookie/get-cookie.ts"; const FetchPost = async ( url: string, body: string | FormData, method: "post" | "delete" = "post", headers: object = {} ): Promise => { - function getCookie(name: string): string { - const regex = new RegExp("(^| )" + name + "=([^;]+)"); - const match = regex.exec(document.cookie); - if (match) return match[2]; - return "X-XSRF-TOKEN"; - } - const settings: RequestInit = { method: method, body, credentials: "include" as RequestCredentials, headers: { - "X-XSRF-TOKEN": getCookie("X-XSRF-TOKEN"), + "X-XSRF-TOKEN": GetCookie("X-XSRF-TOKEN"), Accept: "application/json", ...headers } diff --git a/starsky/starsky/readme.md b/starsky/starsky/readme.md index 98fd031a2a..3a12ad32e6 100644 --- a/starsky/starsky/readme.md +++ b/starsky/starsky/readme.md @@ -92,6 +92,8 @@ You could use machine specific configuration files: appsettings.machinename.json 36. `GeoFilesSkipDownloadOnStartup` Skip download of GeoFiles on startup, _recommend to keep this false or null_ - _default false_ 37. `ExiftoolSkipDownloadOnStartup` Skip download of Exiftool on startup, _recommend to keep this false or null_ - _default false_ 38. `AccountRolesByEmailRegisterOverwrite` Overwrite the default role for a user by email address, _default empty list_ +39. `OpenTelemetry` See logging in an external service, _default no enabled_ see [OpenTelemetry](https://docs.qdraw.nl/docs/developer-guide/logging/opentelemetry.md) + ### Appsettings.json example ```json diff --git a/starsky/starskyadmincli/Program.cs b/starsky/starskyadmincli/Program.cs index 102566069e..0a89fa8dd6 100644 --- a/starsky/starskyadmincli/Program.cs +++ b/starsky/starskyadmincli/Program.cs @@ -38,7 +38,7 @@ internal static async Task Main(string[] args) var appSettings = serviceProvider.GetRequiredService(); services.AddMonitoringWorkerService(appSettings, AppSettings.StarskyAppType.Geo); - services.AddApplicationInsightsLogging(appSettings); + services.AddTelemetryLogging(appSettings); var webLogger = serviceProvider.GetRequiredService(); diff --git a/starsky/starskydemoseedcli/Program.cs b/starsky/starskydemoseedcli/Program.cs index de894549b3..a3b7d8e923 100644 --- a/starsky/starskydemoseedcli/Program.cs +++ b/starsky/starskydemoseedcli/Program.cs @@ -33,7 +33,7 @@ public static async Task Main(string[] args) var appSettings = serviceProvider.GetRequiredService(); services.AddMonitoringWorkerService(appSettings, AppSettings.StarskyAppType.DemoSeed); - services.AddApplicationInsightsLogging(appSettings); + services.AddTelemetryLogging(appSettings); new SetupDatabaseTypes(appSettings,services).BuilderDb(); serviceProvider = services.BuildServiceProvider(); diff --git a/starsky/starskygeocli/Program.cs b/starsky/starskygeocli/Program.cs index 721360bc1a..e912ac59bc 100644 --- a/starsky/starskygeocli/Program.cs +++ b/starsky/starskygeocli/Program.cs @@ -33,7 +33,7 @@ public static async Task Main(string[] args) var appSettings = serviceProvider.GetRequiredService(); services.AddMonitoringWorkerService(appSettings, AppSettings.StarskyAppType.Geo); - services.AddApplicationInsightsLogging(appSettings); + services.AddTelemetryLogging(appSettings); new SetupDatabaseTypes(appSettings,services).BuilderDb(); serviceProvider = services.BuildServiceProvider(); diff --git a/starsky/starskyimportercli/Program.cs b/starsky/starskyimportercli/Program.cs index 419666c42f..d59fdcfe65 100644 --- a/starsky/starskyimportercli/Program.cs +++ b/starsky/starskyimportercli/Program.cs @@ -32,7 +32,7 @@ public static async Task Main(string[] args) var appSettings = serviceProvider.GetRequiredService(); services.AddMonitoringWorkerService(appSettings, AppSettings.StarskyAppType.Importer); - services.AddApplicationInsightsLogging(appSettings); + services.AddTelemetryLogging(appSettings); new SetupDatabaseTypes(appSettings,services).BuilderDb(); serviceProvider = services.BuildServiceProvider(); diff --git a/starsky/starskysynchronizecli/Program.cs b/starsky/starskysynchronizecli/Program.cs index 197b10e56a..413ba31bc8 100644 --- a/starsky/starskysynchronizecli/Program.cs +++ b/starsky/starskysynchronizecli/Program.cs @@ -32,7 +32,7 @@ public static async Task Main(string[] args) var appSettings = serviceProvider.GetRequiredService(); services.AddMonitoringWorkerService(appSettings, AppSettings.StarskyAppType.Sync); - services.AddApplicationInsightsLogging(appSettings); + services.AddTelemetryLogging(appSettings); new SetupDatabaseTypes(appSettings,services).BuilderDb(); serviceProvider = services.BuildServiceProvider(); diff --git a/starsky/starskytest/starsky.foundation.platform/Helpers/AppSettingsCompareHelperTest.cs b/starsky/starskytest/starsky.foundation.platform/Helpers/AppSettingsCompareHelperTest.cs index df49b04cb4..73e14db215 100644 --- a/starsky/starskytest/starsky.foundation.platform/Helpers/AppSettingsCompareHelperTest.cs +++ b/starsky/starskytest/starsky.foundation.platform/Helpers/AppSettingsCompareHelperTest.cs @@ -477,5 +477,78 @@ public void CompareInt_NotFound() 2, list); Assert.IsNotNull(list); } + + [TestMethod] + public void OpenTelemetrySettings() + { + var source = new AppSettings + { + OpenTelemetry = new OpenTelemetrySettings + { + Header = "source/test", + TracesEndpoint = "source/traces", + TracesHeader = "source/traces", + MetricsEndpoint = "source/metrics", + MetricsHeader = "source/metrics", + LogsEndpoint = "source/logs", + LogsHeader = "source/logs" + } + }; + + var to = new AppSettings + { + OpenTelemetry = new OpenTelemetrySettings + { + Header = "to/test", + TracesEndpoint = "to/traces", + TracesHeader = "to/traces", + MetricsEndpoint = "to/metrics", + MetricsHeader = "to/metrics", + LogsEndpoint = "to/logs", + LogsHeader = "to/logs" + } + }; + + AppSettingsCompareHelper.Compare(source, to); + + Assert.AreEqual(source.OpenTelemetry.Header, to.OpenTelemetry.Header); + Assert.AreEqual(source.OpenTelemetry.TracesEndpoint, to.OpenTelemetry.TracesEndpoint); + Assert.AreEqual(source.OpenTelemetry.TracesHeader, to.OpenTelemetry.TracesHeader); + Assert.AreEqual(source.OpenTelemetry.MetricsEndpoint, to.OpenTelemetry.MetricsEndpoint); + Assert.AreEqual(source.OpenTelemetry.MetricsHeader, to.OpenTelemetry.MetricsHeader); + Assert.AreEqual(source.OpenTelemetry.LogsEndpoint, to.OpenTelemetry.LogsEndpoint); + Assert.AreEqual(source.OpenTelemetry.LogsHeader, to.OpenTelemetry.LogsHeader); + + } + + [TestMethod] + public void OpenTelemetrySettings_Ignore_DefaultOption() + { + var source = new AppSettings + { + OpenTelemetry = new OpenTelemetrySettings + { + Header = "source/test", + TracesEndpoint = "source/traces", + TracesHeader = "source/traces", + MetricsEndpoint = "source/metrics", + MetricsHeader = "source/metrics", + LogsEndpoint = "source/logs", + LogsHeader = "source/logs" + } + }; + + var to = new AppSettings + { + OpenTelemetry = new OpenTelemetrySettings() + }; + + AppSettingsCompareHelper.Compare(source, to); + + Assert.AreEqual("source/test", source.OpenTelemetry.Header); + Assert.AreEqual("source/traces", source.OpenTelemetry.TracesEndpoint); + Assert.AreEqual("source/metrics", source.OpenTelemetry.MetricsEndpoint); + Assert.AreEqual("source/logs", source.OpenTelemetry.LogsEndpoint); + } } } diff --git a/starsky/starskytest/starsky.foundation.platform/Models/AppSettingsTest.cs b/starsky/starskytest/starsky.foundation.platform/Models/AppSettingsTest.cs index fd9ea35818..7c84008cc2 100644 --- a/starsky/starskytest/starsky.foundation.platform/Models/AppSettingsTest.cs +++ b/starsky/starskytest/starsky.foundation.platform/Models/AppSettingsTest.cs @@ -1,11 +1,9 @@ using System; using System.Collections.Generic; using System.IO; -using System.Runtime.InteropServices; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.VisualStudio.TestTools.UnitTesting; -using Newtonsoft.Json.Linq; using starsky.foundation.platform.Extensions; using starsky.foundation.platform.Models; using starskytest.FakeCreateAn; @@ -363,7 +361,63 @@ public void AppSettings_CloneToDisplay_hideSecurityItems() Assert.AreEqual(AppSettings.CloneToDisplaySecurityWarning, display.WebFtp); Assert.AreEqual(AppSettings.CloneToDisplaySecurityWarning, display.ApplicationInsightsConnectionString); } + + [TestMethod] + public void AppSettings_CloneToDisplay_hideSecurityItems2() + { + var appSettings = new AppSettings + { + OpenTelemetry = new OpenTelemetrySettings + { + Header = "test", + LogsHeader = "test", + MetricsHeader = "test", + TracesHeader = "test" + } + }; + var display = appSettings.CloneToDisplay(); + + Assert.AreEqual(AppSettings.CloneToDisplaySecurityWarning, display.OpenTelemetry.Header); + Assert.AreEqual(AppSettings.CloneToDisplaySecurityWarning, display.OpenTelemetry.LogsHeader); + Assert.AreEqual(AppSettings.CloneToDisplaySecurityWarning, display.OpenTelemetry.MetricsHeader); + Assert.AreEqual(AppSettings.CloneToDisplaySecurityWarning, display.OpenTelemetry.TracesHeader); + } + + [TestMethod] + public void AppSettings_CloneToDisplay_skip_Null_SecurityItems2_OpenTelemetrySettings() + { + var appSettings = new AppSettings + { + OpenTelemetry = new OpenTelemetrySettings + { + Header = null, + LogsHeader = null, + MetricsHeader = null, + TracesHeader = null, + } + }; + + var display = appSettings.CloneToDisplay(); + + Assert.IsNull(display.OpenTelemetry.Header); + Assert.IsNull(display.OpenTelemetry.LogsHeader); + Assert.IsNull(display.OpenTelemetry.MetricsHeader); + Assert.IsNull(display.OpenTelemetry.TracesHeader); + } + [TestMethod] + public void AppSettings_CloneToDisplay_skip_object_Null_SecurityItems2_OpenTelemetrySettings() + { + var appSettings = new AppSettings + { + OpenTelemetry = null + }; + + var display = appSettings.CloneToDisplay(); + + Assert.IsNull(display.OpenTelemetry); + } + [TestMethod] public void AppSettings_CloneToDisplay_hideSecurityItems_PublishProfiles() { @@ -406,7 +460,7 @@ public void AppSettings_IsReadOnly_NullNoItemTest() public void PublishProfiles_Null() { var appSettings = new AppSettings {PublishProfiles = null}; - Assert.AreEqual(0, appSettings.PublishProfiles.Count ); + Assert.AreEqual(0, appSettings.PublishProfiles?.Count); } [TestMethod] @@ -487,5 +541,26 @@ public void AccountRolesByEmailRegisterOverwrite_ValidRole2() Assert.AreEqual(2,appSettings.AccountRolesByEmailRegisterOverwrite.Count); Assert.AreEqual("Administrator", appSettings.AccountRolesByEmailRegisterOverwrite["bogusEmail2"]); } + + + [TestMethod] + public void DatabasePathToFilePath_Null() + { + var appSettings = new AppSettings(); + + var result = appSettings.DatabasePathToFilePath("\\test"); + + Assert.IsNull(result); + } + + [TestMethod] + public void DatabasePathToFilePath_NoNull() + { + var appSettings = new AppSettings(); + + var result = appSettings.DatabasePathToFilePath("\\test",false); + + Assert.IsNotNull(result); + } } } diff --git a/starsky/starskytest/starsky.foundation.platform/Models/OpenTelemetrySettingsTest.cs b/starsky/starskytest/starsky.foundation.platform/Models/OpenTelemetrySettingsTest.cs new file mode 100644 index 0000000000..ac2662d3a9 --- /dev/null +++ b/starsky/starskytest/starsky.foundation.platform/Models/OpenTelemetrySettingsTest.cs @@ -0,0 +1,89 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using starsky.foundation.platform.Models; + +namespace starskytest.starsky.foundation.platform.Models; + +[TestClass] +public class OpenTelemetrySettingsTest +{ + [TestMethod] + public void ServiceNameDefault() + { + var result = new OpenTelemetrySettings().GetServiceName(); + Assert.AreEqual("Starsky",result); + } + + [TestMethod] + public void ServiceNameProperty() + { + var result = new OpenTelemetrySettings + { + ServiceName = "test-service" + }.GetServiceName(); + + Assert.AreEqual("test-service",result); + } + + [TestMethod] + public void GetLogsHeaderDefault() + { + var result = new OpenTelemetrySettings().GetLogsHeader(); + Assert.AreEqual(null,result); + } + + [TestMethod] + public void GetLogsHeaderFallback() + { + var result = new OpenTelemetrySettings{Header = "logs"}.GetLogsHeader(); + Assert.AreEqual("logs",result); + } + + [TestMethod] + public void GetLogsShowProperty() + { + var result = new OpenTelemetrySettings{LogsHeader = "logs"}.GetLogsHeader(); + Assert.AreEqual("logs",result); + } + + [TestMethod] + public void GetMetricsHeaderDefault() + { + var result = new OpenTelemetrySettings().GetMetricsHeader(); + Assert.AreEqual(null,result); + } + + [TestMethod] + public void GetMetricsHeaderFallback() + { + var result = new OpenTelemetrySettings{Header = "metrics"}.GetMetricsHeader(); + Assert.AreEqual("metrics",result); + } + + [TestMethod] + public void GetMetricsShowProperty() + { + var result = new OpenTelemetrySettings{MetricsHeader = "metrics"}.GetMetricsHeader(); + Assert.AreEqual("metrics",result); + } + + [TestMethod] + public void GetTracesHeaderDefault() + { + var result = new OpenTelemetrySettings().GetTracesHeader(); + Assert.AreEqual(null,result); + } + + [TestMethod] + public void GetTracesHeaderFallback() + { + var result = new OpenTelemetrySettings{Header = "traces"}.GetTracesHeader(); + Assert.AreEqual("traces",result); + } + + [TestMethod] + public void GetTracesShowProperty() + { + var result = new OpenTelemetrySettings{MetricsHeader = "traces"}.GetMetricsHeader(); + Assert.AreEqual("traces",result); + } +} diff --git a/starsky/starskytest/starsky.foundation.webtelemetry/Helpers/OpenTelemetryExtensionTest.cs b/starsky/starskytest/starsky.foundation.webtelemetry/Helpers/OpenTelemetryExtensionTest.cs new file mode 100644 index 0000000000..75476c3ac3 --- /dev/null +++ b/starsky/starskytest/starsky.foundation.webtelemetry/Helpers/OpenTelemetryExtensionTest.cs @@ -0,0 +1,159 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using OpenTelemetry.Metrics; +using OpenTelemetry.Trace; +using starsky.foundation.platform.Models; +using starsky.foundation.webtelemetry.Extensions; + +namespace starskytest.starsky.foundation.webtelemetry.Helpers; + +[TestClass] +public class OpenTelemetryExtensionTest +{ + + [TestMethod] + public void ConfiguresTelemetryBuilder() + { + // Arrange + var services = new ServiceCollection(); + var appSettings = new AppSettings + { + OpenTelemetry = new OpenTelemetrySettings + { + // Set OpenTelemetry settings as needed for the test + TracesEndpoint = "https://example.com/traces", + MetricsEndpoint = "https://example.com/metrics" + } + }; + + // Act + services.AddOpenTelemetryMonitoring(appSettings); + + // Assert + var serviceProvider = services.BuildServiceProvider(); + + + // Verify tracing configuration + var tracerProvider = serviceProvider.GetRequiredService(); + Assert.IsNotNull(tracerProvider); + + // Verify metrics configuration + var meterProvider = serviceProvider.GetRequiredService(); + Assert.IsNotNull(meterProvider); + } + + [TestMethod] + public void ConfiguresTelemetryBuilder_Skip_WhenTraces() + { + // Arrange + var services = new ServiceCollection(); + var appSettings = new AppSettings + { + OpenTelemetry = new OpenTelemetrySettings + { + // Set OpenTelemetry settings as needed for the test + TracesEndpoint = null, + MetricsEndpoint = "https://example.com/metrics" + } + }; + + // Act + services.AddOpenTelemetryMonitoring(appSettings); + + // Assert + var serviceProvider = services.BuildServiceProvider(); + + + // Verify tracing configuration + var tracerProvider = serviceProvider.GetService(); + Assert.IsNull(tracerProvider); + + // Verify metrics configuration + var meterProvider = serviceProvider.GetRequiredService(); + Assert.IsNotNull(meterProvider); + } + + [TestMethod] + public void ConfiguresTelemetryBuilder_Skip_WhenMetrics() + { + // Arrange + var services = new ServiceCollection(); + var appSettings = new AppSettings + { + OpenTelemetry = new OpenTelemetrySettings + { + // Set OpenTelemetry settings as needed for the test + TracesEndpoint = "https://example.com/traces", + MetricsEndpoint = null + } + }; + + // Act + services.AddOpenTelemetryMonitoring(appSettings); + + // Assert + var serviceProvider = services.BuildServiceProvider(); + + + // Verify tracing configuration + var tracerProvider = serviceProvider.GetService(); + Assert.IsNotNull(tracerProvider); + + // Verify metrics configuration + var meterProvider = serviceProvider.GetService(); + Assert.IsNull(meterProvider); + } + + [TestMethod] + public void FilterPathTestIsTrue() + { + var context = new DefaultHttpContext { Request = { Path = "/test" } }; + Assert.IsTrue(OpenTelemetryExtension.FilterPath(context)); + } + + [TestMethod] + public void FilterPathTestSkipHealth() + { + var context = new DefaultHttpContext { Request = { Path = "/api/health" } }; + Assert.IsFalse(OpenTelemetryExtension.FilterPath(context)); + } + + [TestMethod] + public void FilterPathTestSkipRealtime() + { + var context = new DefaultHttpContext { Request = { Path = "/realtime" } }; + Assert.IsFalse(OpenTelemetryExtension.FilterPath(context)); + } + + [TestMethod] + public void FilterPathTestHitRealtimeFail() + { + var context = new DefaultHttpContext + { + Request = { Path = "/realtime" }, + Response = { StatusCode = 500} + }; + Assert.IsTrue(OpenTelemetryExtension.FilterPath(context)); + } + + [TestMethod] + public void FilterPathTestSkipTraceApi() + { + var context = new DefaultHttpContext { Request = { Path = "/api/open-telemetry/trace" } }; + Assert.IsFalse(OpenTelemetryExtension.FilterPath(context)); + } + + [TestMethod] + public void FilterPathTestSkipIndexAuthApi() + { + var context = new DefaultHttpContext + { + Request = { Path = "/api/index" }, + Response = { StatusCode = 401} + }; + + Assert.IsFalse(OpenTelemetryExtension.FilterPath(context)); + } + +} diff --git a/starsky/starskytest/starsky.foundation.webtelemetry/Helpers/SetupLoggingTest.cs b/starsky/starskytest/starsky.foundation.webtelemetry/Helpers/SetupLoggingTest.cs index 225c6f5d56..d9bc576461 100644 --- a/starsky/starskytest/starsky.foundation.webtelemetry/Helpers/SetupLoggingTest.cs +++ b/starsky/starskytest/starsky.foundation.webtelemetry/Helpers/SetupLoggingTest.cs @@ -3,6 +3,7 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.ApplicationInsights; using Microsoft.VisualStudio.TestTools.UnitTesting; +using OpenTelemetry.Logs; using starsky.foundation.platform.Models; using starsky.foundation.webtelemetry.Helpers; @@ -16,7 +17,7 @@ public void AddApplicationInsightsLoggingTest() { var testGuid = Guid.NewGuid().ToString(); IServiceCollection services = new ServiceCollection(); - services.AddApplicationInsightsLogging(new AppSettings + services.AddTelemetryLogging(new AppSettings { ApplicationInsightsLog = true, ApplicationInsightsConnectionString = $"InstrumentationKey={testGuid}" @@ -27,4 +28,22 @@ public void AddApplicationInsightsLoggingTest() var type = build.GetRequiredService(); Assert.AreEqual(typeof(ApplicationInsightsLoggerProvider),type.GetType()); } + + [TestMethod] + public void OpenTelemetry() + { + IServiceCollection services = new ServiceCollection(); + services.AddTelemetryLogging(new AppSettings + { + OpenTelemetry = new OpenTelemetrySettings + { + LogsEndpoint = "https://test.me/v1/logs" + } + }); + + var build = services.BuildServiceProvider(); + + var type = build.GetRequiredService(); + Assert.AreEqual(typeof(OpenTelemetryLoggerProvider),type.GetType()); + } } diff --git a/starsky/starskythumbnailcli/Program.cs b/starsky/starskythumbnailcli/Program.cs index 58f3d93b82..76592278bb 100644 --- a/starsky/starskythumbnailcli/Program.cs +++ b/starsky/starskythumbnailcli/Program.cs @@ -31,7 +31,7 @@ public static async Task Main(string[] args) var appSettings = serviceProvider.GetRequiredService(); services.AddMonitoringWorkerService(appSettings, AppSettings.StarskyAppType.Thumbnail); - services.AddApplicationInsightsLogging(appSettings); + services.AddTelemetryLogging(appSettings); new SetupDatabaseTypes(appSettings,services).BuilderDb(); serviceProvider = services.BuildServiceProvider(); diff --git a/starsky/starskythumbnailmetacli/Program.cs b/starsky/starskythumbnailmetacli/Program.cs index 73ef8dd50e..59497480ed 100644 --- a/starsky/starskythumbnailmetacli/Program.cs +++ b/starsky/starskythumbnailmetacli/Program.cs @@ -32,7 +32,7 @@ public static async Task Main(string[] args) var appSettings = serviceProvider.GetRequiredService(); services.AddMonitoringWorkerService(appSettings, AppSettings.StarskyAppType.MetaThumbnail); - services.AddApplicationInsightsLogging(appSettings); + services.AddTelemetryLogging(appSettings); new SetupDatabaseTypes(appSettings,services).BuilderDb(); serviceProvider = services.BuildServiceProvider(); diff --git a/starsky/telemetry.md b/starsky/telemetry.md index a43a744f84..e647b515ad 100644 --- a/starsky/telemetry.md +++ b/starsky/telemetry.md @@ -121,3 +121,7 @@ You may re-enable telemetry if you'd like to re-join the program by running the `app__EnablePackageTelemetry=true` +## OpenTelemetry + +By default OpenTelemetry is disabled to collect telemetry data. +But you can setup your own provider to collect information