From 3ec9b65fae7b3132249ca8bb72d01d6d4205019f Mon Sep 17 00:00:00 2001 From: thorsten Date: Sat, 13 Jun 2026 13:38:10 +0200 Subject: [PATCH 1/8] refactor: configure OTLP exporters per signal without a signal parameter Replace the stringly-typed signalPath argument with dedicated ConfigureTraceExporter/ConfigureMetricExporter/ConfigureLogExporter methods. Each names its signal; the per-signal path lives in one place and the gRPC/HttpProtobuf endpoint logic stays in the shared core. --- .../TelemetryServiceCollectionExtensions.cs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/OpenTelemetryExtension.Configuration/TelemetryServiceCollectionExtensions.cs b/src/OpenTelemetryExtension.Configuration/TelemetryServiceCollectionExtensions.cs index 4113728..fd85bcc 100644 --- a/src/OpenTelemetryExtension.Configuration/TelemetryServiceCollectionExtensions.cs +++ b/src/OpenTelemetryExtension.Configuration/TelemetryServiceCollectionExtensions.cs @@ -209,7 +209,7 @@ private static void ConfigureTelemetry(IServiceCollection services, TelemetryOpt options.ConfigureTracing?.Invoke(tracing); - tracing.AddOtlpExporter(exp => ConfigureOtlpExporter(exp, options, "v1/traces")); + tracing.AddOtlpExporter(exp => ConfigureTraceExporter(exp, options)); }); } @@ -241,7 +241,7 @@ private static void ConfigureTelemetry(IServiceCollection services, TelemetryOpt options.ConfigureMetrics?.Invoke(metrics); - metrics.AddOtlpExporter(exp => ConfigureOtlpExporter(exp, options, "v1/metrics")); + metrics.AddOtlpExporter(exp => ConfigureMetricExporter(exp, options)); }); } @@ -256,15 +256,25 @@ private static void ConfigureTelemetry(IServiceCollection services, TelemetryOpt otel.IncludeScopes = options.IncludeScopes; otel.IncludeFormattedMessage = options.IncludeFormattedMessage; - otel.AddOtlpExporter(exp => ConfigureOtlpExporter(exp, options, "v1/logs")); + otel.AddOtlpExporter(exp => ConfigureLogExporter(exp, options)); }); }); } } + private static void ConfigureTraceExporter(OtlpExporterOptions exporter, TelemetryOptions options) + => ConfigureOtlpExporter(exporter, options, "v1/traces"); + + private static void ConfigureMetricExporter(OtlpExporterOptions exporter, TelemetryOptions options) + => ConfigureOtlpExporter(exporter, options, "v1/metrics"); + + private static void ConfigureLogExporter(OtlpExporterOptions exporter, TelemetryOptions options) + => ConfigureOtlpExporter(exporter, options, "v1/logs"); + private static void ConfigureOtlpExporter(OtlpExporterOptions exporter, TelemetryOptions options, string signalPath) { // ! is safe: Endpoint is [Required]-validated before ConfigureTelemetry runs + // gRPC posts every signal to the base endpoint; HttpProtobuf needs the per-signal path appended. #pragma warning disable CS0618 // OtlpExportProtocol.Grpc is intentionally supported; warning only applies to netstandard2.0 without HttpClientFactory exporter.Endpoint = options.Protocol == OtlpExportProtocol.Grpc ? options.Endpoint! From 43f1b0bebfdffc19a55703be26f9d5d8d8428371 Mon Sep 17 00:00:00 2001 From: thorsten Date: Sat, 13 Jun 2026 13:38:15 +0200 Subject: [PATCH 2/8] test: simplify integration test harness Drop the env-var config overrides, network Reachability probe and the IntegrationFact/SqlIntegrationFact skip attributes; tests now run against fixed local endpoints. --- .../SqlServerInstrumentationTests.cs | 4 +-- .../TelemetryIntegrationTests.cs | 6 ++-- .../Utils/IntegrationConfig.cs | 27 ++++-------------- .../Utils/IntegrationFactAttribute.cs | 14 ---------- .../Utils/OpenObserveClient.cs | 8 +----- .../Utils/OtelTestHost.cs | 22 +++++---------- .../Utils/Reachability.cs | 28 ------------------- .../Utils/SqlIntegrationFactAttribute.cs | 17 ----------- 8 files changed, 17 insertions(+), 109 deletions(-) delete mode 100644 src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/IntegrationFactAttribute.cs delete mode 100644 src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/Reachability.cs delete mode 100644 src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/SqlIntegrationFactAttribute.cs diff --git a/src/OpenTelemetryExtension.Configuration.IntegrationTests/SqlServerInstrumentationTests.cs b/src/OpenTelemetryExtension.Configuration.IntegrationTests/SqlServerInstrumentationTests.cs index 4027beb..b63a009 100644 --- a/src/OpenTelemetryExtension.Configuration.IntegrationTests/SqlServerInstrumentationTests.cs +++ b/src/OpenTelemetryExtension.Configuration.IntegrationTests/SqlServerInstrumentationTests.cs @@ -9,7 +9,7 @@ public sealed class SqlServerInstrumentationTests { private static readonly TimeSpan QueryTimeout = TimeSpan.FromSeconds(40); - [SqlIntegrationFact] + [Fact] public async Task SqlServer_CommandSpans_AreExported_AndQueryableInOpenObserve() { var runId = Guid.NewGuid().ToString("N"); @@ -41,8 +41,6 @@ public async Task SqlServer_CommandSpans_AreExported_AndQueryableInOpenObserve() QueryTimeout); Assert.True(spans > 0, $"Expected a SQL Server span for service '{serviceName}' in OpenObserve."); - // Instrumentation emits the current database semantic conventions: - // db.system.name = "microsoft.sql_server" (flattened to db_system_name in OpenObserve). var sqlServerSpans = await client.PollUntilAsync( "traces", $"SELECT COUNT(*) AS c FROM \"default\" WHERE service_name = '{serviceName}' AND db_system_name = 'microsoft.sql_server'", diff --git a/src/OpenTelemetryExtension.Configuration.IntegrationTests/TelemetryIntegrationTests.cs b/src/OpenTelemetryExtension.Configuration.IntegrationTests/TelemetryIntegrationTests.cs index 710dd35..f1561a7 100644 --- a/src/OpenTelemetryExtension.Configuration.IntegrationTests/TelemetryIntegrationTests.cs +++ b/src/OpenTelemetryExtension.Configuration.IntegrationTests/TelemetryIntegrationTests.cs @@ -10,7 +10,7 @@ public sealed class TelemetryIntegrationTests { private static readonly TimeSpan QueryTimeout = TimeSpan.FromSeconds(40); - [IntegrationFact] + [Fact] public async Task Traces_AreExported_AndQueryableInOpenObserve() { var runId = Guid.NewGuid().ToString("N"); @@ -43,7 +43,7 @@ public async Task Traces_AreExported_AndQueryableInOpenObserve() Assert.True(count > 0, $"Expected at least one trace for service '{serviceName}' in OpenObserve."); } - [IntegrationFact] + [Fact] public async Task Metrics_AreExported_AndQueryableInOpenObserve() { var runId = Guid.NewGuid().ToString("N"); @@ -75,7 +75,7 @@ public async Task Metrics_AreExported_AndQueryableInOpenObserve() Assert.True(count > 0, $"Expected the metrics stream '{counterName}' to contain data points in OpenObserve."); } - [IntegrationFact] + [Fact] public async Task Logs_AreExported_AndQueryableInOpenObserve() { var runId = Guid.NewGuid().ToString("N"); diff --git a/src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/IntegrationConfig.cs b/src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/IntegrationConfig.cs index 87f43a4..e0c68ab 100644 --- a/src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/IntegrationConfig.cs +++ b/src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/IntegrationConfig.cs @@ -2,27 +2,10 @@ namespace OpenTelemetryExtension.Configuration.IntegrationTests.Utils; internal static class IntegrationConfig { - public static string OpenObserveBaseUrl => - Environment.GetEnvironmentVariable("OTEL_IT_OPENOBSERVE_URL") ?? "http://localhost:30117/api/default"; - - public static string OpenObserveUser => - Environment.GetEnvironmentVariable("OTEL_IT_OPENOBSERVE_USER") ?? "admin@web.de"; - - public static string OpenObservePassword => - Environment.GetEnvironmentVariable("OTEL_IT_OPENOBSERVE_PASSWORD") ?? "admin"; - - // OTLP exporter auth + log stream routing. Base64 decodes to "admin@web.de:admin". - public static string OtlpHeaders => - Environment.GetEnvironmentVariable("OTEL_IT_OTLP_HEADERS") - ?? "Authorization=Basic YWRtaW5Ad2ViLmRlOmFkbWlu,stream-name=default"; - + public static string OpenObserveBaseUrl => "http://localhost:30117/api/default"; + public static string OpenObserveUser => "admin@web.de"; + public static string OpenObservePassword => "admin"; + public static string OtlpHeaders => "Authorization=Basic YWRtaW5Ad2ViLmRlOmFkbWlu,stream-name=default"; public static Uri OtlpEndpoint => new(OpenObserveBaseUrl); - - public static string SqlConnectionString => - Environment.GetEnvironmentVariable("OTEL_IT_SQL_CONNECTION") - ?? "Server=localhost,31433;Database=master;User Id=sa;Password=YourStrongPassword123!;TrustServerCertificate=True;Encrypt=False"; - - public static (string Host, int Port) OpenObserveEndpoint => ("localhost", 30117); - - public static (string Host, int Port) SqlServerEndpoint => ("localhost", 31433); + public static string SqlConnectionString => "Server=localhost,31433;Database=master;User Id=sa;Password=YourStrongPassword123!;TrustServerCertificate=True;Encrypt=False"; } diff --git a/src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/IntegrationFactAttribute.cs b/src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/IntegrationFactAttribute.cs deleted file mode 100644 index b1e2bfb..0000000 --- a/src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/IntegrationFactAttribute.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace OpenTelemetryExtension.Configuration.IntegrationTests.Utils; - -// A Fact that skips itself when the OpenObserve backend is not reachable, so the -// suite stays green on machines without the telemetry stack running. -public sealed class IntegrationFactAttribute : FactAttribute -{ - public IntegrationFactAttribute() - { - if (!Reachability.OpenObserveAvailable) - { - Skip = "OpenObserve is not reachable on localhost:30117 — start it via infrastructure/helm/helm-install-openobserve.cmd."; - } - } -} diff --git a/src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/OpenObserveClient.cs b/src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/OpenObserveClient.cs index 9dbd7fe..6be305f 100644 --- a/src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/OpenObserveClient.cs +++ b/src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/OpenObserveClient.cs @@ -1,13 +1,9 @@ -using System.Net.Http; using System.Net.Http.Headers; using System.Text; using System.Text.Json; namespace OpenTelemetryExtension.Configuration.IntegrationTests.Utils; -// Thin wrapper around the OpenObserve _search API used to assert that emitted -// telemetry actually arrived. The API needs the root user credentials, not the -// OTLP ingestion passcode. internal sealed class OpenObserveClient : IDisposable { private const long OneHourMicros = 3_600_000_000L; @@ -16,8 +12,7 @@ internal sealed class OpenObserveClient : IDisposable public OpenObserveClient() { - var credentials = Convert.ToBase64String( - Encoding.UTF8.GetBytes($"{IntegrationConfig.OpenObserveUser}:{IntegrationConfig.OpenObservePassword}")); + var credentials = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{IntegrationConfig.OpenObserveUser}:{IntegrationConfig.OpenObservePassword}")); _http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials); } @@ -30,7 +25,6 @@ public async Task CountAsync(string streamType, string sql, CancellationTo using var response = await _http.PostAsync( $"{IntegrationConfig.OpenObserveBaseUrl}/_search?type={streamType}", content, ct); - // A missing stream (no data yet) answers non-2xx; treat it as "nothing there yet". if (!response.IsSuccessStatusCode) { return 0; diff --git a/src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/OtelTestHost.cs b/src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/OtelTestHost.cs index d015317..28c5612 100644 --- a/src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/OtelTestHost.cs +++ b/src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/OtelTestHost.cs @@ -7,9 +7,6 @@ namespace OpenTelemetryExtension.Configuration.IntegrationTests.Utils; -// Builds a service provider wired up through the library's AddTelemetry() against -// the OpenObserve OTLP endpoint, and exposes a force-flush so a test can assert -// straight afterwards instead of waiting for the batch interval. internal sealed class OtelTestHost : IDisposable { private readonly ServiceProvider _provider; @@ -17,22 +14,15 @@ internal sealed class OtelTestHost : IDisposable public OtelTestHost(Action configure) { var services = new ServiceCollection(); - services.AddTelemetry(o => + services.AddTelemetry(opt => { - o.Protocol = OtlpExportProtocol.HttpProtobuf; - o.Endpoint = IntegrationConfig.OtlpEndpoint; - o.Headers = IntegrationConfig.OtlpHeaders; - o.EnableAspNetCoreInstrumentation = false; - o.EnableHttpClientInstrumentation = false; - o.EnableRuntimeInstrumentation = false; - configure(o); + opt.Protocol = OtlpExportProtocol.HttpProtobuf; + opt.Endpoint = IntegrationConfig.OtlpEndpoint; + opt.Headers = IntegrationConfig.OtlpHeaders; + configure(opt); }); _provider = services.BuildServiceProvider(); - - // Resolve the providers so the SDK starts listening before telemetry is emitted. - _ = _provider.GetService(); - _ = _provider.GetService(); } public ILogger CreateLogger() => _provider.GetRequiredService>(); @@ -42,6 +32,8 @@ public void Flush() _provider.GetService()?.ForceFlush(15_000); _provider.GetService()?.ForceFlush(15_000); _provider.GetService()?.ForceFlush(15_000); + + Thread.Sleep(500); } public void Dispose() diff --git a/src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/Reachability.cs b/src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/Reachability.cs deleted file mode 100644 index a5c3768..0000000 --- a/src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/Reachability.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Net.Sockets; - -namespace OpenTelemetryExtension.Configuration.IntegrationTests.Utils; - -internal static class Reachability -{ - public static bool IsTcpOpen(string host, int port, int timeoutMs = 1500) - { - try - { - using var client = new TcpClient(); - return client.ConnectAsync(host, port).Wait(timeoutMs) && client.Connected; - } - catch - { - return false; - } - } - - private static bool? _openObserve; - private static bool? _sqlServer; - - public static bool OpenObserveAvailable => - _openObserve ??= IsTcpOpen(IntegrationConfig.OpenObserveEndpoint.Host, IntegrationConfig.OpenObserveEndpoint.Port); - - public static bool SqlServerAvailable => - _sqlServer ??= IsTcpOpen(IntegrationConfig.SqlServerEndpoint.Host, IntegrationConfig.SqlServerEndpoint.Port); -} diff --git a/src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/SqlIntegrationFactAttribute.cs b/src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/SqlIntegrationFactAttribute.cs deleted file mode 100644 index dd02918..0000000 --- a/src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/SqlIntegrationFactAttribute.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace OpenTelemetryExtension.Configuration.IntegrationTests.Utils; - -// Like IntegrationFact, but additionally requires a reachable SQL Server. -public sealed class SqlIntegrationFactAttribute : FactAttribute -{ - public SqlIntegrationFactAttribute() - { - if (!Reachability.OpenObserveAvailable) - { - Skip = "OpenObserve is not reachable on localhost:30117 — start it via infrastructure/helm/helm-install-openobserve.cmd."; - } - else if (!Reachability.SqlServerAvailable) - { - Skip = "SQL Server is not reachable on localhost:31433 — start it via infrastructure/helm/helm-install-sqlserver.cmd."; - } - } -} From 7eff6486a7e5f156655cd0e9f14a773168dd3f68 Mon Sep 17 00:00:00 2001 From: thorsten Date: Sat, 13 Jun 2026 13:38:24 +0200 Subject: [PATCH 3/8] chore: add SigNoz local stack and tidy dev infrastructure Add SigNoz helm values and a valid NodePort service (otel-collector selector, in-range nodePorts 30317/30318), align the other helm install scripts, and update editorconfig, solution layout and sample projects. --- .editorconfig | 10 +- OpenTelemetryExtension.slnx | 20 +- .../templates/deployment.yaml | 2 +- .../helm/chart-openobserve/templates/pvc.yaml | 5 +- .../helm/helm-install-aspire-dashboard.cmd | 6 +- .../helm/helm-install-openobserve.cmd | 4 +- infrastructure/helm/helm-install-signoz.cmd | 11 +- .../helm/helm-install-sqlserver.cmd | 4 +- infrastructure/helm/signoz.nodeports.yaml | 19 + infrastructure/helm/signoz.values.yaml | 1994 +++++++++++++++++ ...tension.Configuration.Sample.WebApi.csproj | 3 +- .../appsettings.signoz.json | 2 +- ...yExtension.Configuration.Sample.Wpf.csproj | 1 + 13 files changed, 2059 insertions(+), 22 deletions(-) create mode 100644 infrastructure/helm/signoz.nodeports.yaml create mode 100644 infrastructure/helm/signoz.values.yaml diff --git a/.editorconfig b/.editorconfig index 993c6b1..683ab1d 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,7 +1,15 @@ root = true -# Generated EF Core migrations — skip style rules +[*.csproj] +indent_style = space +indent_size = 2 +tab_width = 2 +insert_final_newline = true + +# optional XML-spezifisch +charset = utf-8 + [src/**/Migrations/*.cs] generated_code = true dotnet_analyzer_diagnostic.severity = none diff --git a/OpenTelemetryExtension.slnx b/OpenTelemetryExtension.slnx index 63b5592..fdccd2b 100644 --- a/OpenTelemetryExtension.slnx +++ b/OpenTelemetryExtension.slnx @@ -1,12 +1,4 @@ - - - - - - - - @@ -55,6 +47,7 @@ + @@ -86,5 +79,16 @@ + + + + + + + + + + + diff --git a/infrastructure/helm/chart-openobserve/templates/deployment.yaml b/infrastructure/helm/chart-openobserve/templates/deployment.yaml index 91f9190..ec434bd 100644 --- a/infrastructure/helm/chart-openobserve/templates/deployment.yaml +++ b/infrastructure/helm/chart-openobserve/templates/deployment.yaml @@ -81,7 +81,7 @@ spec: {{- if .Values.persistence.enabled }} - name: data persistentVolumeClaim: - claimName: openobserve-data + claimName: {{ include "openobserve.fullname" . }}-data {{- end }} {{- with .Values.volumes }} {{- toYaml . | nindent 8 }} diff --git a/infrastructure/helm/chart-openobserve/templates/pvc.yaml b/infrastructure/helm/chart-openobserve/templates/pvc.yaml index b0ecf27..32aa78e 100644 --- a/infrastructure/helm/chart-openobserve/templates/pvc.yaml +++ b/infrastructure/helm/chart-openobserve/templates/pvc.yaml @@ -2,7 +2,10 @@ apiVersion: v1 kind: PersistentVolumeClaim metadata: - name: openobserve-data + name: {{ include "openobserve.fullname" . }}-data + annotations: + "helm.sh/hook": pre-install,pre-upgrade + "helm.sh/hook-weight": "-5" spec: accessModes: - ReadWriteOnce diff --git a/infrastructure/helm/helm-install-aspire-dashboard.cmd b/infrastructure/helm/helm-install-aspire-dashboard.cmd index c5d3ae8..16de23b 100644 --- a/infrastructure/helm/helm-install-aspire-dashboard.cmd +++ b/infrastructure/helm/helm-install-aspire-dashboard.cmd @@ -2,12 +2,12 @@ helm repo add aspire-dashboard https://kube-the-home.github.io/aspire-dashboard-helm/ helm repo update -helm uninstall aspire-dashboard -helm install aspire-dashboard aspire-dashboard/aspire-dashboard --version 1.28.3 -f aspire-dashboard.values.yaml +helm uninstall aspire-dashboard --wait --timeout 120s +helm install aspire-dashboard aspire-dashboard/aspire-dashboard --version 1.28.3 -f aspire-dashboard.values.yaml --wait --timeout 120s kubectl delete -f aspire-dashboard.nodeports.yaml kubectl apply -f aspire-dashboard.nodeports.yaml -REM helm show values aspire-dashboard/aspire-dashboard > values.aspire-dashboard.yaml +REM helm show values aspire-dashboard/aspire-dashboard > aspire-dashboard.values.yaml pause \ No newline at end of file diff --git a/infrastructure/helm/helm-install-openobserve.cmd b/infrastructure/helm/helm-install-openobserve.cmd index eb8bb64..0748f0e 100644 --- a/infrastructure/helm/helm-install-openobserve.cmd +++ b/infrastructure/helm/helm-install-openobserve.cmd @@ -1,5 +1,5 @@ -helm uninstall openobserve -helm install openobserve ./chart-openobserve +helm uninstall openobserve --wait --timeout 120s +helm install openobserve ./chart-openobserve --wait --timeout 120s pause \ No newline at end of file diff --git a/infrastructure/helm/helm-install-signoz.cmd b/infrastructure/helm/helm-install-signoz.cmd index 0362a2e..75b6da0 100644 --- a/infrastructure/helm/helm-install-signoz.cmd +++ b/infrastructure/helm/helm-install-signoz.cmd @@ -2,7 +2,14 @@ helm repo add signoz https://charts.signoz.io helm repo update -helm uninstall signoz -helm install signoz signoz/signoz +helm uninstall signoz --wait --timeout 300s +kubectl delete chi signoz-clickhouse --ignore-not-found --wait + +helm install signoz signoz/signoz --version 0.128.0 -f signoz.values.yaml --wait --timeout 600s + +kubectl delete -f signoz.nodeports.yaml --ignore-not-found +kubectl apply -f signoz.nodeports.yaml + +REM helm show values signoz/signoz --version 0.128.0 > signoz.values.yaml pause \ No newline at end of file diff --git a/infrastructure/helm/helm-install-sqlserver.cmd b/infrastructure/helm/helm-install-sqlserver.cmd index 1830992..75eb918 100644 --- a/infrastructure/helm/helm-install-sqlserver.cmd +++ b/infrastructure/helm/helm-install-sqlserver.cmd @@ -1,5 +1,5 @@ -helm uninstall sqlserver -helm install sqlserver ./chart-sqlserver +helm uninstall sqlserver --wait --timeout 120s +helm install sqlserver ./chart-sqlserver --wait --timeout 120s pause \ No newline at end of file diff --git a/infrastructure/helm/signoz.nodeports.yaml b/infrastructure/helm/signoz.nodeports.yaml new file mode 100644 index 0000000..c983223 --- /dev/null +++ b/infrastructure/helm/signoz.nodeports.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Service +metadata: + name: signoz-nodeport + namespace: default +spec: + type: NodePort + selector: + app.kubernetes.io/instance: signoz + app.kubernetes.io/component: otel-collector + ports: + - name: otlp-grpc + port: 4317 + targetPort: 4317 + nodePort: 30317 + - name: otlp-http + port: 4318 + targetPort: 4318 + nodePort: 30318 diff --git a/infrastructure/helm/signoz.values.yaml b/infrastructure/helm/signoz.values.yaml new file mode 100644 index 0000000..1952ad2 --- /dev/null +++ b/infrastructure/helm/signoz.values.yaml @@ -0,0 +1,1994 @@ +# global -- Global override values for the chart. +# @section -- Global Settings +global: + # global.imageRegistry -- Overrides the Image registry globally for all components. + # @default -- null + # @section -- Global Settings + imageRegistry: &GLOBAL_IMAGE_REGISTRY null + # global.imagePullSecrets -- Global Image Pull Secrets. + # @default -- [] + # @section -- Global Settings + imagePullSecrets: [] + # global.storageClass -- Overrides the storage class for all PVCs with persistence enabled. + # If not set, the default storage class is used. + # If set to "-", storageClassName will be an empty string, which disables dynamic provisioning. + # @default -- null + # @section -- Global Settings + storageClass: null + # global.clusterDomain -- The Kubernetes cluster domain. + # It is used only when components are installed in different namespaces. + # @default -- "cluster.local" + # @section -- Global Settings + clusterDomain: cluster.local + # global.clusterName -- The Kubernetes cluster name. + # It is used to attach to telemetry data via the resource detection processor. + # @default -- "" + # @section -- Global Settings + clusterName: "" + # global.cloud -- The Kubernetes cluster cloud provider and distribution (if any). + # example: `aws`, `azure`, `gcp`, `gcp/autogke`, `hcloud`, `other` + # The storage class for persistent volumes is selected based on this value. + # When set to 'aws' or 'gcp' with `installCustomStorageClass` enabled, a new expandable storage class is created. + # @default -- "other" + # @section -- Global Settings + cloud: other +# -- Override the default chart name. +# @section -- General Settings +# @default -- "" +nameOverride: "" +# -- Override the default full chart name. +# @section -- General Settings +# @default -- "" +fullnameOverride: "" +# -- Name of the K8s cluster. Used by SigNoz OtelCollectors to attach to telemetry data. +# @section -- General Settings +# @default -- "" +clusterName: "" +# -- Image Registry Secret Names for all SigNoz components. +# If `global.imagePullSecrets` is set, it will be merged with this list. +# This has lower precedence than `imagePullSecrets` at the individual component level. +# @section -- General Settings +# @default -- [] +imagePullSecrets: [] +# - "signoz-pull-secret" + +# clickhouse -- Clickhouse default values. For a complete list of configurations, check `values.yaml` of the upstream `clickhouse` chart. +# @default -- "Check out the clickhouse chart for default values" +# @ignored +clickhouse: + # clickhouse.enabled -- Whether to install ClickHouse. If false, `clickhouse.host` must be set. + # @section -- ClickHouse Settings + # @default -- true + enabled: true + # clickhouse.zookeeper -- Zookeeper default values. + # Ref: https://github.com/bitnami/charts/blob/main/bitnami/zookeeper/values.yaml + # @ignored + zookeeper: + # Please DO NOT override this value. This chart installs Zookeeper separately. + # Only if you know what you are doing, proceed with overriding. + # To see default values, refer to the zookeeper section in the values.yaml of the upstream clickhouse chart. + + # clickhouse.zookeeper.enabled -- Whether to install Zookeeper. If false, `clickhouse.externalZookeeper` must be set. + # @section -- Zookeeper Settings + # @default -- true + enabled: true + # clickhouse.zookeeper.podAnnotations -- Annotations for the Zookeeper pod. + # @section -- Zookeeper Settings + # @default -- { signoz.io/scrape: "true", signoz.io/port: "9141", signoz.io/path: "/metrics" } + podAnnotations: + signoz.io/scrape: "true" + signoz.io/port: "9141" + signoz.io/path: "/metrics" + # clickhouse.zookeeper.metrics -- Zookeeper metrics settings. + # @section -- Zookeeper Settings + # @default -- { enabled: true } + metrics: + enabled: true + # clickhouse.zookeeper.logLevel -- Zookeeper log level. + # @section -- Zookeeper Settings + # @default -- "INFO" + logLevel: INFO + # clickhouse.zookeeper.livenessProbe -- Zookeeper liveness probe settings. + # @section -- Zookeeper Settings + # @default -- { enabled: false } + livenessProbe: + enabled: false + # clickhouse.zookeeper.readinessProbe -- Zookeeper readiness probe settings. + # @section -- Zookeeper Settings + # @default -- { enabled: false } + readinessProbe: + enabled: false + # clickhouse.zookeeper.customLivenessProbe -- Custom liveness probe for Zookeeper. + # @section -- Zookeeper Settings + # @default -- "Please checkout the default values in values.yml" + customLivenessProbe: + exec: + command: ['/bin/bash', '-c', 'curl -s -m 2 http://localhost:8080/commands/ruok | grep ruok'] + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 6 + # clickhouse.zookeeper.customReadinessProbe -- Custom readiness probe for Zookeeper. + # @section -- Zookeeper Settings + # @default -- "Please checkout the default values in values.yml" + customReadinessProbe: + exec: + command: ['/bin/bash', '-c', 'curl -s -m 2 http://localhost:8080/commands/ruok | grep error | grep null'] + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 6 + # clickhouse.zookeeper.image -- Zookeeper image configuration. + # @section -- Zookeeper Settings + image: + # clickhouse.zookeeper.image.registry -- Zookeeper image registry to use. + # @default -- (value of global.imageRegistry) + registry: *GLOBAL_IMAGE_REGISTRY + # clickhouse.zookeeper.image.repository -- Zookeeper image repository to use. + # @default -- "bitnami/zookeeper" + repository: signoz/zookeeper + # clickhouse.zookeeper.image.tag -- Zookeeper image tag. SigNoz ClickHouse does not support all versions of Zookeeper. + # Please override the default only if you know what you are doing. + # @default -- "3.7.1" + tag: 3.7.1 + # clickhouse.zookeeper.replicaCount -- Replica count for Zookeeper. + # @section -- Zookeeper Settings + # @default -- 1 + replicaCount: 1 + # clickhouse.zookeeper.namespaceOverride -- Whether to install Zookeeper into a different namespace than the parent. + # @section -- Zookeeper Settings + # @default -- "" + namespaceOverride: "" + # clickhouse.zookeeper.resources -- Resources requests and limits for Zookeeper. + # @section -- Zookeeper Settings + # @default -- { limits: {}, requests: { memory: "256Mi", cpu: "100m" } } + resources: + limits: {} + requests: + memory: 256Mi + cpu: 100m + # clickhouse.namespace -- The namespace to install ClickHouse and `clickhouse-operator` into (defaults to the chart's installation namespace). + # @section -- ClickHouse Settings + # @default -- "" + namespace: "" + # clickhouse.nameOverride -- Name override for ClickHouse. + # @section -- ClickHouse Settings + # @default -- "" + nameOverride: "" + # clickhouse.fullnameOverride -- Fullname override for ClickHouse. + # @section -- ClickHouse Settings + # @default -- "" + fullnameOverride: "" + # clickhouse.cluster -- ClickHouse cluster name. + # @section -- ClickHouse Settings + # @default -- "cluster" + cluster: cluster + # clickhouse.database -- ClickHouse Settings for SigNoz Metrics. + # @section -- ClickHouse Settings + # @default -- "signoz_metrics" + database: signoz_metrics + # clickhouse.traceDatabase -- ClickHouse Settings for SigNoz Traces. + # @section -- ClickHouse Settings + # @default -- "signoz_traces" + traceDatabase: signoz_traces + # clickhouse.logDatabase -- ClickHouse Settings for SigNoz Logs. + # @section -- ClickHouse Settings + # @default -- "signoz_logs" + logDatabase: signoz_logs + # clickhouse.meterDatabase -- Clickhouse meter Database (SigNoz Meter) + # @section -- ClickHouse Settings + # @default -- "signoz_meter" + meterDatabase: signoz_meter + # clickhouse.user -- ClickHouse user. + # @section -- ClickHouse Settings + # @default -- "admin" + user: admin + # clickhouse.password -- ClickHouse password. + # @section -- ClickHouse Settings + # @default -- "27ff0399-0d3a-4bd8-919d-17c2181e6fb9" + password: 27ff0399-0d3a-4bd8-919d-17c2181e6fb9 + # clickhouse.image -- ClickHouse image configuration. + # @section -- ClickHouse Image + image: + # clickhouse.image.registry -- ClickHouse image registry to use. + # @default -- "docker.io" + registry: docker.io + # clickhouse.image.repository -- ClickHouse image repository to use. + # @default -- "clickhouse/clickhouse-server" + repository: clickhouse/clickhouse-server + # clickhouse.image.tag -- ClickHouse image tag to use. SigNoz is not always tested with the latest version of ClickHouse. + # Only override if you know what you are doing. + # @default -- "25.5.6" + tag: 25.5.6 + # clickhouse.image.pullPolicy -- ClickHouse image pull policy. + # @default -- "IfNotPresent" + pullPolicy: IfNotPresent + # clickhouse.imagePullSecrets -- Image Registry Secret Names for ClickHouse. Merged with `global.imagePullSecrets` if set. + # @section -- ClickHouse Image + # @default -- [] + imagePullSecrets: [] + # - "clickhouse-pull-secret" + + # clickhouse.annotations -- Annotations for the ClickHouse instance. + # @section -- ClickHouse Settings + # @default -- {} + annotations: {} + # clickhouse.serviceAccount -- ClickHouse Service Account configuration. + # @section -- ClickHouse Settings + serviceAccount: + # clickhouse.serviceAccount.create -- Specifies whether a service account should be created. + # @default -- true + create: true + # clickhouse.serviceAccount.annotations -- Annotations to add to the service account. + # @default -- {} + annotations: {} + # clickhouse.serviceAccount.name -- The name of the service account to use. If not set and create is true, a name is generated. + # @default -- null + name: + # clickhouse.service -- ClickHouse service configuration. + # @section -- ClickHouse Settings + service: + # clickhouse.service.annotations -- Annotations for the ClickHouse service. + # @default -- {} + annotations: {} + # clickhouse.service.type -- Service type. `LoadBalancer` allows external access; `NodePort` is more secure and has no extra cost. + # @default -- "ClusterIP" + type: ClusterIP + # clickhouse.service.httpPort -- ClickHouse HTTP port. + # @default -- 8123 + httpPort: 8123 + # clickhouse.service.tcpPort -- ClickHouse TCP port. + # @default -- 9000 + tcpPort: 9000 + # clickhouse.secure -- Whether to use a TLS connection when connecting to ClickHouse. + # @section -- ClickHouse Settings + # @default -- false + secure: false + # clickhouse.verify -- Whether to verify the TLS certificate on connection to ClickHouse. + # @section -- ClickHouse Settings + # @default -- false + verify: false + # clickhouse.externalZookeeper -- Configuration for an external Zookeeper. + # @section -- Zookeeper Settings + # @default -- {} + externalZookeeper: {} + # servers: + # - host: signoz-signoz-zookeeper + # port: 2181 + + # clickhouse.nodeSelector -- Node selector for assigning the ClickHouse pod. + # @section -- ClickHouse Settings + # @default -- {} + nodeSelector: {} + # clickhouse.tolerations -- Toleration labels for ClickHouse pod assignment. + # @section -- ClickHouse Settings + # @default -- [] + tolerations: [] + # clickhouse.affinity -- Affinity settings for the ClickHouse pod. + # @section -- ClickHouse Settings + # @default -- {} + affinity: {} + # clickhouse.resources -- Configure resource requests and limits. Update according to your use case. + # Ref: http://kubernetes.io/docs/user-guide/compute-resources/ + # @section -- ClickHouse Resources + # @default -- { requests: { cpu: "100m", memory: "200Mi" } } + resources: + requests: + cpu: 100m + memory: 200Mi + # limits: + # cpu: 2000m + # memory: 4Gi + + # clickhouse.securityContext -- Security context for the ClickHouse node. + # @section -- ClickHouse Settings + # @default -- "Please checkout the default values in values.yml" + securityContext: + enabled: true + runAsUser: 101 + runAsGroup: 101 + fsGroup: 101 + fsGroupChangePolicy: OnRootMismatch + # clickhouse.allowedNetworkIps -- An allowlist of IP addresses or network masks the ClickHouse user can access from. + # By default, private network ranges are allowed. + # Refs: + # - https://clickhouse.com/docs/en/operations/settings/settings-users/#user-namenetworks + # - https://en.wikipedia.org/wiki/Reserved_IP_addresses#IPv4 + # @section -- ClickHouse Settings + # @default -- "Please checkout the default values in values.yml" + allowedNetworkIps: + - "10.0.0.0/8" + - "100.64.0.0/10" + - "172.16.0.0/12" + - "192.0.0.0/24" + - "198.18.0.0/15" + - "192.168.0.0/16" + # clickhouse.persistence -- ClickHouse persistence configuration. + # @section -- ClickHouse Persistence + persistence: + # clickhouse.persistence.enabled -- Enable data persistence using a PVC for ClickHouse data. + # @default -- true + enabled: true + # clickhouse.persistence.existingClaim -- Use a manually managed Persistent Volume Claim. If defined, the PVC must be created manually. + # @default -- "" + existingClaim: "" + # clickhouse.persistence.storageClass -- Persistent Volume Storage Class. If "-", disables dynamic provisioning. If null, uses the default provisioner. + # @default -- null + storageClass: null + # clickhouse.persistence.accessModes -- Access Modes for the persistent volume. + # @default -- ["ReadWriteOnce"] + accessModes: + - ReadWriteOnce + # clickhouse.persistence.size -- Persistent Volume size. + # @default -- "20Gi" + size: 4Gi + # clickhouse.profiles -- ClickHouse user profile configuration. + # Use this to override profile settings, e.g., `default/max_memory_usage: 40000000000`. + # For the full list of settings, see: + # - https://clickhouse.com/docs/en/operations/settings/settings-profiles/ + # - https://clickhouse.com/docs/en/operations/settings/settings/ + # @section -- ClickHouse Settings + # @default -- {} + profiles: {} + # clickhouse.defaultProfiles -- Default user profile configuration for ClickHouse. !!! Please DO NOT override this !!! + # @section -- ClickHouse Settings + # @default -- "Please checkout the default values in values.yml" + defaultProfiles: + default/allow_experimental_window_functions: "1" + default/allow_nondeterministic_mutations: "1" + default/secondary_indices_enable_bulk_filtering: "0" + admin/secondary_indices_enable_bulk_filtering: "0" + default/query_plan_max_limit_for_lazy_materialization: "0" + admin/query_plan_max_limit_for_lazy_materialization: "0" + # clickhouse.initContainers -- Init container to copy the histogramQuantile UDF. + # @section -- ClickHouse Settings + # @default -- "Please checkout the default values in values.yml" + initContainers: + enabled: true + udf: + enabled: true + image: + registry: docker.io + repository: alpine + tag: 3.18.2 + pullPolicy: IfNotPresent + command: + - sh + - -c + - | + set -e + version="v0.0.1" + node_os=$(uname -s | tr '[:upper:]' '[:lower:]') + node_arch=$(uname -m | sed s/aarch64/arm64/ | sed s/x86_64/amd64/) + echo "Fetching histogram-binary for ${node_os}/${node_arch}" + cd /tmp + wget -O histogram-quantile.tar.gz "https://github.com/SigNoz/signoz/releases/download/histogram-quantile%2F${version}/histogram-quantile_${node_os}_${node_arch}.tar.gz" + tar -xzf histogram-quantile.tar.gz + chmod +x histogram-quantile + mv histogram-quantile /var/lib/clickhouse/user_scripts/histogramQuantile + echo "histogram-quantile installed successfully" + init: + enabled: false + image: + registry: docker.io + repository: busybox + tag: 1.35 + pullPolicy: IfNotPresent + command: + - /bin/sh + - -c + - | + set -e + until curl -s -o /dev/null http://signoz-clickhouse:8123/ + do sleep 1 + done + # clickhouse.layout -- ClickHouse cluster layout. (Experimental, use at own risk) + # For a full list of options, see https://github.com/Altinity/clickhouse-operator/blob/master/docs/custom_resource_explained.md + # @section -- ClickHouse Settings + # @default -- { shardsCount: 1, replicasCount: 1 } + layout: + shardsCount: 1 + replicasCount: 1 + # clickhouse.settings -- ClickHouse settings configuration. + # You can use this to override settings, e.g., `prometheus/port: 9363`. + # For the full list of settings, see https://clickhouse.com/docs/en/operations/settings/settings/ + # @section -- ClickHouse Settings + # @default -- "Please checkout the default values in values.yml" + settings: + # Uncomment those lines to enable the built-in Prometheus HTTP endpoint in ClickHouse. + prometheus/endpoint: /metrics + prometheus/port: 9363 + # prometheus/metrics: true + # prometheus/events: true + # prometheus/asynchronous_metrics: true + # clickhouse.defaultSettings -- Default settings for ClickHouse. !!! Please DO NOT override this !!! + # @section -- ClickHouse Settings + # @default -- "Please checkout the default values in values.yml" + defaultSettings: + format_schema_path: /etc/clickhouse-server/config.d/ + user_scripts_path: /var/lib/clickhouse/user_scripts/ + user_defined_executable_functions_config: '/etc/clickhouse-server/functions/custom-functions.xml' + # clickhouse.podAnnotations -- Annotations for the ClickHouse pod(s). + # @section -- ClickHouse Settings + # @default -- { signoz.io/scrape: "true", signoz.io/port: "9363", signoz.io/path: "/metrics" } + podAnnotations: + signoz.io/scrape: 'true' + signoz.io/port: '9363' + signoz.io/path: /metrics + # clickhouse.podDistribution -- Topologies for distributing the ClickHouse pods. + # Possible values can be found here: https://github.com/Altinity/clickhouse-operator/blob/1414503921da3ae475eb6f9a296d3475a6993768/docs/chi-examples/99-clickhouseinstallation-max.yaml#L428-L481 + # @section -- ClickHouse Settings + # @default -- [] + podDistribution: [] + # - type: ShardAntiAffinity + # topologyKey: kubernetes.io/hostname + # - type: ReplicaAntiAffinity + # topologyKey: kubernetes.io/hostname + # - type: MaxNumberPerNode + # number: 2 + # topologyKey: kubernetes.io/hostname + + # clickhouse.coldStorage -- Cold storage configuration. + # @section -- ClickHouse Cold Storage + coldStorage: + # clickhouse.coldStorage.enabled -- Whether to enable S3/GCS cold storage. + # @default -- false + enabled: false + # clickhouse.coldStorage.defaultKeepFreeSpaceBytes -- Reserve free space on the default disk (in bytes). + # @default -- "10485760" + defaultKeepFreeSpaceBytes: "10485760" + # clickhouse.coldStorage.type -- Type of cold storage: `s3` or `gcs`. + # @default -- "s3" + type: s3 + # clickhouse.coldStorage.endpoint -- Endpoint for S3 or GCS. + # For S3 (us-east-1): https://s3.amazonaws.com + # For S3 (other regions): https://s3-.amazonaws.com + # For GCS: https://storage.googleapis.com//data/ + # @default -- "https://.s3-.amazonaws.com/data/" + endpoint: https://.s3-.amazonaws.com/data/ + # clickhouse.coldStorage.accessKey -- Access Key ID for S3 or GCS. + # @default -- "" + accessKey: + # clickhouse.coldStorage.secretAccess -- Secret Access Key for S3 or GCS. + # @default -- "" + secretAccess: + # clickhouse.coldStorage.role -- AWS IAM role configuration to use environment variables instead of keys. + # @section -- ClickHouse Cold Storage + role: + # clickhouse.coldStorage.role.enabled -- Whether to enable using an AWS IAM ARN role. + # @default -- false + enabled: false + # clickhouse.coldStorage.role.annotations -- Annotations for the service account to assume the AWS role. + # @default -- { eks.amazonaws.com/role-arn: "arn:aws:iam::******:role/****" } + annotations: + eks.amazonaws.com/role-arn: arn:aws:iam::******:role/***** + # clickhouse.files -- ClickHouse configuration files. + # Refs: + # - https://clickhouse.com/docs/en/operations/configuration-files/ + # - https://github.com/Altinity/clickhouse-operator/blob/master/docs/chi-examples/05-settings-05-files-nested.yaml + # @section -- ClickHouse Settings + # @default -- {} + files: + config.d/formatting.xml: | + + + + json + + date_time + thread_name + thread_id + level + query_id + logger_name + message + source_file + source_line + + + + + config.d/crash.xml: | + + + false + + + config.d/load.xml: | + + false + + config.d/system_log.xml: | + + + event_date + INTERVAL 3 DAY DELETE + + + event_date + INTERVAL 3 DAY DELETE + + + event_date + INTERVAL 7 DAY DELETE + + + event_date + INTERVAL 3 DAY DELETE + + + # clickhouse.installCustomStorageClass -- When enabled with `cloud` as `gcp` or `aws`, creates a custom storage class with volume expansion permission. + # @section -- ClickHouse Persistence + # @default -- false + installCustomStorageClass: false + # clickhouse.clickhouseOperator -- ClickHouse Operator settings. + # @section -- ClickHouse Operator + clickhouseOperator: + # clickhouse.clickhouseOperator.name -- Name of the component. + # @default -- "operator" + name: operator + # clickhouse.clickhouseOperator.version -- Version of the operator. + # @default -- "0.21.2" + version: 0.21.2 + # clickhouse.clickhouseOperator.image -- ClickHouse Operator image configuration. + # @section -- ClickHouse Operator Image + image: + # clickhouse.clickhouseOperator.image.registry -- ClickHouse Operator image registry. + # @default -- "docker.io" + registry: docker.io + # clickhouse.clickhouseOperator.image.repository -- ClickHouse Operator image repository. + # @default -- "altinity/clickhouse-operator" + repository: altinity/clickhouse-operator + # clickhouse.clickhouseOperator.image.tag -- ClickHouse Operator image tag. + # @default -- "0.21.2" + tag: 0.21.2 + # clickhouse.clickhouseOperator.image.pullPolicy -- ClickHouse Operator image pull policy. + # @default -- "IfNotPresent" + pullPolicy: IfNotPresent + # clickhouse.clickhouseOperator.imagePullSecrets -- Image Registry Secret Names for ClickHouse Operator. + # @section -- ClickHouse Operator Image + # @default -- [] + imagePullSecrets: [] + # - "clickhouseOperator-pull-secret" + + # clickhouse.clickhouseOperator.serviceAccount -- ClickHouse Operator Service Account configuration. + # @section -- ClickHouse Operator Security + serviceAccount: + # clickhouse.clickhouseOperator.serviceAccount.create -- Specifies whether a service account should be created. + # @default -- true + create: true + # clickhouse.clickhouseOperator.serviceAccount.annotations -- Annotations to add to the service account. + # @default -- {} + annotations: {} + # clickhouse.clickhouseOperator.serviceAccount.name -- The name of the service account to use. + # @default -- null + name: + # clickhouse.clickhouseOperator.logger -- ClickHouse logging configuration. + # @section -- ClickHouse Operator Logging + # @default -- "Please checkout the default values in values.yml" + logger: + level: information + size: 1000M + count: 10 + console: 1 + # clickhouse.clickhouseOperator.queryLog -- Query Log table configuration. + # @section -- ClickHouse Operator Logging + # @default -- { ttl: 30, flushInterval: 7500 } + queryLog: + ttl: 30 + flushInterval: 7500 + # clickhouse.clickhouseOperator.partLog -- Part Log table configuration. + # @section -- ClickHouse Operator Logging + # @default -- { ttl: 30, flushInterval: 7500 } + partLog: + ttl: 30 + flushInterval: 7500 + # clickhouse.clickhouseOperator.traceLog -- Trace Log table configuration. + # @section -- ClickHouse Operator Logging + # @default -- { ttl: 7, flushInterval: 7500 } + traceLog: + ttl: 7 + flushInterval: 7500 + # clickhouse.clickhouseOperator.asynchronousInsertLog -- Asynchronous Insert Log table configuration. + # @section -- ClickHouse Operator Logging + # @default -- { ttl: 7, flushInterval: 7500 } + asynchronousInsertLog: + ttl: 7 + flushInterval: 7500 + # clickhouse.clickhouseOperator.asynchronousMetricLog -- Asynchronous Metric Log table configuration. + # @section -- ClickHouse Operator Logging + # @default -- { ttl: 30, flushInterval: 7500 } + asynchronousMetricLog: + ttl: 30 + flushInterval: 7500 + # clickhouse.clickhouseOperator.backupLog -- Backup Log table configuration. + # @section -- ClickHouse Operator Logging + # @default -- { ttl: 7, flushInterval: 7500 } + backupLog: + ttl: 7 + flushInterval: 7500 + # clickhouse.clickhouseOperator.blobStorageLog -- Blob Storage Log table configuration. + # @section -- ClickHouse Operator Logging + # @default -- { ttl: 30, flushInterval: 7500 } + blobStorageLog: + ttl: 30 + flushInterval: 7500 + # clickhouse.clickhouseOperator.crashLog -- Crash Log table configuration. + # @section -- ClickHouse Operator Logging + # @default -- { ttl: 30, flushInterval: 7500 } + crashLog: + ttl: 30 + flushInterval: 7500 + # clickhouse.clickhouseOperator.metricLog -- Metric Log table configuration. + # @section -- ClickHouse Operator Logging + # @default -- { ttl: 30, flushInterval: 7500 } + metricLog: + ttl: 30 + flushInterval: 7500 + # clickhouse.clickhouseOperator.queryThreadLog -- Query Thread Log table configuration. + # @section -- ClickHouse Operator Logging + # @default -- { ttl: 7, flushInterval: 7500 } + queryThreadLog: + ttl: 7 + flushInterval: 7500 + # clickhouse.clickhouseOperator.queryViewsLog -- Query Views Log table configuration. + # @section -- ClickHouse Operator Logging + # @default -- { ttl: 15, flushInterval: 7500 } + queryViewsLog: + ttl: 15 + flushInterval: 7500 + # clickhouse.clickhouseOperator.sessionLog -- Session Log table configuration. + # @section -- ClickHouse Operator Logging + # @default -- { ttl: 30, flushInterval: 7500 } + sessionLog: + ttl: 30 + flushInterval: 7500 + # clickhouse.clickhouseOperator.zookeeperLog -- Zookeeper Log table configuration. + # @section -- ClickHouse Operator Logging + # @default -- { ttl: 30, flushInterval: 7500 } + zookeeperLog: + ttl: 30 + flushInterval: 7500 + # clickhouse.clickhouseOperator.processorsProfileLog -- Processors Profile Log table configuration. + # @section -- ClickHouse Operator Logging + # @default -- { ttl: 7, flushInterval: 7500 } + processorsProfileLog: + ttl: 7 + flushInterval: 7500 + # clickhouse.clickhouseOperator.podAnnotations -- ClickHouse Operator pod annotations. + # @section -- ClickHouse Operator + # @default -- { signoz.io/port: "8888", signoz.io/scrape: "true" } + podAnnotations: + signoz.io/port: '8888' + signoz.io/scrape: 'true' + # clickhouse.clickhouseOperator.nodeSelector -- ClickHouse Operator node selector. + # @section -- ClickHouse Operator Scheduling + # @default -- {} + nodeSelector: {} + # clickhouse.clickhouseOperator.metricsExporter -- Metrics Exporter configuration. + # @section -- ClickHouse Operator Metrics + metricsExporter: + # clickhouse.clickhouseOperator.metricsExporter.name -- Name of the component. + # @default -- "metrics-exporter" + name: metrics-exporter + # clickhouse.clickhouseOperator.metricsExporter.service -- Metrics Exporter service configuration. + # @section -- ClickHouse Operator Metrics + service: + # clickhouse.clickhouseOperator.metricsExporter.service.annotations -- Annotations for the Metrics Exporter service. + # @default -- {} + annotations: {} + # clickhouse.clickhouseOperator.metricsExporter.service.type -- Service type. + # @default -- "ClusterIP" + type: ClusterIP + # clickhouse.clickhouseOperator.metricsExporter.service.port -- Metrics Exporter port. + # @default -- 8888 + port: 8888 + # clickhouse.clickhouseOperator.metricsExporter.image -- Metrics Exporter image configuration. + # @section -- ClickHouse Operator Metrics Image + image: + # clickhouse.clickhouseOperator.metricsExporter.image.registry -- Metrics Exporter image registry. + # @default -- "docker.io" + registry: docker.io + # clickhouse.clickhouseOperator.metricsExporter.image.repository -- Metrics Exporter image repository. + # @default -- "altinity/metrics-exporter" + repository: altinity/metrics-exporter + # clickhouse.clickhouseOperator.metricsExporter.image.tag -- Metrics Exporter image tag. + # @default -- "0.21.2" + tag: 0.21.2 + # clickhouse.clickhouseOperator.metricsExporter.image.pullPolicy -- Metrics Exporter image pull policy. + # @default -- "IfNotPresent" + pullPolicy: IfNotPresent +# externalClickhouse -- External ClickHouse configuration. Required when `clickhouse.enabled` is false. +# @section -- External ClickHouse +externalClickhouse: + # externalClickhouse.host - Host of the external ClickHouse cluster. + # @default -- null + host: + # externalClickhouse.cluster - Name of the external cluster to run DDL queries on. + # @default -- "cluster" + cluster: cluster + # externalClickhouse.database - Database name for the external cluster. + # @default -- "signoz_metrics" + database: signoz_metrics + # externalClickhouse.traceDatabase - Database name for SigNoz Traces on the external cluster. + # @default -- "signoz_traces" + traceDatabase: signoz_traces + # externalClickhouse.logDatabase - Database name for SigNoz Logs on the external cluster. + # @default -- "signoz_logs" + logDatabase: signoz_logs + # externalClickhouse.meterDatabase - Database name for SigNoz Meter on the external cluster. + # @default -- "signoz_meter" + meterDatabase: signoz_meter + # externalClickhouse.user - Username to connect to the external cluster. + # @default -- "" + user: "" + # externalClickhouse.password - Password for the external cluster. Ignored if `externalClickhouse.existingSecret` is set. + # @default -- "" + password: "" + # externalClickhouse.existingSecret - Name of an existing Kubernetes secret containing the password. + # @default -- null + existingSecret: + # externalClickhouse.existingSecretPasswordKey - Key in the existing secret that contains the password. + # @default -- null + existingSecretPasswordKey: + # externalClickhouse.secure - Whether to use a TLS connection when connecting to ClickHouse. + # @default -- false + secure: false + # externalClickhouse.verify - Whether to verify the TLS certificate on connection to ClickHouse. + # @default -- false + verify: false + # externalClickhouse.httpPort - HTTP port of the external ClickHouse instance. + # @default -- 8123 + httpPort: 8123 + # externalClickhouse.tcpPort - TCP port of the external ClickHouse instance. + # @default - 9000 + tcpPort: 9000 +# signoz -- Default values for SigNoz. +# @section -- SigNoz +# @default -- "Please checkout the default values in values.yml" +signoz: + # signoz.name -- The name of the SigNoz component. + # @default -- "signoz" + # @section -- SigNoz + name: "signoz" + # signoz.replicaCount -- The number of pod replicas for SigNoz. + # @default -- 1 + # @section -- SigNoz + replicaCount: 1 + # signoz.image -- Image configuration for SigNoz. + # @section -- SigNoz + image: + # signoz.image.registry - The container image registry. + # @default -- "docker.io" + # @section -- SigNoz + registry: docker.io + # signoz.image.repository - The container image repository. + # @default -- "signoz/signoz" + repository: signoz/signoz + # signoz.image.tag - The container image tag. + # @default -- "v0.110.1" + tag: v0.128.0 + # signoz.image.pullPolicy - The image pull policy. + # @default -- "IfNotPresent" + pullPolicy: IfNotPresent + # signoz.imagePullSecrets -- Image pull secrets for SigNoz. + # This has higher precedence than the root level or global value. + # @section -- SigNoz + # @default -- [] + imagePullSecrets: [] + # signoz.serviceAccount -- Service Account configuration for SigNoz. + # @section -- SigNoz + serviceAccount: + # signoz.serviceAccount.create - Specifies whether a service account should be created. + # @default -- true + create: true + # signoz.serviceAccount.annotations - Annotations to add to the service account. + # @default -- {} + annotations: {} + # signoz.serviceAccount.name - The name of the service account to use. If not set and `create` is true, a name is generated. + # @default -- null + name: + # signoz.service -- Service configuration for SigNoz. + # This allows you to configure how SigNoz is exposed within the Kubernetes cluster. + # @section -- SigNoz Networking + service: + # signoz.service.annotations - Annotations for the SigNoz service object. + # @default -- {} + annotations: {} + # signoz.service.labels - Labels for the SigNoz service object. + # @default -- {} + labels: {} + # signoz.service.type - The service type (`ClusterIP`, `NodePort`, `LoadBalancer`). + # @default -- "ClusterIP" + type: NodePort + # signoz.service.port - The external HTTP port for SigNoz. + # @default -- 8080 + port: 8080 + # signoz.service.internalPort - The internal gRPC port for SigNoz. + # @default -- 8085 + internalPort: 8085 + # signoz.service.opampPort - The internal OpAMP port for SigNoz. + # @default -- 4320 + opampPort: 4320 + # signoz.service.nodePort - Manually specify the nodePort for HTTP when `service.type` is `NodePort`. + # @default -- null + nodePort: 30111 + # signoz.service.internalNodePort - Manually specify the nodePort for the internal port when `service.type` is `NodePort`. + # @default -- null + internalNodePort: null + # signoz.service.opampInternalNodePort - Manually specify the nodePort for OpAMP when `service.type` is `NodePort`. + # @default -- null + opampInternalNodePort: null + # signoz.annotations -- Annotations for the SigNoz pod. + # @section -- SigNoz + # @default -- null + annotations: + # signoz.additionalArgs -- Additional command-line arguments for SigNoz. + # @section -- SigNoz + # @default -- [] + additionalArgs: [] + # Environment variables for the SigNoz. + # You can specify variables in two ways: + # 1. Flexible structure for advanced configurations (recommended): + # Example: + # env: + # MY_KEY: + # value: my-value # Direct value + # SECRET_KEY: + # valueFrom: # Reference from a Secret or ConfigMap + # secretKeyRef: + # name: my-secret + # key: my-key + # 2. Simple key-value pairs (backward-compatible): + # Example: + # env: + # MY_KEY: my-value + + # signoz.env -- Environment variables for SigNoz. + # Refer to the official documentation for a complete list: https://github.com/SigNoz/signoz/blob/main/conf/example.yaml + # Note on Variable Naming: Environment variables are derived from the YAML configuration. + # For example, a key `provider` under the `telemetry_store` section becomes + # `signoz_telemetrystore_provider`. + # @section -- SigNoz + env: + signoz_telemetrystore_provider: clickhouse + # ClickHouse URL is set and applied internally. Don't override unless you know what you are doing. + # signoz_telemetrystore_clickhouse_dsn: tcp://clickhouse_operator:clickhouse_operator_password@my-release-clickhouse:9000/signoz_traces + + # Enable SMTP for user invitations. For more details see: https://signoz.io/docs/manage/administrator-guide/configuration/smtp-email-invitations/ + signoz_emailing_enabled: false + # To enable/disable the active query tracker. + signoz_prometheus_active__query__tracker_enabled: false + # signoz alertemanager configuration + # For more details see: https://signoz.io/docs/manage/administrator-guide/configuration/alertmanager/ + signoz_alertmanager_provider: signoz + # The URL under which Alertmanager is externally reachable, Used for generating relative and absolute links back to Alertmanager itself. + signoz_alertmanager_signoz_external__url: http://localhost:8080 + # signoz.podSecurityContext -- Pod-level security context. + # @section -- SigNoz + # @default -- {} + podSecurityContext: {} + # fsGroup: 2000 + + # signoz.podAnnotations -- Annotations for the SigNoz pod. + # @section -- SigNoz + # @default -- {} + podAnnotations: {} + # signoz.securityContext -- Container-level security context. + # @section -- SigNoz + # @default -- {} + securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + + # signoz.additionalVolumeMounts -- Additional volume mounts for the SigNoz container. + # @section -- SigNoz + # @default -- [] + additionalVolumeMounts: [] + # signoz.additionalVolumes -- Additional volumes for the SigNoz pod. + # @section -- SigNoz + # @default -- [] + additionalVolumes: [] + # signoz.livenessProbe -- Liveness probe configuration. + # @section -- SigNoz + # @default -- "Please checkout the default values in values.yml" + livenessProbe: + enabled: true + port: http + path: /api/v1/health + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + # signoz.readinessProbe -- Readiness probe configuration. + # @section -- SigNoz + # @default -- "Please checkout the default values in values.yml" + readinessProbe: + enabled: true + port: http + path: /api/v1/health?live=1 + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + # signoz.customLivenessProbe -- Custom liveness probe to override the default. + # @section -- SigNoz + # @default -- {} + customLivenessProbe: {} + # signoz.customReadinessProbe -- Custom readiness probe to override the default. + # @section -- SigNoz + # @default -- {} + customReadinessProbe: {} + # signoz.ingress -- (object) Ingress configuration for SigNoz. + # @section -- SigNoz Networking + ingress: + # signoz.ingress.enabled - Enable ingress controller resource. + # @default -- false + enabled: false + # signoz.ingress.className - Ingress class name. + # @default -- "" + className: "" + # signoz.ingress.annotations - Annotations for the ingress resource. + # @default -- {} + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + # cert-manager.io/cluster-issuer: letsencrypt-prod + # signoz.ingress.hosts - Hostname and path configurations for the ingress. + # @section -- SigNoz Networking + hosts: + - host: signoz.domain.com + paths: + - path: / + pathType: ImplementationSpecific + port: 8080 + # signoz.ingress.tls - TLS configuration for the ingress. + # @default -- [] + # @section -- SigNoz Networking + tls: [] + # - secretName: chart-example-tls + # hosts: + # - signoz.domain.com + # signoz.resources -- Resource requests and limits. + # Ref: http://kubernetes.io/docs/user-guide/compute-resources/ + # @section -- SigNoz + # @default -- '{ requests: { cpu: "100m", memory: "100Mi" } }' + resources: + requests: + cpu: 100m + memory: 100Mi + # limits: + # cpu: 750m + # memory: 1000Mi + + # signoz.priorityClassName -- Priority class for the SigNoz pods. + # @section -- SigNoz + # @default -- "" + priorityClassName: "" + # signoz.nodeSelector -- Node selector for pod assignment. + # @section -- SigNoz + # @default -- {} + nodeSelector: {} + # signoz.tolerations -- Tolerations for pod assignment. + # @section -- SigNoz + # @default -- [] + tolerations: [] + # signoz.affinity -- Affinity settings for pod assignment. + # @section -- SigNoz + # @default -- {} + affinity: {} + # signoz.topologySpreadConstraints -- Topology spread constraints for pod distribution. + # @section -- SigNoz + # @default -- [] + topologySpreadConstraints: [] + # signoz.persistence -- Persistence configuration for the internal SQLite database. + # @section -- SigNoz + persistence: + # signoz.persistence.enabled - Enable data persistence using a PVC. + # @default -- true + enabled: true + # signoz.persistence.existingClaim - Use a manually managed PVC. + # @default -- "" + existingClaim: "" + # signoz.persistence.storageClass - The storage class for the PVC. If "-", disables dynamic provisioning. + # @default -- null + storageClass: null + # signoz.persistence.accessModes - Access modes for the persistent volume. + # @default -- ["ReadWriteOnce"] + accessModes: + - ReadWriteOnce + # signoz.persistence.size - The size of the persistent volume. + # @default -- "1Gi" + size: 1Gi +# telemetryStoreMigrator -- Default values for the Telemetry Store Migrator. +# @section -- Telemetry Store Migrator +# @default -- "Please checkout the default values in values.yml" +telemetryStoreMigrator: + # telemetryStoreMigrator.enabled -- Enable the Telemetry Store Migrator component. + # @default -- true + # @section -- Telemetry Store Migrator + enabled: true + # telemetryStoreMigrator.name -- The name of the Telemetry Store Migrator component. + # @default -- "signoz-telemetrystore-migrator" + # @section -- Telemetry Store Migrator + name: "signoz-telemetrystore-migrator" + # telemetryStoreMigrator.annotations -- Annotations for the Telemetry Store Migrator job. + # @default -- {} + # @section -- Telemetry Store Migrator + annotations: {} + # telemetryStoreMigrator.upgradeHelmHooks -- Enable Helm pre-upgrade hooks and ArgoCD Sync hooks. + # @default -- true + # @section -- Telemetry Store Migrator + upgradeHelmHooks: true + # telemetryStoreMigrator.enableReplication -- Whether to enable replication for the Telemetry Store Migrator. + # @default -- true + # @section -- Telemetry Store Migrator + enableReplication: true + # telemetryStoreMigrator.timeout -- Timeout for the migration. + # @default -- "10m" + # @section -- Telemetry Store Migrator + timeout: "10m" + # telemetryStoreMigrator.nodeSelector -- Node selector for pod assignment. + # @section -- Telemetry Store Migrator + # @default -- {} + nodeSelector: {} + # telemetryStoreMigrator.tolerations -- Tolerations for pod assignment. + # @section -- Telemetry Store Migrator + # @default -- [] + tolerations: [] + # telemetryStoreMigrator.affinity -- Affinity settings for pod assignment. + # @section -- Telemetry Store Migrator + # @default -- {} + affinity: {} + # telemetryStoreMigrator.topologySpreadConstraints -- Topology spread constraints for pod distribution. + # @section -- Telemetry Store Migrator + # @default -- [] + topologySpreadConstraints: [] + # telemetryStoreMigrator.resources -- Resource requests and limits for all migrator containers. + # @section -- Telemetry Store Migrator + # @default -- {} + resources: {} + # telemetryStoreMigrator.serviceAccount -- Service Account configuration for the Telemetry Store Migrator. + # @section -- Telemetry Store Migrator + serviceAccount: + # telemetryStoreMigrator.serviceAccount.create - Specifies whether a service account should be created. + # @default -- true + create: true + # telemetryStoreMigrator.serviceAccount.annotations - Annotations to add to the service account. + # @default -- {} + annotations: {} + # telemetryStoreMigrator.serviceAccount.name - The name of the service account to use. If not set and `create` is true, a name is generated. + # @default -- null + name: +# Default values for OtelCollector +# otelCollector -- Default values for the OpenTelemetry Collector. +# @section -- Otel Collector +# @default -- "Please checkout the default values in values.yml" +otelCollector: + # otelCollector.name -- The name of the Otel Collector component. + # @default -- "otel-collector" + # @section -- Otel Collector + name: "otel-collector" + # otelCollector.image -- Image configuration for the Otel Collector. + # @section -- Otel Collector + # @default -- "Please checkout the default values in values.yml" + image: + # otelCollector.image.registry - The container image registry. + # @default -- "docker.io" + registry: docker.io + # otelCollector.image.repository - The container image repository. + # @default -- "signoz/signoz-otel-collector" + repository: signoz/signoz-otel-collector + # otelCollector.image.tag - The container image tag. + # @default -- "v0.144.0" + tag: v0.144.5 + # otelCollector.image.pullPolicy - The image pull policy. + # @default -- "IfNotPresent" + pullPolicy: IfNotPresent + # otelCollector.imagePullSecrets -- Image pull secrets for the Otel Collector. + # This has higher precedence than the root level or global value. + # @section -- Otel Collector + # @default -- [] + imagePullSecrets: [] + # otelCollector.strategy -- Deployment strategy to use + # @section -- Otel Collector + # @default -- "RollingUpdate" + strategy: "" + # otelCollector.command -- Configuration for the Otel Collector executable. + # @section -- Otel Collector + command: + # otelCollector.command.name - Otel Collector command name. + # @default -- "/signoz-otel-collector" + name: /signoz-otel-collector + # otelCollector.command.extraArgs - Extra command-line arguments for the Otel Collector. + extraArgs: + # otelCollector.configMap -- ConfigMap settings. + # @section -- Otel Collector + configMap: + # otelCollector.configMap.create - Specifies whether a ConfigMap should be created. + # @default -- true + create: true + # otelCollector.serviceAccount -- Service Account configuration for the Otel Collector. + # @section -- Otel Collector + serviceAccount: + # otelCollector.serviceAccount.create - Specifies whether a service account should be created. + # @default -- true + create: true + # otelCollector.serviceAccount.annotations - Annotations to add to the service account. + # @default -- {} + annotations: {} + # otelCollector.serviceAccount.name - The name of the service account to use. If not set and `create` is true, a name is generated. + # @default -- null + name: + # otelCollector.service -- Service configuration for the Otel Collector. + # @section -- Otel Collector Networking + service: + # otelCollector.service.annotations - Annotations for the Otel Collector service object. + # @default -- {} + annotations: {} + # otelCollector.service.labels - Labels for the Otel Collector service object. + # @default -- {} + labels: {} + # otelCollector.service.type - The service type (`ClusterIP`, `NodePort`, `LoadBalancer`). + # @default -- "ClusterIP" + type: ClusterIP + # otelCollector.service.loadBalancerSourceRanges - Allowed source ranges when service type is `LoadBalancer`. + # @default -- [] + loadBalancerSourceRanges: [] + # otelCollector.annotations -- Annotations for the Otel Collector Deployment. + # @section -- Otel Collector + # @default -- null + annotations: + # otelCollector.podAnnotations -- Annotations for the Otel Collector pod(s). + # @section -- Otel Collector + # @default -- { signoz.io/scrape: "true", signoz.io/port: "8888" } + podAnnotations: + signoz.io/scrape: 'true' + signoz.io/port: '8888' + # otelCollector.podLabels -- Labels for the Otel Collector pod(s). + # @section -- Otel Collector + # @default -- {} + podLabels: {} + # otelCollector.additionalEnvs -- Additional environment variables for the Otel Collector. + # @section -- Otel Collector + # @default -- {} + additionalEnvs: {} + # env_key: env_value + + # otelCollector.lowCardinalityExceptionGrouping -- Whether to enable grouping of exceptions with the same name but different stack traces. This is a tradeoff between cardinality and accuracy. + # @section -- Otel Collector + # @default -- false + lowCardinalityExceptionGrouping: false + # otelCollector.minReadySeconds -- Minimum number of seconds for a new pod to be ready. + # @section -- Otel Collector + # @default -- 5 + minReadySeconds: 5 + # otelCollector.progressDeadlineSeconds -- Maximum time in seconds for a deployment to make progress before it is considered failed. + # @section -- Otel Collector + # @default -- 600 + progressDeadlineSeconds: 600 + # otelCollector.replicaCount -- The number of pod replicas for the Otel Collector. + # @section -- Otel Collector + # @default -- 1 + replicaCount: 1 + # otelCollector.clusterRole -- RBAC ClusterRole configuration for the Otel Collector. + # @section -- Otel Collector + # @default -- "Please checkout the default values in values.yml" + clusterRole: + # otelCollector.clusterRole.create - Specifies whether a ClusterRole should be created. + # @default -- true + # @section -- Otel Collector + create: true + # otelCollector.clusterRole.annotations - Annotations to add to the ClusterRole. + # @default -- {} + annotations: {} + # @section -- Otel Collector + # otelCollector.clusterRole.name - The name of the ClusterRole to use. If not set, a name is generated. + # @default -- "" + name: "" + # otelCollector.clusterRole.rules - A set of RBAC rules. Required for the k8sattributes processor. + # ref: https://kubernetes.io/docs/reference/access-authn-authz/rbac/ + # @default -- "Please checkout the default values in values.yml" + # @section -- Otel Collector + rules: + - apiGroups: [""] + resources: ["pods", "namespaces", "nodes"] + verbs: ["get", "list", "watch"] + - apiGroups: ["apps"] + resources: ["replicasets"] + verbs: ["get", "list", "watch"] + - apiGroups: ["extensions"] + resources: ["replicasets"] + verbs: ["get", "list", "watch"] + - apiGroups: ["batch"] + resources: ["jobs"] + verbs: ["get", "list", "watch"] + # otelCollector.clusterRole.clusterRoleBinding - ClusterRoleBinding configuration. + clusterRoleBinding: + # otelCollector.clusterRole.clusterRoleBinding.annotations - Annotations to add to the ClusterRoleBinding. + # @default -- {} + annotations: {} + # otelCollector.clusterRole.clusterRoleBinding.name - The name of the ClusterRoleBinding to use. If not set, a name is generated. + # @default -- "" + name: "" + # otelCollector.ports -- Port configurations for the Otel Collector. + # @section -- Otel Collector Ports + # @default -- "Please checkout the default values in values.yml" + ports: + # otelCollector.ports.otlp -- OTLP gRPC port configuration. + # @section -- Otel Collector Ports + otlp: + # otelCollector.ports.otlp.enabled - Whether to enable the service port for OTLP gRPC. + # @default -- true + enabled: true + # otelCollector.ports.otlp.containerPort - Container port for OTLP gRPC. + # @default -- 4317 + containerPort: 4317 + # otelCollector.ports.otlp.servicePort - Service port for OTLP gRPC. + # @default -- 4317 + servicePort: 4317 + # otelCollector.ports.otlp.nodePort - Node port for OTLP gRPC. + # @default -- "" + nodePort: "" + # otelCollector.ports.otlp.protocol - Protocol for OTLP gRPC. + # @default -- "TCP" + protocol: TCP + # otelCollector.ports.otlp-http -- OTLP HTTP port configuration. + # @section -- Otel Collector Ports + otlp-http: + # otelCollector.ports.otlp-http.enabled - Whether to enable the service port for OTLP HTTP. + # @default -- true + enabled: true + # otelCollector.ports.otlp-http.containerPort - Container port for OTLP HTTP. + # @default -- 4318 + containerPort: 4318 + # otelCollector.ports.otlp-http.servicePort - Service port for OTLP HTTP. + # @default -- 4318 + servicePort: 4318 + # otelCollector.ports.otlp-http.nodePort - Node port for OTLP HTTP. + # @default -- "" + nodePort: "" + # otelCollector.ports.otlp-http.protocol - Protocol for OTLP HTTP. + # @default -- "TCP" + protocol: TCP + # otelCollector.ports.jaeger-compact -- Jaeger Compact port configuration. + # @section -- Otel Collector Ports + jaeger-compact: + # otelCollector.ports.jaeger-compact.enabled - Whether to enable the service port for Jaeger Compact. + # @default -- false + enabled: false + # otelCollector.ports.jaeger-compact.containerPort - Container port for Jaeger Compact. + # @default -- 6831 + containerPort: 6831 + # otelCollector.ports.jaeger-compact.servicePort - Service port for Jaeger Compact. + # @default -- 6831 + servicePort: 6831 + # otelCollector.ports.jaeger-compact.nodePort - Node port for Jaeger Compact. + # @default -- "" + nodePort: "" + # otelCollector.ports.jaeger-compact.protocol - Protocol for Jaeger Compact. + # @default -- "UDP" + protocol: UDP + # otelCollector.ports.jaeger-thrift -- Jaeger Thrift port configuration. + # @section -- Otel Collector Ports + jaeger-thrift: + # otelCollector.ports.jaeger-thrift.enabled - Whether to enable the service port for Jaeger Thrift HTTP. + # @default -- true + enabled: true + # otelCollector.ports.jaeger-thrift.containerPort - Container port for Jaeger Thrift. + # @default -- 14268 + containerPort: 14268 + # otelCollector.ports.jaeger-thrift.servicePort - Service port for Jaeger Thrift. + # @default -- 14268 + servicePort: 14268 + # otelCollector.ports.jaeger-thrift.nodePort - Node port for Jaeger Thrift. + # @default -- "" + nodePort: "" + # otelCollector.ports.jaeger-thrift.protocol - Protocol for Jaeger Thrift. + # @default -- "TCP" + protocol: TCP + # otelCollector.ports.jaeger-grpc -- Jaeger gRPC port configuration. + # @section -- Otel Collector Ports + jaeger-grpc: + # otelCollector.ports.jaeger-grpc.enabled - Whether to enable the service port for Jaeger gRPC. + # @default -- true + enabled: true + # otelCollector.ports.jaeger-grpc.containerPort - Container port for Jaeger gRPC. + # @default -- 14250 + containerPort: 14250 + # otelCollector.ports.jaeger-grpc.servicePort - Service port for Jaeger gRPC. + # @default -- 14250 + servicePort: 14250 + # otelCollector.ports.jaeger-grpc.nodePort - Node port for Jaeger gRPC. + # @default -- "" + nodePort: "" + # otelCollector.ports.jaeger-grpc.protocol - Protocol for Jaeger gRPC. + # @default -- "TCP" + protocol: TCP + # otelCollector.ports.zipkin -- Zipkin port configuration. + # @section -- Otel Collector Ports + zipkin: + # otelCollector.ports.zipkin.enabled - Whether to enable the service port for Zipkin. + # @default -- false + enabled: false + # otelCollector.ports.zipkin.containerPort - Container port for Zipkin. + # @default -- 9411 + containerPort: 9411 + # otelCollector.ports.zipkin.servicePort - Service port for Zipkin. + # @default -- 9411 + servicePort: 9411 + # otelCollector.ports.zipkin.nodePort - Node port for Zipkin. + # @default -- "" + nodePort: "" + # otelCollector.ports.zipkin.protocol - Protocol for Zipkin. + # @default -- "TCP" + protocol: TCP + # otelCollector.ports.metrics -- Internal metrics port configuration. + # @section -- Otel Collector Ports + metrics: + # otelCollector.ports.metrics.enabled - Whether to enable the service port for internal metrics. + # @default -- true + enabled: true + # otelCollector.ports.metrics.containerPort - Container port for internal metrics. + # @default -- 8888 + containerPort: 8888 + # otelCollector.ports.metrics.servicePort - Service port for internal metrics. + # @default -- 8888 + servicePort: 8888 + # otelCollector.ports.metrics.nodePort - Node port for internal metrics. + # @default -- "" + nodePort: "" + # otelCollector.ports.metrics.protocol - Protocol for internal metrics. + # @default -- "TCP" + protocol: TCP + # otelCollector.ports.zpages -- ZPages port configuration. + # @section -- Otel Collector Ports + zpages: + # otelCollector.ports.zpages.enabled - Whether to enable the service port for ZPages. + # @default -- false + enabled: false + # otelCollector.ports.zpages.containerPort - Container port for ZPages. + # @default -- 55679 + containerPort: 55679 + # otelCollector.ports.zpages.servicePort - Service port for ZPages. + # @default -- 55679 + servicePort: 55679 + # otelCollector.ports.zpages.nodePort - Node port for ZPages. + # @default -- "" + nodePort: "" + # otelCollector.ports.zpages.protocol - Protocol for ZPages. + # @default -- "TCP" + protocol: TCP + # otelCollector.ports.pprof -- pprof port configuration. + # @section -- Otel Collector Ports + pprof: + # otelCollector.ports.pprof.enabled - Whether to enable the service port for pprof. + # @default -- false + enabled: false + # otelCollector.ports.pprof.containerPort - Container port for pprof. + # @default -- 1777 + containerPort: 1777 + # otelCollector.ports.pprof.servicePort - Service port for pprof. + # @default -- 1777 + servicePort: 1777 + # otelCollector.ports.pprof.nodePort - Node port for pprof. + # @default -- "" + nodePort: "" + # otelCollector.ports.pprof.protocol - Protocol for pprof. + # @default -- "TCP" + protocol: TCP + # otelCollector.ports.logsheroku -- Heroku logs port configuration. + # @section -- Otel Collector Ports + logsheroku: + # otelCollector.ports.logsheroku.enabled - Whether to enable the service port for Heroku logs. + # @default -- true + enabled: true + # otelCollector.ports.logsheroku.containerPort - Container port for Heroku logs. + # @default -- 8081 + containerPort: 8081 + # otelCollector.ports.logsheroku.servicePort - Service port for Heroku logs. + # @default -- 8081 + servicePort: 8081 + # otelCollector.ports.logsheroku.nodePort - Node port for Heroku logs. + # @default -- "" + nodePort: "" + # otelCollector.ports.logsheroku.protocol - Protocol for Heroku logs. + # @default -- "TCP" + protocol: TCP + # otelCollector.ports.logsjson -- JSON logs port configuration. + # @section -- Otel Collector Ports + logsjson: + # otelCollector.ports.logsjson.enabled - Whether to enable the service port for JSON logs. + # @default -- true + enabled: true + # otelCollector.ports.logsjson.containerPort - Container port for JSON logs. + # @default -- 8082 + containerPort: 8082 + # otelCollector.ports.logsjson.servicePort - Service port for JSON logs. + # @default -- 8082 + servicePort: 8082 + # otelCollector.ports.logsjson.nodePort - Node port for JSON logs. + # @default -- "" + nodePort: "" + # otelCollector.ports.logsjson.protocol - Protocol for JSON logs. + # @default -- "TCP" + protocol: TCP + # otelCollector.livenessProbe -- Liveness probe configuration. + # ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes + # @section -- Otel Collector + # @default -- "Please checkout the default values in values.yml" + livenessProbe: + enabled: true + port: 13133 + path: / + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + # otelCollector.readinessProbe -- Readiness probe configuration. + # @section -- Otel Collector + # @default -- "Please checkout the default values in values.yml" + readinessProbe: + enabled: true + port: 13133 + path: / + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + # otelCollector.customLivenessProbe -- Custom liveness probe to override the default. + # @section -- Otel Collector + # @default -- {} + customLivenessProbe: {} + # otelCollector.customReadinessProbe -- Custom readiness probe to override the default. + # @section -- Otel Collector + # @default -- {} + customReadinessProbe: {} + # otelCollector.extraVolumeMounts -- Extra volume mounts for the Otel Collector pod. + # @section -- Otel Collector + # @default -- [] + extraVolumeMounts: [] + # otelCollector.extraVolumes -- Extra volumes for the Otel Collector pod. + # @section -- Otel Collector + # @default -- [] + extraVolumes: [] + # otelCollector.ingress -- Ingress configuration for the Otel Collector. + # @section -- Otel Collector Networking + ingress: + # otelCollector.ingress.enabled - Enable ingress controller resource. + # @default -- false + enabled: false + # otelCollector.ingress.className - Ingress class name. + # @default -- "" + className: "" + # otelCollector.ingress.annotations - Annotations for the ingress resource. + # @default -- {} + annotations: {} + # cert-manager.io/cluster-issuer: letsencrypt-prod + # nginx.ingress.kubernetes.io/ssl-redirect: "true" + # nginx.ingress.kubernetes.io/backend-protocol: "GRPC" + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + # otelCollector.ingress.hosts -- Hostname and path configurations for the ingress. + # @default -- "Please checkout the default values in values.yml" + # @section -- Otel Collector Networking + hosts: + - host: otelcollector.domain.com + paths: + - path: / + pathType: ImplementationSpecific + port: 4318 + # otelCollector.ingress.tls - TLS configuration for the ingress. + # @default -- [] + tls: [] + # - secretName: chart-example-tls + # hosts: + # - otelcollector.domain.com + # otelCollector.resources -- Resource requests and limits. + # Ref: http://kubernetes.io/docs/user-guide/compute-resources/ + # @section -- Otel Collector + # @default -- { requests: { cpu: "100m", memory: "200Mi" } } + resources: + requests: + cpu: 100m + memory: 200Mi + # limits: + # cpu: "1" + # memory: 2Gi + + # otelCollector.priorityClassName -- Priority class for the Otel Collector pods. + # @section -- Otel Collector + # @default -- "" + priorityClassName: "" + # otelCollector.nodeSelector -- Node selector for pod assignment. + # @section -- Otel Collector + # @default -- {} + nodeSelector: {} + # otelCollector.tolerations -- Tolerations for pod assignment. + # @section -- Otel Collector + # @default -- [] + tolerations: [] + # otelCollector.affinity -- Affinity settings for pod assignment. + # @section -- Otel Collector + # @default -- {} + affinity: {} + # otelCollector.topologySpreadConstraints -- Topology spread constraints for pod distribution. + # @section -- Otel Collector + # @default -- "Please checkout the default values in values.yml" + topologySpreadConstraints: + - maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway + labelSelector: + matchLabels: + app.kubernetes.io/component: otel-collector + # otelCollector.podSecurityContext -- Pod-level security context. + # @section -- Otel Collector + # @default -- {} + podSecurityContext: {} + # fsGroup: 2000 + + # otelCollector.securityContext -- Container-level security context. + # @section -- Otel Collector + # @default -- {} + securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + + # otelCollector.autoscaling -- Autoscaling configuration (HPA). + # @section -- Otel Collector + # @default -- "Please checkout the default values in values.yml" + autoscaling: + # otelCollector.autoscaling.enabled - Enable Horizontal Pod Autoscaler. + # @default -- false + enabled: false + # otelCollector.autoscaling.minReplicas - Minimum number of replicas. + # @default -- 1 + minReplicas: 1 + # otelCollector.autoscaling.maxReplicas - Maximum number of replicas. + # @default -- 11 + maxReplicas: 11 + # otelCollector.autoscaling.targetCPUUtilizationPercentage - Target CPU utilization percentage. + # @default -- 50 + targetCPUUtilizationPercentage: 50 + # otelCollector.autoscaling.targetMemoryUtilizationPercentage - Target memory utilization percentage. + # @default -- 50 + targetMemoryUtilizationPercentage: 50 + # otelCollector.autoscaling.behavior - Scaling behavior policies. + # @default -- {} + behavior: {} + # scaleDown: + # stabilizationWindowSeconds: 300 + # policies: + # - type: Pods + # value: 1 + # periodSeconds: 180 + # scaleUp: + # stabilizationWindowSeconds: 300 + # policies: + # - type: Pods + # value: 2 + # periodSeconds: 60 + + # otelCollector.autoscaling.autoscalingTemplate - Template for autoscaling. + # @default -- [] + autoscalingTemplate: [] + # otelCollector.autoscaling.keda -- KEDA-based autoscaling configuration. + # @section -- Otel Collector + keda: + # otelCollector.autoscaling.keda.annotations - Annotations for the KEDA ScaledObject. + # @default -- null + annotations: + # otelCollector.autoscaling.keda.enabled - Enable KEDA autoscaling. + # @default -- false + enabled: false + # otelCollector.autoscaling.keda.pollingInterval - Polling interval for metrics data (in seconds). + # @default -- "30" + pollingInterval: "30" + # otelCollector.autoscaling.keda.cooldownPeriod - Cooldown period before downscaling (in seconds). + # @default -- "300" + cooldownPeriod: "300" + # otelCollector.autoscaling.keda.minReplicaCount - Minimum replica count for KEDA. + # @default -- "1" + minReplicaCount: "1" + # otelCollector.autoscaling.keda.maxReplicaCount - Maximum replica count for KEDA. + # @default -- "5" + maxReplicaCount: "5" + # otelCollector.autoscaling.keda.triggers - KEDA trigger configuration. + # @default -- [] + triggers: [] + # otelCollector.config -- Main configuration for the OpenTelemetry Collector pipelines. + # @section -- Otel Collector Configuration + # @default -- "Please checkout the default values in values.yml" + config: + connectors: + signozmeter: + metrics_flush_interval: 1h + dimensions: + - name: service.name + - name: deployment.environment + - name: host.name + receivers: + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 + max_recv_msg_size_mib: 16 + http: + endpoint: 0.0.0.0:4318 + jaeger: + protocols: + grpc: + endpoint: 0.0.0.0:14250 + thrift_http: + endpoint: 0.0.0.0:14268 + httplogreceiver/heroku: + endpoint: 0.0.0.0:8081 + source: heroku + httplogreceiver/json: + endpoint: 0.0.0.0:8082 + source: json + processors: + batch: + send_batch_size: 50000 + timeout: 1s + batch/meter: + send_batch_max_size: 25000 + send_batch_size: 20000 + timeout: 1s + # Memory Limiter processor. If not set, it will be overridden with values based on k8s resource limits. + # ref: https://github.com/open-telemetry/opentelemetry-collector/blob/main/processor/memorylimiterprocessor/README.md + # memory_limiter: null + signozspanmetrics/delta: + metrics_exporter: signozclickhousemetrics + latency_histogram_buckets: [100us, 1ms, 2ms, 6ms, 10ms, 50ms, 100ms, 250ms, 500ms, 1000ms, 1400ms, 2000ms, 5s, 10s, 20s, 40s, 60s] + dimensions_cache_size: 100000 + dimensions: + - name: service.namespace + default: default + - name: deployment.environment + default: default + - name: signoz.collector.id + aggregation_temporality: AGGREGATION_TEMPORALITY_DELTA + extensions: + health_check: + endpoint: 0.0.0.0:13133 + zpages: + endpoint: localhost:55679 + pprof: + endpoint: localhost:1777 + exporters: + clickhousetraces: + datasource: tcp://${env:CLICKHOUSE_USER}:${env:CLICKHOUSE_PASSWORD}@${env:CLICKHOUSE_HOST}:${env:CLICKHOUSE_PORT}/${env:CLICKHOUSE_TRACE_DATABASE} + low_cardinal_exception_grouping: ${env:LOW_CARDINAL_EXCEPTION_GROUPING} + use_new_schema: true + signozclickhousemetrics: + dsn: tcp://${env:CLICKHOUSE_USER}:${env:CLICKHOUSE_PASSWORD}@${env:CLICKHOUSE_HOST}:${env:CLICKHOUSE_PORT}/${env:CLICKHOUSE_DATABASE} + timeout: 45s + clickhouselogsexporter: + dsn: tcp://${env:CLICKHOUSE_USER}:${env:CLICKHOUSE_PASSWORD}@${env:CLICKHOUSE_HOST}:${env:CLICKHOUSE_PORT}/${env:CLICKHOUSE_LOG_DATABASE} + timeout: 10s + use_new_schema: true + metadataexporter: + enabled: true + dsn: tcp://${env:CLICKHOUSE_USER}:${env:CLICKHOUSE_PASSWORD}@${env:CLICKHOUSE_HOST}:${env:CLICKHOUSE_PORT}/signoz_metadata + timeout: 10s + tenant_id: ${env:TENANT_ID} + cache: + provider: in_memory + signozclickhousemeter: + dsn: tcp://${env:CLICKHOUSE_USER}:${env:CLICKHOUSE_PASSWORD}@${env:CLICKHOUSE_HOST}:${env:CLICKHOUSE_PORT}/${env:CLICKHOUSE_METER_DATABASE} + timeout: 45s + sending_queue: + enabled: false + service: + telemetry: + logs: + encoding: json + extensions: [health_check, zpages, pprof] + pipelines: + traces: + receivers: [otlp, jaeger] + processors: [signozspanmetrics/delta, batch] + exporters: [clickhousetraces, metadataexporter, signozmeter] + metrics: + receivers: [otlp] + processors: [batch] + exporters: [metadataexporter, signozclickhousemetrics, signozmeter] + logs: + receivers: [otlp, httplogreceiver/heroku, httplogreceiver/json] + processors: [batch] + exporters: [clickhouselogsexporter, metadataexporter, signozmeter] + metrics/meter: + receivers: [signozmeter] + processors: [batch/meter] + exporters: [signozclickhousemeter] +# @section -- Postgres +postgresql: + # postgresql.enabled -- Enable or disable the PostgreSQL for signoz. + # For more details, check out the postgresql chart: https://github.com/SigNoz/charts/tree/main/charts/postgresql + # @default -- false + # @section -- Postgres + enabled: false +# -- This component is configurable with licensed version of SigNoz. +# @section -- Otel Gateway Settings +signoz-otel-gateway: + enabled: false + # @ignored + replicaCount: 1 + # signoz-otel-gateway.strategy -- Deployment strategy to use + # @section -- signoz-otel-gateway + # @default -- "RollingUpdate" + strategy: "" + # @ignored + resources: + requests: + cpu: 2500m + memory: 2500Mi + # @ignored + # config: + # exporters: + # signozkafka: + # brokers: + # # replace with the correct address based on the release name + # # - redpanda-0.redpanda.redpanda.svc.cluster.local:9093 + # # - redpanda-1.redpanda.redpanda.svc.cluster.local:9093 + # # - redpanda-2.redpanda.redpanda.svc.cluster.local:9093 + # producer: + # compression: lz4 + # max_message_bytes: 209715200 + # protocol_version: 2.0.0 + # extensions: + # health_check: + # endpoint: 0.0.0.0:13133 + # path: /healthz + # signozadminapi: + # cache: + # extension: signozcache + # endpoint: 0.0.0.0:8001 + # limiter: + # policy: postgres + # storage: + # extension: signozstorage + # signozcache: + # strategy: ${env:OTELGATEWAY_CACHE_STRATEGY} + # uri: + # database: ${env:OTELGATEWAY_REDIS_DATABASE} + # host: ${env:OTELGATEWAY_REDIS_HOST} + # port: ${env:OTELGATEWAY_REDIS_PORT} + # signozkeyauth: + # cache: + # extension: signozcache + # headers: + # - signoz-access-token + # - authorization + # - signoz-ingestion-key + # - x-amz-firehose-access-key + # storage: + # extension: signozstorage + # signozstorage: + # strategy: ${env:OTELGATEWAY_STORAGE_STRATEGY} + # uri: + # database: ${env:OTELGATEWAY_POSTGRES_DATABASE} + # host: ${env:OTELGATEWAY_POSTGRES_HOST} + # password: ${env:OTELGATEWAY_POSTGRES_PASSWORD} + # port: ${env:OTELGATEWAY_POSTGRES_PORT} + # user: ${env:OTELGATEWAY_POSTGRES_USER} + # zpages: + # endpoint: :55679 + # processors: + # batch: + # metadata_keys: + # - signoz-workspace-name + # send_batch_max_size: 25000 + # send_batch_size: 20000 + # timeout: 10s + # signozlimiter/postgres: + # cache: + # extension: signozcache + # policy: postgres + # storage: + # extension: signozstorage + # receivers: + # otlp: + # protocols: + # grpc: + # auth: + # authenticator: signozkeyauth + # endpoint: 0.0.0.0:4317 + # max_recv_msg_size_mib: 16 + # http: + # auth: + # authenticator: signozkeyauth + # cors: + # allowed_origins: + # - '*' + # endpoint: 0.0.0.0:4318 + # signozhttplog/heroku: + # auth: + # authenticator: signozkeyauth + # endpoint: 0.0.0.0:8081 + # source: heroku + # signozhttplog/json: + # auth: + # authenticator: signozkeyauth + # endpoint: 0.0.0.0:8082 + # source: json + # signozawsfirehose/cwmetrics: + # auth: + # authenticator: signozkeyauth + # endpoint: 0.0.0.0:8084 + # record_type: cwmetrics + # signozawsfirehose/cwlogs: + # auth: + # authenticator: signozkeyauth + # endpoint: 0.0.0.0:8085 + # record_type: cwlogs + # signozawsfirehose/otlp_v1: + # auth: + # authenticator: signozkeyauth + # endpoint: 0.0.0.0:8086 + # record_type: otlp_v1 + # service: + # extensions: + # - signozstorage + # - signozcache + # - zpages + # - signozkeyauth + # - health_check + # - signozadminapi + # pipelines: + # logs: + # exporters: + # - signozkafka + # processors: + # # replace with signozlimiter/redis if redis is used as cache backend + # - signozlimiter/postgres + # - batch + # receivers: + # - otlp + # - signozhttplog/heroku + # - signozhttplog/json + # - signozawsfirehose/cwlogs + # metrics: + # exporters: + # - signozkafka + # processors: + # # replace with signozlimiter/redis if redis is used as cache backend + # - signozlimiter/postgres + # - batch + # receivers: + # - otlp + # - signozawsfirehose/cwmetrics + # - signozawsfirehose/otlp_v1 + # traces: + # exporters: + # - signozkafka + # processors: + # # replace with signozlimiter/redis if redis is used as cache backend + # - signozlimiter/postgres + # - batch + # receivers: + # - otlp + # @ignored + env: + cache_strategy: "off" + storage_strategy: postgres + # postgres_database: + # valueFrom: + # secretKeyRef: + # key: database + # name: postgres-secret-otelgateway + # postgres_host: + # valueFrom: + # secretKeyRef: + # key: host + # name: postgres-secret-otelgateway + # postgres_password: + # valueFrom: + # secretKeyRef: + # key: password + # name: postgres-secret-otelgateway + # postgres_port: + # valueFrom: + # secretKeyRef: + # key: port + # name: postgres-secret-otelgateway + # postgres_user: + # valueFrom: + # secretKeyRef: + # key: username + # name: postgres-secret-otelgateway + # @ignored + fullnameOverride: opentelemetry-gateway + # @ignored + ingress: [] + # @ignored + service: + annotations: {} + ports: + otlp: + containerPort: 4317 + enabled: true + protocol: TCP + servicePort: 4317 + otlp-grpc: + enabled: false + aws-cwmetrics: + enabled: true + containerPort: 8084 + servicePort: 8084 + protocol: TCP + aws-cwlogs: + enabled: true + containerPort: 8085 + servicePort: 8085 + protocol: TCP + aws-otlp: + enabled: true + containerPort: 8086 + servicePort: 8086 + protocol: TCP + type: NodePort +# -- This component is configurable with licensed version of SigNoz. +# @section -- Redpanda Settings +redpanda: + enabled: false + # @ignored + fullnameOverride: redpanda + # @ignored + config: + cluster: + auto_create_topics_enabled: true + default_topic_partitions: 3 + delete_retention_ms: 21600000 + tunable: + kafka_batch_max_bytes: 209715200 + kafka_request_max_bytes: 209715200 + # @ignored + console: + enabled: false + # @ignored + rbac: + enabled: false + # @ignored + resources: + cpu: + cores: 7 + memory: + container: + max: 28Gi + # @ignored + serviceAccount: + create: false + # @ignored + statefulset: + podTemplate: + annotations: + signoz.io/path: /public_metrics + signoz.io/port: "9644" + signoz.io/scrape: "true" + replicas: 3 + terminationGracePeriodSeconds: 180 + # @ignored + storage: + persistentVolume: + size: 100Gi + storageClass: null + # @ignored + tls: + certs: + external: + caEnabled: false + enabled: false + diff --git a/src/OpenTelemetryExtension.Configuration.Sample.WebApi/OpenTelemetryExtension.Configuration.Sample.WebApi.csproj b/src/OpenTelemetryExtension.Configuration.Sample.WebApi/OpenTelemetryExtension.Configuration.Sample.WebApi.csproj index 71d6344..18c29ca 100644 --- a/src/OpenTelemetryExtension.Configuration.Sample.WebApi/OpenTelemetryExtension.Configuration.Sample.WebApi.csproj +++ b/src/OpenTelemetryExtension.Configuration.Sample.WebApi/OpenTelemetryExtension.Configuration.Sample.WebApi.csproj @@ -6,7 +6,8 @@ enable Linux ..\WpfApp - true + true + 1.1.1.1 diff --git a/src/OpenTelemetryExtension.Configuration.Sample.WebApi/appsettings.signoz.json b/src/OpenTelemetryExtension.Configuration.Sample.WebApi/appsettings.signoz.json index b1bddc3..631e16a 100644 --- a/src/OpenTelemetryExtension.Configuration.Sample.WebApi/appsettings.signoz.json +++ b/src/OpenTelemetryExtension.Configuration.Sample.WebApi/appsettings.signoz.json @@ -1,7 +1,7 @@ { "Telemetry": { "Protocol": "HttpProtobuf", - "Endpoint": "http://localhost:50709", + "Endpoint": "http://localhost:30318", "Headers": "" } } diff --git a/src/OpenTelemetryExtension.Configuration.Sample.Wpf/OpenTelemetryExtension.Configuration.Sample.Wpf.csproj b/src/OpenTelemetryExtension.Configuration.Sample.Wpf/OpenTelemetryExtension.Configuration.Sample.Wpf.csproj index 08c160c..86a9660 100644 --- a/src/OpenTelemetryExtension.Configuration.Sample.Wpf/OpenTelemetryExtension.Configuration.Sample.Wpf.csproj +++ b/src/OpenTelemetryExtension.Configuration.Sample.Wpf/OpenTelemetryExtension.Configuration.Sample.Wpf.csproj @@ -7,6 +7,7 @@ enable true true + 9.9.9.9 From c450d8ccb3fffaca798426a8b18332935f771375 Mon Sep 17 00:00:00 2001 From: thorsten Date: Sat, 13 Jun 2026 13:41:02 +0200 Subject: [PATCH 4/8] chore: cover csproj, yaml and batch files in editorconfig --- .editorconfig | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/.editorconfig b/.editorconfig index 683ab1d..2a29b0f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,23 +1,32 @@ root = true -[*.csproj] +# MSBuild project files +[*.{csproj,props,targets}] indent_style = space indent_size = 2 tab_width = 2 +charset = utf-8 insert_final_newline = true -# optional XML-spezifisch -charset = utf-8 +# YAML +[*.{yaml,yml}] +indent_style = space +indent_size = 2 +tab_width = 2 +insert_final_newline = true + +# Windows batch scripts +[*.{bat,cmd}] +indent_style = space +indent_size = 2 +tab_width = 2 +end_of_line = crlf +insert_final_newline = true [src/**/Migrations/*.cs] generated_code = true dotnet_analyzer_diagnostic.severity = none - -# [*.{xml,yaml,yml,json}] -# indent_style = space -# indent_size = 2 -# tab_width = 2 [*.{cs,vb}] indent_size = 4 From e8b2dddb6d3a0288a91e00ae9532392f3cdab4fb Mon Sep 17 00:00:00 2001 From: thorsten Date: Sat, 13 Jun 2026 18:05:01 +0200 Subject: [PATCH 5/8] test: add SigNoz integration tests with auto-provisioned dev admin Export traces, metrics and logs over OTLP HTTP (port 30318) and verify ingestion via SigNoz's query_range API. A helm bootstrap Job registers the dev admin on first boot so the tests work without manual signup. Also fix OtelTestHost to instantiate the Tracer/Meter providers up front, so the ActivityListener and metric readers are active before spans/measurements are created (previously only logs were exported). --- infrastructure/helm/helm-install-signoz.cmd | 5 +- .../helm/signoz.bootstrap-admin.yaml | 33 +++ infrastructure/helm/signoz.nodeports.yaml | 19 +- infrastructure/helm/signoz.values.yaml | 4 +- .../SigNozIntegrationTests.cs | 106 +++++++++ .../Utils/IntegrationConfig.cs | 5 + .../Utils/OtelTestHost.cs | 5 + .../Utils/SigNozClient.cs | 219 ++++++++++++++++++ 8 files changed, 392 insertions(+), 4 deletions(-) create mode 100644 infrastructure/helm/signoz.bootstrap-admin.yaml create mode 100644 src/OpenTelemetryExtension.Configuration.IntegrationTests/SigNozIntegrationTests.cs create mode 100644 src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/SigNozClient.cs diff --git a/infrastructure/helm/helm-install-signoz.cmd b/infrastructure/helm/helm-install-signoz.cmd index 75b6da0..f21bba7 100644 --- a/infrastructure/helm/helm-install-signoz.cmd +++ b/infrastructure/helm/helm-install-signoz.cmd @@ -3,13 +3,16 @@ helm repo add signoz https://charts.signoz.io helm repo update helm uninstall signoz --wait --timeout 300s -kubectl delete chi signoz-clickhouse --ignore-not-found --wait +REM kubectl delete chi signoz-clickhouse --ignore-not-found --wait helm install signoz signoz/signoz --version 0.128.0 -f signoz.values.yaml --wait --timeout 600s kubectl delete -f signoz.nodeports.yaml --ignore-not-found kubectl apply -f signoz.nodeports.yaml +kubectl delete -f signoz.bootstrap-admin.yaml --ignore-not-found +kubectl apply -f signoz.bootstrap-admin.yaml + REM helm show values signoz/signoz --version 0.128.0 > signoz.values.yaml pause \ No newline at end of file diff --git a/infrastructure/helm/signoz.bootstrap-admin.yaml b/infrastructure/helm/signoz.bootstrap-admin.yaml new file mode 100644 index 0000000..80e7b1e --- /dev/null +++ b/infrastructure/helm/signoz.bootstrap-admin.yaml @@ -0,0 +1,33 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: signoz-bootstrap-admin + namespace: default +spec: + backoffLimit: 20 + ttlSecondsAfterFinished: 300 + template: + spec: + restartPolicy: OnFailure + containers: + - name: register + image: curlimages/curl:8.11.0 + command: ["/bin/sh", "-c"] + args: + - | + set -eu + echo "Waiting for SigNoz to be ready..." + until curl -sf http://signoz:8080/api/v1/health >/dev/null 2>&1; do sleep 3; done + echo "Registering dev admin (idempotent)..." + code=$(curl -s -o /tmp/out -w "%{http_code}" -X POST \ + -H "Content-Type: application/json" \ + -d '{"email":"admin@web.de","password":"$$$AdminPass123","orgDisplayName":"dev"}' \ + http://signoz:8080/api/v1/register) + echo "register -> ${code}: $(cat /tmp/out)" + case "${code}" in + 200|201) echo "admin created"; exit 0 ;; + esac + if grep -q "self-registration is disabled" /tmp/out; then + echo "already initialized; nothing to do"; exit 0 + fi + echo "unexpected register failure"; exit 1 diff --git a/infrastructure/helm/signoz.nodeports.yaml b/infrastructure/helm/signoz.nodeports.yaml index c983223..9605d1b 100644 --- a/infrastructure/helm/signoz.nodeports.yaml +++ b/infrastructure/helm/signoz.nodeports.yaml @@ -1,7 +1,7 @@ apiVersion: v1 kind: Service metadata: - name: signoz-nodeport + name: signoz-otel-nodeport namespace: default spec: type: NodePort @@ -17,3 +17,20 @@ spec: port: 4318 targetPort: 4318 nodePort: 30318 + +--- +apiVersion: v1 +kind: Service +metadata: + name: signoz-nodeport + namespace: default +spec: + type: NodePort + selector: + app.kubernetes.io/instance: signoz + app.kubernetes.io/component: signoz + ports: + - name: http + port: 8080 + targetPort: 8080 + nodePort: 30111 diff --git a/infrastructure/helm/signoz.values.yaml b/infrastructure/helm/signoz.values.yaml index 1952ad2..c0e43e1 100644 --- a/infrastructure/helm/signoz.values.yaml +++ b/infrastructure/helm/signoz.values.yaml @@ -798,7 +798,7 @@ signoz: labels: {} # signoz.service.type - The service type (`ClusterIP`, `NodePort`, `LoadBalancer`). # @default -- "ClusterIP" - type: NodePort + type: ClusterIP # signoz.service.port - The external HTTP port for SigNoz. # @default -- 8080 port: 8080 @@ -810,7 +810,7 @@ signoz: opampPort: 4320 # signoz.service.nodePort - Manually specify the nodePort for HTTP when `service.type` is `NodePort`. # @default -- null - nodePort: 30111 + nodePort: null # signoz.service.internalNodePort - Manually specify the nodePort for the internal port when `service.type` is `NodePort`. # @default -- null internalNodePort: null diff --git a/src/OpenTelemetryExtension.Configuration.IntegrationTests/SigNozIntegrationTests.cs b/src/OpenTelemetryExtension.Configuration.IntegrationTests/SigNozIntegrationTests.cs new file mode 100644 index 0000000..566a240 --- /dev/null +++ b/src/OpenTelemetryExtension.Configuration.IntegrationTests/SigNozIntegrationTests.cs @@ -0,0 +1,106 @@ +using System.Diagnostics; +using System.Diagnostics.Metrics; +using Microsoft.Extensions.Logging; +using OpenTelemetry.Exporter; +using OpenTelemetryExtension.Configuration.IntegrationTests.Utils; + +namespace OpenTelemetryExtension.Configuration.IntegrationTests; + +[Trait("Category", "Integration")] +public sealed class SigNozIntegrationTests +{ + private static readonly TimeSpan QueryTimeout = TimeSpan.FromSeconds(40); + + [Fact] + public async Task Traces_AreExported_AndQueryableInSigNoz() + { + var runId = Guid.NewGuid().ToString("N"); + var serviceName = $"itest-signoz-traces-{runId}"; + var sourceName = $"Itest.SigNoz.Traces.{runId}"; + + using (var host = new OtelTestHost(o => + { + o.Protocol = OtlpExportProtocol.HttpProtobuf; + o.Endpoint = IntegrationConfig.SigNozOtlpEndpoint; + o.Headers = string.Empty; + o.ServiceName = serviceName; + o.EnableMetrics = false; + o.EnableLogging = false; + o.AdditionalTracingSources = [sourceName]; + })) + { + using var source = new ActivitySource(sourceName); + using (var activity = source.StartActivity("integration-span")) + { + activity?.SetTag("itest.run", runId); + } + + host.Flush(); + } + + using var client = new SigNozClient(); + var count = await client.CountServiceSignalAsync("traces", serviceName, QueryTimeout); + + Assert.True(count > 0, $"Expected at least one trace for service '{serviceName}' in SigNoz."); + } + + [Fact] + public async Task Metrics_AreExported_AndQueryableInSigNoz() + { + var runId = Guid.NewGuid().ToString("N"); + var serviceName = $"itest-signoz-metrics-{runId}"; + var meterName = $"Itest.SigNoz.Metrics.{runId}"; + var counterName = $"itest_signoz_counter_{runId}"; + + using (var host = new OtelTestHost(o => + { + o.Protocol = OtlpExportProtocol.HttpProtobuf; + o.Endpoint = IntegrationConfig.SigNozOtlpEndpoint; + o.Headers = string.Empty; + o.ServiceName = serviceName; + o.EnableTracing = false; + o.EnableLogging = false; + o.AdditionalMeters = [meterName]; + })) + { + using var meter = new Meter(meterName); + var counter = meter.CreateCounter(counterName); + counter.Add(3); + + host.Flush(); + } + + using var client = new SigNozClient(); + var count = await client.CountMetricAsync(counterName, QueryTimeout); + + Assert.True(count > 0, $"Expected the metric '{counterName}' to contain data points in SigNoz."); + } + + [Fact] + public async Task Logs_AreExported_AndQueryableInSigNoz() + { + var runId = Guid.NewGuid().ToString("N"); + var serviceName = $"itest-signoz-logs-{runId}"; + + using (var host = new OtelTestHost(o => + { + o.Protocol = OtlpExportProtocol.HttpProtobuf; + o.Endpoint = IntegrationConfig.SigNozOtlpEndpoint; + o.Headers = string.Empty; + o.ServiceName = serviceName; + o.EnableTracing = false; + o.EnableMetrics = false; + })) + { + var logger = host.CreateLogger(); + logger.LogInformation("integration log {RunId}", runId); + + host.Flush(); + } + + using var client = new SigNozClient(); + var count = await client.CountServiceSignalAsync("logs", serviceName, QueryTimeout); + + Assert.True(count > 0, $"Expected at least one log record for service '{serviceName}' in SigNoz."); + } +} diff --git a/src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/IntegrationConfig.cs b/src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/IntegrationConfig.cs index e0c68ab..6eeb7ea 100644 --- a/src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/IntegrationConfig.cs +++ b/src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/IntegrationConfig.cs @@ -8,4 +8,9 @@ internal static class IntegrationConfig public static string OtlpHeaders => "Authorization=Basic YWRtaW5Ad2ViLmRlOmFkbWlu,stream-name=default"; public static Uri OtlpEndpoint => new(OpenObserveBaseUrl); public static string SqlConnectionString => "Server=localhost,31433;Database=master;User Id=sa;Password=YourStrongPassword123!;TrustServerCertificate=True;Encrypt=False"; + + public static Uri SigNozOtlpEndpoint => new("http://localhost:30318"); + public static string SigNozApiBaseUrl => "http://localhost:30111"; + public static string SigNozUser => "admin@web.de"; + public static string SigNozPassword => "$$$AdminPass123"; } diff --git a/src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/OtelTestHost.cs b/src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/OtelTestHost.cs index 28c5612..249657d 100644 --- a/src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/OtelTestHost.cs +++ b/src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/OtelTestHost.cs @@ -23,6 +23,11 @@ public OtelTestHost(Action configure) }); _provider = services.BuildServiceProvider(); + + // Instantiate the providers up front so the ActivityListener and metric + // readers are active before the test creates spans or measurements. + _provider.GetService(); + _provider.GetService(); } public ILogger CreateLogger() => _provider.GetRequiredService>(); diff --git a/src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/SigNozClient.cs b/src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/SigNozClient.cs new file mode 100644 index 0000000..0687785 --- /dev/null +++ b/src/OpenTelemetryExtension.Configuration.IntegrationTests/Utils/SigNozClient.cs @@ -0,0 +1,219 @@ +using System.Globalization; +using System.Net.Http.Headers; +using System.Text; +using System.Text.Json; + +namespace OpenTelemetryExtension.Configuration.IntegrationTests.Utils; + +internal sealed class SigNozClient : IDisposable +{ + private const long OneHourMillis = 3_600_000L; + + private readonly HttpClient _http = new() { Timeout = TimeSpan.FromSeconds(20) }; + private string? _jwt; + + public Task CountServiceSignalAsync(string dataSource, string serviceName, TimeSpan timeout, CancellationToken ct = default) + => PollUntilAsync(BuildServiceQuery(dataSource, serviceName), timeout, ct); + + public Task CountMetricAsync(string metricName, TimeSpan timeout, CancellationToken ct = default) + => PollUntilAsync(BuildMetricQuery(metricName), timeout, ct); + + private async Task PollUntilAsync(Func buildQuery, TimeSpan timeout, CancellationToken ct) + { + await EnsureAuthenticatedAsync(ct); + + var deadline = DateTime.UtcNow + timeout; + long count = 0; + + while (DateTime.UtcNow < deadline) + { + var now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); + count = await QueryAsync(buildQuery(now - OneHourMillis, now), ct); + if (count > 0) + { + return count; + } + + await Task.Delay(2000, ct); + } + + return count; + } + + private async Task EnsureAuthenticatedAsync(CancellationToken ct) + { + if (_jwt is not null) + { + return; + } + + var orgId = await GetOrgIdAsync(ct); + + var payload = new { email = IntegrationConfig.SigNozUser, password = IntegrationConfig.SigNozPassword, orgId }; + using var content = new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json"); + using var response = await _http.PostAsync($"{IntegrationConfig.SigNozApiBaseUrl}/api/v2/sessions/email_password", content, ct); + response.EnsureSuccessStatusCode(); + + using var doc = JsonDocument.Parse(await response.Content.ReadAsStringAsync(ct)); + _jwt = doc.RootElement.GetProperty("data").GetProperty("accessToken").GetString(); + } + + private async Task GetOrgIdAsync(CancellationToken ct) + { + var url = $"{IntegrationConfig.SigNozApiBaseUrl}/api/v2/sessions/context?email={Uri.EscapeDataString(IntegrationConfig.SigNozUser)}"; + using var response = await _http.GetAsync(url, ct); + response.EnsureSuccessStatusCode(); + + using var doc = JsonDocument.Parse(await response.Content.ReadAsStringAsync(ct)); + var orgs = doc.RootElement.GetProperty("data").GetProperty("orgs"); + if (orgs.ValueKind != JsonValueKind.Array || orgs.GetArrayLength() == 0) + { + throw new InvalidOperationException($"SigNoz returned no organization for user '{IntegrationConfig.SigNozUser}'."); + } + + return orgs[0].GetProperty("id").GetString() + ?? throw new InvalidOperationException("SigNoz organization id was null."); + } + + private async Task QueryAsync(object query, CancellationToken ct) + { + using var request = new HttpRequestMessage(HttpMethod.Post, $"{IntegrationConfig.SigNozApiBaseUrl}/api/v4/query_range") + { + Content = new StringContent(JsonSerializer.Serialize(query), Encoding.UTF8, "application/json"), + }; + request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _jwt); + + using var response = await _http.SendAsync(request, ct); + if (!response.IsSuccessStatusCode) + { + return 0; + } + + return ParseCount(await response.Content.ReadAsStringAsync(ct)); + } + + private static Func BuildServiceQuery(string dataSource, string serviceName) => (start, end) => new + { + start, + end, + step = 60, + compositeQuery = new + { + queryType = "builder", + panelType = "table", + builderQueries = new Dictionary + { + ["A"] = new + { + dataSource, + queryName = "A", + expression = "A", + aggregateOperator = "count", + timeAggregation = "count", + spaceAggregation = "sum", + stepInterval = 60, + disabled = false, + reduceTo = "sum", + filters = new + { + op = "AND", + items = new[] + { + new + { + key = new { key = "service.name", dataType = "string", type = "resource", isColumn = false }, + op = "=", + value = serviceName, + }, + }, + }, + }, + }, + }, + }; + + private static Func BuildMetricQuery(string metricName) => (start, end) => new + { + start, + end, + step = 60, + compositeQuery = new + { + queryType = "builder", + panelType = "table", + builderQueries = new Dictionary + { + ["A"] = new + { + dataSource = "metrics", + queryName = "A", + expression = "A", + aggregateOperator = "count", + timeAggregation = "count", + spaceAggregation = "sum", + stepInterval = 60, + disabled = false, + reduceTo = "sum", + aggregateAttribute = new { key = metricName, dataType = "float64", type = "" }, + filters = new { op = "AND", items = Array.Empty() }, + }, + }, + }, + }; + + private static long ParseCount(string json) + { + using var doc = JsonDocument.Parse(json); + if (!doc.RootElement.TryGetProperty("data", out var data) + || !data.TryGetProperty("result", out var result) + || result.ValueKind != JsonValueKind.Array) + { + return 0; + } + + long max = 0; + foreach (var query in result.EnumerateArray()) + { + if (!query.TryGetProperty("series", out var series) || series.ValueKind != JsonValueKind.Array) + { + continue; + } + + foreach (var serie in series.EnumerateArray()) + { + if (!serie.TryGetProperty("values", out var values) || values.ValueKind != JsonValueKind.Array) + { + continue; + } + + foreach (var point in values.EnumerateArray()) + { + if (point.TryGetProperty("value", out var value) + && TryReadDouble(value, out var parsed) + && parsed > max) + { + max = (long)parsed; + } + } + } + } + + return max; + } + + private static bool TryReadDouble(JsonElement element, out double value) + { + switch (element.ValueKind) + { + case JsonValueKind.Number: + return element.TryGetDouble(out value); + case JsonValueKind.String: + return double.TryParse(element.GetString(), NumberStyles.Float, CultureInfo.InvariantCulture, out value); + default: + value = 0; + return false; + } + } + + public void Dispose() => _http.Dispose(); +} From c4670f893e4920a8fe572528bbb322b329af8bcb Mon Sep 17 00:00:00 2001 From: thorsten Date: Sat, 13 Jun 2026 18:05:23 +0200 Subject: [PATCH 6/8] =?UTF-8?q?chore:=20repo=20hygiene=20=E2=80=94=20.clau?= =?UTF-8?q?de=20to=20.agents=20migration,=20SECURITY=20policy,=20CI/doc=20?= =?UTF-8?q?fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Move the prepare-release skill from .claude/ to .agents/ and retarget all pointers (AGENTS.md, CONTRIBUTING.md, .slnx); gitignore the local settings - Add a repo-tailored /evaluate-repository command and SECURITY.md - Trim CLAUDE.md to a pure pointer (its notes already live in AGENTS.md) - Fix stale AGENTS.md test docs (no IntegrationFact/auto-skip; hardcoded creds) - Fix ci.yml trailing-backtick continuation and make tool-manifest idempotent --- .agents/commands/evaluate-repository.md | 121 ++++++++++++++++++ .../skills/prepare-release/SKILL.md | 0 .../prepare-release/assets/release-notes.md | 0 .../scripts/check-otel-updates.sh | 0 .../prepare-release/scripts/smoke-test.sh | 0 .github/workflows/ci.yml | 6 +- .gitignore | 1 + AGENTS.md | 31 +++-- CLAUDE.md | 9 -- CONTRIBUTING.md | 2 +- OpenTelemetryExtension.slnx | 18 +-- SECURITY.md | 23 ++++ 12 files changed, 179 insertions(+), 32 deletions(-) create mode 100644 .agents/commands/evaluate-repository.md rename {.claude => .agents}/skills/prepare-release/SKILL.md (100%) rename {.claude => .agents}/skills/prepare-release/assets/release-notes.md (100%) rename {.claude => .agents}/skills/prepare-release/scripts/check-otel-updates.sh (100%) rename {.claude => .agents}/skills/prepare-release/scripts/smoke-test.sh (100%) create mode 100644 SECURITY.md diff --git a/.agents/commands/evaluate-repository.md b/.agents/commands/evaluate-repository.md new file mode 100644 index 0000000..0007ae3 --- /dev/null +++ b/.agents/commands/evaluate-repository.md @@ -0,0 +1,121 @@ +--- +description: Static, read-only quality & health review of this OpenTelemetry NuGet library +argument-hint: "[path or focus area, e.g. src/... or infrastructure/helm]" +--- + +# Repository Evaluation · OpenTelemetryExtension.Configuration + +## Context + +You are reviewing **this** repository: a NuGet package that wires up +OpenTelemetry (tracing, metrics, logging) for .NET apps via a single +`AddTelemetry()` call and `appsettings.json`. `AGENTS.md` is the canonical +source of truth for layout, conventions, build/test commands and the release +process — read it first and treat any deviation between it and the code as a +finding. + +The shipped surface is small (the library targets `netstandard2.0`, `net8.0`, +`net10.0`); most risk is in **multi-targeting correctness, telemetry wiring, +test gating, and release/packaging hygiene** — not in third-party trust. + +## Instructions + +Perform a **static, read-only** review. Do not run code, install packages, or +execute scripts. Base every claim on repository contents; cite concrete files +and lines. Prefer explicit uncertainty over confident speculation, and separate +confirmed findings from speculation. + +Scope: if `$ARGUMENTS` is non-empty, focus the review on that path or area; +otherwise evaluate the whole repository. + +## Evaluation criteria + +For each category: assign a score 1–10, justify concisely with file/line +evidence, and note uncertainty. + +### 1. .NET code quality & conventions +- Adherence to `AGENTS.md` / `CLAUDE.md` conventions: file-scoped namespaces, + `_camelCase`/`s_camelCase` fields, `is null`/`is not null`, + `ArgumentNullException.ThrowIfNull`, expression-bodied members, no `#region`. +- `src/Directory.Build.props` invariants actually hold: nullable enabled, + `TreatWarningsAsErrors`, `EnforceCodeStyleInBuild`, implicit usings. +- Readability, correctness, internal consistency. + +### 2. Multi-targeting correctness +- `netstandard2.0` does not use net5.0+ APIs without `#if NET5_0_OR_GREATER` / + `#if !NETSTANDARD2_0` guards. +- ASP.NET Core instrumentation is referenced only where valid (not on + `netstandard2.0`); any `!`-suppression carries the documented justification. + +### 3. Telemetry wiring +- `TelemetryServiceCollectionExtensions` / `TelemetryOptions`: OTLP exporter + configured correctly per signal (gRPC posts to base endpoint; HttpProtobuf + appends `v1/traces|metrics|logs`), sampler, resource/service attributes, + validation of required options. +- Config binding (`Telemetry` section) matches the documented options and + defaults. + +### 4. Tests +- Unit tests carry `[Trait("Category", "Unit")]` (untagged tests are silently + skipped by CI); integration tests carry `[Trait("Category", "Integration")]`. +- Unit tests avoid `Thread.Sleep`/network; integration tests (`OpenObserve`, + `SigNoz`, SQL Server) are isolated from CI and self-contained. +- Coverage of the public surface and meaningful assertions (not smoke-only). + +### 5. Public API & packaging +- Public surface is minimal and intentional; XML `` docs present on + public members, absent on internal/private. +- NuGet metadata, SemVer discipline, and that `` is managed only via + the `prepare-release` skill (never bumped manually). + +### 6. Build, CI & automation surface +- `ci.yml` builds + runs `Category=Unit`; `deploy-nuget.yml` is manual-only and + builds only library + unit-test projects. +- Local-execution surface under `infrastructure/helm/` (install `.cmd`/`.sh` + scripts, the `signoz.bootstrap-admin` Job) and `.agents/` (skills, commands, + `settings.local.json`): note anything that runs implicitly or with elevated + trust, and confirm it is documented. + +## Checklist (answer each explicitly) + +- Builds clean under `TreatWarningsAsErrors` (no evidence of suppressed/ignored + warnings) +- `netstandard2.0` API guards present where required +- Every unit-test class is `Category=Unit` +- OTLP per-signal endpoint logic is correct +- Public members documented; internals not over-documented +- `` not hand-edited outside the release skill +- Scripts / Jobs that execute locally are documented and scoped +- Secrets/credentials: none committed **except** clearly local-only dev + defaults (e.g. the SigNoz/OpenObserve dev login used by integration tests) — + flag any real secret + +Briefly explain any item that fails. + +## Findings format + +### A. Confirmed issues +File · line · description · suggested minimal fix. + +### B. Likely issues / needs manual check +Mark each as *likely* or *unclear*. + +### C. Convention drift vs AGENTS.md +List mismatches between documented rules and the code. + +## Overall assessment + +- **Score:** X / 10 +- **Recommendation:** one of — *Healthy* · *Healthy with caveats* · + *Needs cleanup before release* · *Blocking issues* +- If *Blocking*, name the blocker(s). + +## Suggested improvements + +Specific, minimal changes that would raise quality or unblock a release +(convention fixes, missing guards, test gaps, doc/packaging clarifications). + +--- + +FOCUS: $ARGUMENTS +(empty = evaluate the whole repository) diff --git a/.claude/skills/prepare-release/SKILL.md b/.agents/skills/prepare-release/SKILL.md similarity index 100% rename from .claude/skills/prepare-release/SKILL.md rename to .agents/skills/prepare-release/SKILL.md diff --git a/.claude/skills/prepare-release/assets/release-notes.md b/.agents/skills/prepare-release/assets/release-notes.md similarity index 100% rename from .claude/skills/prepare-release/assets/release-notes.md rename to .agents/skills/prepare-release/assets/release-notes.md diff --git a/.claude/skills/prepare-release/scripts/check-otel-updates.sh b/.agents/skills/prepare-release/scripts/check-otel-updates.sh similarity index 100% rename from .claude/skills/prepare-release/scripts/check-otel-updates.sh rename to .agents/skills/prepare-release/scripts/check-otel-updates.sh diff --git a/.claude/skills/prepare-release/scripts/smoke-test.sh b/.agents/skills/prepare-release/scripts/smoke-test.sh similarity index 100% rename from .claude/skills/prepare-release/scripts/smoke-test.sh rename to .agents/skills/prepare-release/scripts/smoke-test.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d60ae26..e2182ff 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,7 +38,7 @@ jobs: - name: Install .NET Tools (local) run: | - dotnet new tool-manifest + dotnet new tool-manifest --force dotnet tool install dotnet-reportgenerator-globaltool - name: Restore @@ -58,8 +58,8 @@ jobs: dotnet tool run reportgenerator ` -reports:TestResults/**/coverage.cobertura.xml ` -targetdir:TestResults/Reports ` - -reporttypes:"Html;lcov;Cobertura" ` - + -reporttypes:"Html;lcov;Cobertura" + - name: Upload Coverage to Coveralls uses: coverallsapp/github-action@v2 with: diff --git a/.gitignore b/.gitignore index 3e7693a..3f37222 100644 --- a/.gitignore +++ b/.gitignore @@ -91,6 +91,7 @@ yarn-error.log* /logs /archiv /_archiv +/.agents/settings.local.json **/TestResult/ /test.html.lnk diff --git a/AGENTS.md b/AGENTS.md index 1bb3ebd..916f22e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -110,15 +110,24 @@ API to confirm the data was ingested. - Needs the OpenObserve Helm chart (`infrastructure/helm/helm-install-openobserve.cmd`); the SQL Server chart (`helm-install-sqlserver.cmd`) is required only for the SQL test. -- Tests use `[IntegrationFact]` / `[SqlIntegrationFact]` (in `Utils/`) instead - of `[Fact]` — they **auto-skip** when OpenObserve (`localhost:30117`) or SQL - Server (`localhost:31433`) is unreachable, so the suite stays green without - the stack. +- Tests use plain `[Fact]` with `[Trait("Category", "Integration")]` at the + class level. They do **not** auto-skip — they fail if the backend + (OpenObserve `localhost:30117`, SQL Server `localhost:31433`, SigNoz + `localhost:30318`/`30111`) is unreachable — and are excluded from CI by the + `Category=Unit` filter, so the suite only runs with the stack up. +- `SigNozIntegrationTests` exercises the same export path against a running + **SigNoz** stack (`infrastructure/helm/helm-install-signoz.cmd`): it exports + via OTLP HTTP to `localhost:30318` and queries SigNoz's `query_range` API + (`localhost:30111`) to confirm ingestion. The dev admin login + (`admin@web.de`) is created automatically on first boot by the + `signoz.bootstrap-admin.yaml` Job that the install script applies; the org id + is resolved at runtime. Credentials are the local dev defaults in + `IntegrationConfig`. - Shared helpers live in `Utils/`: `IntegrationConfig` (endpoints/credentials), - `OpenObserveClient` (`_search` queries), `OtelTestHost`, `Reachability`. -- Endpoints/credentials default to the Helm chart values; override via env vars: - `OTEL_IT_OPENOBSERVE_URL`, `OTEL_IT_OPENOBSERVE_USER`, - `OTEL_IT_OPENOBSERVE_PASSWORD`, `OTEL_IT_OTLP_HEADERS`, `OTEL_IT_SQL_CONNECTION`. + `OpenObserveClient` (`_search` queries), `SigNozClient` (`query_range`), + `OtelTestHost`. +- Endpoints/credentials are hardcoded local-dev defaults in `IntegrationConfig` + (matching the Helm chart values); they are dev-only and not real secrets. - Run: `dotnet test src/OpenTelemetryExtension.Configuration.IntegrationTests -c Release`. ## Language & framework @@ -153,8 +162,8 @@ API to confirm the data was ingested. - **Every unit test class must carry `[Trait("Category", "Unit")]`** (class level). CI and the deploy workflow filter on `Category=Unit` — an untagged test is silently never run in CI. -- Integration test classes carry `[Trait("Category", "Integration")]` and use - `[IntegrationFact]` / `[SqlIntegrationFact]` instead of `[Fact]` +- Integration test classes carry `[Trait("Category", "Integration")]` at the + class level and use plain `[Fact]` / `[Theory]` - xUnit `[Fact]` for single cases, `[Theory]` + `[InlineData]` for parameterised - Method name pattern: `MethodOrProperty_Condition_ExpectedResult` - Arrange / Act / Assert with a blank line between each section; trivial @@ -177,7 +186,7 @@ API to confirm the data was ingested. never triggered automatically; it also creates the `v{VERSION}` git tag - The full release-prep workflow (decide SemVer, bump, update deps, build/test, end-to-end smoke test, release notes, PR to `main`) is encoded in the - **`prepare-release`** skill at `.claude/skills/prepare-release/`. Run it via + **`prepare-release`** skill at `.agents/skills/prepare-release/`. Run it via Claude Code (`/prepare-release`) when cutting a release; it only prepares the PR — publishing stays the manual `deploy-nuget.yml` trigger. diff --git a/CLAUDE.md b/CLAUDE.md index f6c62b6..d5b1709 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,12 +4,3 @@ project layout, build & test commands, code conventions, test rules, and the release process all live there. Read it before making changes — do not duplicate its content here. - -## Claude-specific notes - -- Quick start: `dotnet build OpenTelemetryExtension.slnx -c Release`, then - `dotnet test src/OpenTelemetryExtension.Configuration.Tests -c Release --filter "Category=Unit"`. -- GitHub Flow: branch off `main` (`feature/*` or `fix/*`) → PR → `main`; never - commit straight to `main`. Release branches (`release/*`) are skill-managed. -- Use the `/prepare-release` skill (`.claude/skills/prepare-release/`) for the - entire release workflow — never bump `` or publish manually. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ce9280e..05fb964 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -72,7 +72,7 @@ change. At release time the maintainer cuts the version and writes the notes; the `prepare-release` skill decides the SemVer bump (PATCH / MINOR / MAJOR) from the commits merged since the last release. -> **Maintainers:** the release-prep steps (version decision, dependency updates, build/test, smoke test, release notes, release PR) are automated by the `prepare-release` Claude Code skill in [`.claude/skills/prepare-release/`](./.claude/skills/prepare-release/). It prepares the PR only — the actual NuGet publish remains the manual **Deploy Nuget** workflow. +> **Maintainers:** the release-prep steps (version decision, dependency updates, build/test, smoke test, release notes, release PR) are automated by the `prepare-release` Claude Code skill in [`.agents/skills/prepare-release/`](./.agents/skills/prepare-release/). It prepares the PR only — the actual NuGet publish remains the manual **Deploy Nuget** workflow. ## Adding a New Instrumentation Option diff --git a/OpenTelemetryExtension.slnx b/OpenTelemetryExtension.slnx index fdccd2b..12fd273 100644 --- a/OpenTelemetryExtension.slnx +++ b/OpenTelemetryExtension.slnx @@ -1,14 +1,14 @@ - - - - + + + + - - + + - - + + @@ -47,6 +47,7 @@ + @@ -89,6 +90,7 @@ + diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..97a14dc --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,23 @@ +# Security Policy + +## Reporting a vulnerability + +Please report security vulnerabilities **privately** — do not open a public +issue or pull request for them. + +Use GitHub's private reporting flow: +[**Report a vulnerability**](https://github.com/thorstenalpers/OpenTelemetryExtension.Configuration/security/advisories/new). + +Please include enough detail to reproduce the issue (affected version, a minimal +repro or proof of concept, and the impact). You can expect an initial response +within a few days. Once a fix is available it will be released to NuGet and the +advisory published. + +## Supported versions + +Only the latest `2.x` release receives security fixes. + +| Version | Supported | +| ------- | --------- | +| 2.x | ✅ | +| < 2.0 | ❌ | From 86334cfe60bc8b2f99a5a22fd259ba4923ea3748 Mon Sep 17 00:00:00 2001 From: thorsten Date: Sat, 13 Jun 2026 18:17:12 +0200 Subject: [PATCH 7/8] docs: fix stale .claude script paths inside prepare-release SKILL.md --- .agents/skills/prepare-release/SKILL.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.agents/skills/prepare-release/SKILL.md b/.agents/skills/prepare-release/SKILL.md index 367f80c..04e7433 100644 --- a/.agents/skills/prepare-release/SKILL.md +++ b/.agents/skills/prepare-release/SKILL.md @@ -13,7 +13,7 @@ prepare the repository and open the PR. ## Workflow 1. **Check whether there is anything to release** - - Run the helper: `bash .claude/skills/prepare-release/scripts/check-otel-updates.sh` + - Run the helper: `bash .agents/skills/prepare-release/scripts/check-otel-updates.sh` - The helper only inspects the **shipped library project** (`src/OpenTelemetryExtension.Configuration/...csproj`). Dependency updates in the Sample or Tests projects are ignored — they are never published and must not trigger a new version. - Exit code **3** = nothing to release (no library dependency updates *and* no new commits since the last tag) → **stop**. - Exit code **0** = library dependency updates and/or new commits exist → continue. @@ -43,7 +43,7 @@ prepare the repository and open the PR. OpenObserve is used because it has a real query API, so the test can positively confirm ingested data. The helper starts OpenObserve via its Helm chart, runs the sample, generates traffic and queries the API for records: - - `bash .claude/skills/prepare-release/scripts/smoke-test.sh` + - `bash .agents/skills/prepare-release/scripts/smoke-test.sh` - Exit 0 = telemetry confirmed → continue. Non-zero = stop and report; do not release if telemetry does not arrive. @@ -51,7 +51,7 @@ prepare the repository and open the PR. 10. **Extend docs** — update `README.md` etc. for the changes/new dep versions. -11. **Release notes** — copy `.claude/skills/prepare-release/assets/release-notes.md` to +11. **Release notes** — copy `.agents/skills/prepare-release/assets/release-notes.md` to `release-notes/v.md`, fill in the `{{VERSION}}`/`{{DATE}}` placeholders and the **Added / Changed / Fixed / Removed** sections (omit empty ones). From ab9d09031a0dcff591da50ba430806f605858233 Mon Sep 17 00:00:00 2001 From: thorsten Date: Sat, 13 Jun 2026 18:43:31 +0200 Subject: [PATCH 8/8] sample: apply EF Core migrations on WebApi startup --- .../Program.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/OpenTelemetryExtension.Configuration.Sample.WebApi/Program.cs b/src/OpenTelemetryExtension.Configuration.Sample.WebApi/Program.cs index 3ee86ab..a640f14 100644 --- a/src/OpenTelemetryExtension.Configuration.Sample.WebApi/Program.cs +++ b/src/OpenTelemetryExtension.Configuration.Sample.WebApi/Program.cs @@ -33,6 +33,12 @@ public static void Main(string[] args) }); var app = builder.Build(); + + using (var scope = app.Services.CreateScope()) + { + scope.ServiceProvider.GetRequiredService().Database.Migrate(); + } + app.MapHealthChecks("/health"); app.UseSwagger(); app.UseSwaggerUI();