Add Additional Resource Attributes for OpenTelemetry

Adds the "deployment.environment" resource attribute to those that can
be configured for OpenTelemetry. This was done as some collectors,
including Datadog, require this value to properly classify traces.

Note: the "deployment.environment" attribute is being deprecated in
future versions of the OTel schemas and this may need to be
updated when that library is upgraded.

Fixes #7322

Signed-off-by: Brian Cullen <brianc@kahoot.com>
This commit is contained in:
Brian Cullen
2025-01-28 12:57:19 +01:00
committed by Ashutosh Narkar
parent 6483e7a6a9
commit 08f98e9527
3 changed files with 58 additions and 25 deletions
+16 -14
View File
@@ -88,6 +88,7 @@ distributed_tracing:
service_namespace: "my-namespace"
service_version: "1.1"
service_instance_id: "1"
deployment_environment: "prod"
server:
decoding:
@@ -876,20 +877,21 @@ respectively, and the `json.schema_match` built-in function for compiled JSON sc
Distributed tracing represents the configuration of the OpenTelemetry Tracing.
| Field | Type | Required | Description |
|----------------------------------------------------|----------| --- |------------------------------------------------------------------------------------|
| `distributed_tracing.type` | `string` | No | Setting this to "grpc" enables distributed tracing with an collector gRPC endpoint |
| `distributed_tracing.address` | `string` | No (default: `localhost:4317`) | Address of the OpenTelemetry Collector gRPC endpoint. |
| `distributed_tracing.service_name` | `string` | No (default: `opa`) | Logical name of the service. |
| `distributed_tracing.sample_percentage` | `int` | No (default: `100`) | Percentage of traces that are sampled and exported. |
| `distributed_tracing.encryption` | `string` | No (default: `off`) | Configures TLS. |
| `distributed_tracing.allow_insecure_tls` | `bool` | No (default: `false`) | Allow insecure TLS. |
| `distributed_tracing.tls_ca_cert_file` | `string` | No | The path to the root CA certificate. |
| `distributed_tracing.tls_cert_file` | `string` | No (unless `encryption` equals `mtls`) | The path to the client certificate to authenticate with. |
| `distributed_tracing.tls_private_key_file` | `string` | No (unless `tls_cert_file` provided) | The path to the private key of the client certificate. |
| `distributed_tracing.resource.service_version` | `string` | No | Service version |
| `distributed_tracing.resource.service_instance_id` | `string` | No | Service instance id |
| `distributed_tracing.resource.service_namespace` | `string` | No | Service namespace |
| Field | Type | Required | Description |
|-------------------------------------------------------|----------|----------------------------------------|------------------------------------------------------------------------------------|
| `distributed_tracing.type` | `string` | No | Setting this to "grpc" enables distributed tracing with an collector gRPC endpoint |
| `distributed_tracing.address` | `string` | No (default: `localhost:4317`) | Address of the OpenTelemetry Collector gRPC endpoint. |
| `distributed_tracing.service_name` | `string` | No (default: `opa`) | Logical name of the service. |
| `distributed_tracing.sample_percentage` | `int` | No (default: `100`) | Percentage of traces that are sampled and exported. |
| `distributed_tracing.encryption` | `string` | No (default: `off`) | Configures TLS. |
| `distributed_tracing.allow_insecure_tls` | `bool` | No (default: `false`) | Allow insecure TLS. |
| `distributed_tracing.tls_ca_cert_file` | `string` | No | The path to the root CA certificate. |
| `distributed_tracing.tls_cert_file` | `string` | No (unless `encryption` equals `mtls`) | The path to the client certificate to authenticate with. |
| `distributed_tracing.tls_private_key_file` | `string` | No (unless `tls_cert_file` provided) | The path to the private key of the client certificate. |
| `distributed_tracing.resource.service_version` | `string` | No | Service version |
| `distributed_tracing.resource.service_instance_id` | `string` | No | Service instance id |
| `distributed_tracing.resource.service_namespace` | `string` | No | Service namespace |
| `distributed_tracing.resource.deployment_environment` | `string` | No | Deployment environment name |
The following encryption methods are supported:
@@ -55,9 +55,10 @@ func isSupportedSampleRatePercentage(sampleRate int) bool {
}
type resourceConfig struct {
ServiceVersion string `json:"service_version,omitempty"`
ServiceInstanceID string `json:"service_instance_id,omitempty"`
ServiceNamespace string `json:"service_namespace,omitempty"`
ServiceVersion string `json:"service_version,omitempty"`
ServiceInstanceID string `json:"service_instance_id,omitempty"`
ServiceNamespace string `json:"service_namespace,omitempty"`
DeploymentEnvironment string `json:"deployment_environment,omitempty"`
}
type distributedTracingConfig struct {
@@ -117,6 +118,13 @@ func Init(ctx context.Context, raw []byte, id string) (*otlptrace.Exporter, *tra
if distributedTracingConfig.Resource.ServiceNamespace != "" {
resourceAttributes = append(resourceAttributes, semconv.ServiceNamespaceKey.String(distributedTracingConfig.Resource.ServiceNamespace))
}
// NOTE: this is currently using the `deployment.environment` setting which is being deprecated
// in favour of `deployment.environment.name` in future versions of the OpenTelemetry schema.
// This will need to be taken into account when upgrading the library version in the future.
if distributedTracingConfig.Resource.DeploymentEnvironment != "" {
resourceAttributes = append(resourceAttributes, semconv.DeploymentEnvironmentKey.String(distributedTracingConfig.Resource.DeploymentEnvironment))
}
res, err := resource.New(ctx,
resource.WithAttributes(
semconv.ServiceNameKey.String(distributedTracingConfig.ServiceName),
+31 -8
View File
@@ -37,6 +37,9 @@ import (
"testing"
"time"
"go.opentelemetry.io/otel/attribute"
semconv "go.opentelemetry.io/otel/semconv/v1.7.0"
"github.com/gorilla/mux"
"github.com/open-policy-agent/opa/internal/distributedtracing"
@@ -5857,15 +5860,28 @@ func TestDistributedTracingEnabled(t *testing.T) {
func TestDistributedTracingResourceAttributes(t *testing.T) {
t.Parallel()
c := []byte(`{"distributed_tracing": {
attributes := map[attribute.Key]string{
semconv.DeploymentEnvironmentKey: "prod",
semconv.ServiceNameKey: "my-service",
semconv.ServiceVersionKey: "1.0",
semconv.ServiceNamespaceKey: "my-namespace",
semconv.ServiceInstanceIDKey: "1",
}
c := []byte(fmt.Sprintf(`{"distributed_tracing": {
"type": "grpc",
"service_name": "my-service",
"service_name": "%s",
"resource": {
"service_namespace": "my-namespace",
"service_version": "1.0",
"service_instance_id": "1"
"service_namespace": "%s",
"service_version": "%s",
"service_instance_id": "%s",
"deployment_environment": "%s"
}
}}`)
}}`, attributes[semconv.ServiceNameKey],
attributes[semconv.ServiceNamespaceKey],
attributes[semconv.ServiceVersionKey],
attributes[semconv.ServiceInstanceIDKey],
attributes[semconv.DeploymentEnvironmentKey]))
ctx := context.Background()
_, traceProvider, resource, err := distributedtracing.Init(ctx, c, "foo")
@@ -5878,9 +5894,16 @@ func TestDistributedTracingResourceAttributes(t *testing.T) {
if resource == nil {
t.Fatalf("Resource was not initialized")
}
if len(resource.Attributes()) != 4 {
t.Fatalf("Unexpected resource attributes count. Expected: %v, Got: %v", 4, len(resource.Attributes()))
if len(resource.Attributes()) != 5 {
t.Fatalf("Unexpected resource attributes count. Expected: %v, Got: %v", 5, len(resource.Attributes()))
}
for _, value := range resource.Attributes() {
if attribute.StringValue(attributes[value.Key]) != value.Value {
t.Fatalf("Unexpected resource attribute. Expected: %v, Got: %v", attributes[value.Key], value)
}
}
}
func TestCertPoolReloading(t *testing.T) {