include::{mod-loc}shared/all-attributes.adoc[]

:_mod-docs-content-type: ASSEMBLY
[id="configuring-the-registry_{context}"]
= Configuring your {registry} deployment

[role="_abstract"]
You can set important configuration options for your {registry} deployment, including the {registry} web console, logging, health checks, and observability:

* xref:configuring-registry-ui_{context}[]
* xref:configuring-registry-observability_{context}[]
* xref:otel-features_{context}[]
* xref:otel-performance_{context}[]
* xref:configuring-liveness-readiness-probes_{context}[]
* xref:registry-liveness-env-vars_{context}[]

NOTE: For a list of all available configuration options, see {registry-config-reference}.


// proc-configuring-registry-ui
:_mod-docs-content-type: PROCEDURE
[id="configuring-registry-ui_{context}"]
== Configuring the {registry} web console

[role="_abstract"]
You can set optional environment variables to configure the {registry} web console specifically for your deployment environment or to customize its behavior.

.Prerequisites
* You have already installed {registry}.

.Procedure
. Set the `REGISTRY_API_URL` environment variable to override the default REST API URL. For example, `\https://registry-api.my-domain.com/apis/registry/v3`.
+
Typically the {operator} automatically configures the UI component with the REST API v3 URL. Override this value only if your deployment requires a custom URL.
. Set the `REGISTRY_FEATURE_READ_ONLY` environment variable to `true` to enable read-only mode. The default value is `false`.
+
In read-only mode, you cannot make changes to registered artifacts. For example, the following actions are unavailable:
+
* Creating a group
* Creating an artifact
* Uploading a new artifact version
* Updating artifact metadata
* Deleting an artifact


// ref-configuring-registry-observability
:_mod-docs-content-type: REFERENCE
[id="configuring-registry-observability_{context}"]
== {registry} observability with OpenTelemetry

[role="_abstract"]
You can configure {registry} to export telemetry data using OpenTelemetry (OTel) for comprehensive observability. This includes distributed tracing, metrics export by using the OTLP protocol, and log correlation with trace context.

{registry} is built with OpenTelemetry support and all telemetry signals (traces, metrics, logs) are enabled at build time. However, the OpenTelemetry SDK is disabled by default at runtime. When enabled, {registry} exports telemetry data to an OpenTelemetry-compatible collector such as Jaeger, Grafana Tempo, or the OpenTelemetry Collector.

IMPORTANT: The individual signal properties (`QUARKUS_OTEL_TRACES_ENABLED`, `QUARKUS_OTEL_METRICS_ENABLED`, `QUARKUS_OTEL_LOGS_ENABLED`) are build-time properties and cannot be changed at runtime. All signals are already enabled in the {registry} build. Use `QUARKUS_OTEL_SDK_DISABLED=false` to enable telemetry at runtime.

NOTE: Before you configure OpenTelemetry, ensure that you have installed {registry} and have an OpenTelemetry-compatible backend available, for example, Jaeger, Grafana Tempo, or OpenTelemetry Collector.

To enable OpenTelemetry observability, configure the following environment variables:

.Environment variables for enabling OpenTelemetry
[.table-expandable,width="100%",cols="4,6",options="header"]
|===
|Environment variable
|Description
|`QUARKUS_OTEL_SDK_DISABLED`
|Set to `false` to enable the OpenTelemetry SDK and all telemetry signals. Default is `true` (disabled).
|`QUARKUS_OTEL_EXPORTER_OTLP_ENDPOINT`
|The endpoint URL of your OpenTelemetry collector. For example, `http://jaeger:4317` for gRPC or `http://jaeger:4318` for HTTP.
|===

.Example: Enabling OpenTelemetry with Jaeger
[source,yaml]
----
environment:
  QUARKUS_OTEL_SDK_DISABLED: "false"
  QUARKUS_OTEL_EXPORTER_OTLP_ENDPOINT: "http://jaeger:4317"
----

In production environments, configure trace sampling to reduce processing overhead and control the volume of trace data:

.Environment variables for trace sampling
[.table-expandable,width="100%",cols="4,6",options="header"]
|===
|Environment variable
|Description
|`QUARKUS_OTEL_TRACES_SAMPLER`
|The sampling strategy. Use `parentbased_traceidratio` for production.
|`QUARKUS_OTEL_TRACES_SAMPLER_ARG`
|The sampling ratio (0.0 to 1.0). A value of `0.1` samples 10% of traces.
|===

.Example: Production sampling configuration (10% of traces)
[source,yaml]
----
environment:
  QUARKUS_OTEL_SDK_DISABLED: "false"
  QUARKUS_OTEL_EXPORTER_OTLP_ENDPOINT: "http://otel-collector:4317"
  QUARKUS_OTEL_TRACES_SAMPLER: "parentbased_traceidratio"
  QUARKUS_OTEL_TRACES_SAMPLER_ARG: "0.1"
----

When you use JSON logging format, {registry} automatically includes trace context (trace ID and span ID) in log entries. You can then correlate logs and traces.

.Example: Enabling structured logging with trace context
[source,yaml]
----
environment:
  QUARKUS_OTEL_TRACES_ENABLED: "true"
  QUARKUS_LOG_CONSOLE_JSON: "true"
----


// con-otel-features
:_mod-docs-content-type: CONCEPT
[id="otel-features_{context}"]
== OpenTelemetry features in {registry}

[role="_abstract"]
When OpenTelemetry is enabled, {registry} provides several observability features that are fully compatible with your existing monitoring setup.

* *Distributed tracing*: All REST API requests are automatically traced with spans containing request details, path parameters, and Apicurio-specific attributes such as `groupId`, `artifactId`, and `version`.

* *Storage layer tracing*: All storage operations create child spans. You can trace the complete request flow from REST API to database.

* *Kafka tracing*: When using KafkaSQL storage, Kafka operations are automatically traced with context propagation.

* *Custom metrics*: OpenTelemetry metrics for artifact operations, schema validations, and search requests are exported alongside existing Prometheus metrics.

* *Log correlation*: When JSON logging is enabled, trace context is automatically injected into log entries for correlation.

Existing monitoring endpoints continue to function:

* The Prometheus metrics endpoint is available at `/metrics` on the management port (default 9000).
* Health check endpoints (`/health/ready`, `/health/live`) are served on the management port (default 9000).
* All existing Micrometer-based metrics continue to function.


// ref-otel-performance
:_mod-docs-content-type: REFERENCE
[id="otel-performance_{context}"]
== OpenTelemetry performance impact

[role="_abstract"]
OpenTelemetry instrumentation adds a small performance overhead. The following table shows the measured impact when all telemetry signals are enabled with 100% sampling:

.Performance impact with OpenTelemetry enabled (100% sampling)
[.table-expandable,width="100%",cols="3,2,2,2",options="header"]
|===
|Operation
|Latency increase
|Throughput decrease
|Impact level

|System Info
|+9% (+0.35ms)
|-7%
|Low

|Create Artifact
|+4% (+0.13ms)
|-1%
|Minimal

|Get Artifact
|+5% (+0.05ms)
|-6%
|Minimal

|Search Artifacts
|+1% (+0.04ms)
|-1%
|Minimal

|List Groups
|+6% (+0.16ms)
|-5%
|Low
|===

*Key findings:*

* Average overhead is approximately 4-6% in throughput with 100% trace sampling.
* With the recommended 10% sampling ratio (`QUARKUS_OTEL_TRACES_SAMPLER_ARG=0.1`), the overhead drops to less than 1%.
* OpenTelemetry signals are disabled by default to avoid any overhead for users who do not require observability features.

ifndef::service-registry-downstream[]
To reproduce these benchmarks, run the following commands from the project root:

[source,shell]
----
# Build the project
./mvnw clean install -DskipTests

# Run benchmark with OTEL disabled (baseline)
./mvnw test -pl app -Dtest=OpenTelemetryPerformanceTest \
    -DOpenTelemetryPerformanceTest=enabled

# Run benchmark with OTEL enabled
./mvnw test -pl app -Dtest=OpenTelemetryPerformanceEnabledTest \
    -DOpenTelemetryPerformanceTest=enabled
----
endif::[]

[role="_additional-resources"]
.Additional resources
* link:https://opentelemetry.io/docs/[OpenTelemetry Documentation]
* link:https://quarkus.io/guides/opentelemetry[Quarkus OpenTelemetry Guide]
* link:https://www.jaegertracing.io/docs/[Jaeger Documentation]


// proc-configuring-liveness-readiness-probes
:_mod-docs-content-type: PROCEDURE
[id="configuring-liveness-readiness-probes_{context}"]
== Configuring {registry} health checks on OpenShift

[role="_abstract"]
Health check endpoints are served on the management interface (port 9000 by default), separate from the main application port (8080). Configure liveness and readiness probes to target port 9000.

You can configure optional environment variables for liveness and readiness probes to monitor the health of the {registry} server on OpenShift:

* _Liveness probes_ test if the application can make progress. If the application cannot make progress, OpenShift automatically restarts the failing Pod.

* _Readiness probes_ test if the application is ready to process requests. If the application is not ready, it can become overwhelmed by requests, and OpenShift stops sending requests for the time that the probe fails. If other Pods are OK, they continue to receive requests.

IMPORTANT: The default values of the liveness and readiness environment variables are designed for most cases. Change these values only if required by your environment. Any changes to the defaults depend on your hardware, network, and amount of data stored. Keep these values as low as possible to avoid unnecessary processing overhead.

.Prerequisites
* You must have an OpenShift cluster with cluster administrator access.
* You must have already installed {registry} on OpenShift.
* You must have already installed and configured your chosen {registry} storage in either {kafka-streams} or PostgreSQL.

.Procedure

. In the OpenShift Container Platform web console, log in using an account with cluster administrator privileges.

. Click *Installed Operators* > *{registry}*.

. On the *ApicurioRegistry* tab, click the Operator custom resource for your deployment, for example, *example-apicurioregistry*.

. In the main overview page, find the *Deployment Name* section and the corresponding `DeploymentConfig` name for your {registry} deployment, for example, *example-apicurioregistry*.

. In the left navigation menu, click *Workloads* > *Deployment Configs*, and select your `DeploymentConfig` name.

. Click the *Environment* tab, and enter your environment variables in the *Single values env* section, for example:
** *NAME*: `LIVENESS_STATUS_RESET`
** *VALUE*: `350`

. Click *Save* at the bottom.
+
Alternatively, you can complete these steps by using the OpenShift `oc` command. For more details, see the link:https://docs.openshift.com/container-platform/{registry-ocp-version}/cli_reference/openshift_cli/getting-started-cli.html[OpenShift CLI documentation].

[role="_additional-resources"]
.Additional resources
* xref:registry-liveness-env-vars_{context}[]
* link:https://docs.openshift.com/container-platform/{registry-ocp-version}/applications/application-health.html[OpenShift documentation on monitoring application health]


// ref-registry-liveness-env-vars
:_mod-docs-content-type: REFERENCE
[id="registry-liveness-env-vars_{context}"]
== Environment variables for {registry} health checks

[role="_abstract"]
You can use the following environment variables to configure {registry} health checks on OpenShift. These variables control liveness and readiness probes that monitor the health of the {registry} server. For an example procedure, see xref:configuring-liveness-readiness-probes_{context}[].

IMPORTANT: The following environment variables are provided for reference only. The default values are designed for most cases. Change these values only if required by your environment. Any changes to the defaults depend on your hardware, network, and amount of data stored. Keep these values as low as possible to avoid unnecessary processing overhead.

.Environment variables for {registry} liveness probes
//[%header,cols="5,5,2,5"]
[.table-expandable,width="100%",cols="5,5,2,5",options="header"]
|===
|Name
|Description
|Type
|Default
|`LIVENESS_ERROR_THRESHOLD`
|Number of liveness issues or errors that can occur before the liveness probe fails.
|Integer
|`1`
|`LIVENESS_COUNTER_RESET`
|Period in which the threshold number of errors must occur. For example, if this value is 60 and the threshold is 1, the check fails after two errors occur in 1 minute.
|Seconds
|`60`
|`LIVENESS_STATUS_RESET`
|Number of seconds that must elapse without any more errors for the liveness probe to reset to OK status.
|Seconds
|`300`
|`LIVENESS_ERRORS_IGNORED`
|Comma-separated list of ignored liveness exceptions.
|String
|`io.grpc.StatusRuntimeException,org.apache.kafka.streams.errors.InvalidStateStoreException`
|===

NOTE: Because OpenShift automatically restarts a Pod that fails a liveness check, the liveness settings, unlike readiness settings, do not directly affect behavior of {registry} on OpenShift.

.Environment variables for {registry} readiness probes
//[%header,cols="4,5,2,2"]
[.table-expandable,width="100%",cols="4,5,2,2",options="header"]
|===
|Name
|Description
|Type
|Default
|`READINESS_ERROR_THRESHOLD`
|Number of readiness issues or errors that can occur before the readiness probe fails.
|Integer
|`1`
|`READINESS_COUNTER_RESET`
|Period in which the threshold number of errors must occur. For example, if this value is 60 and the threshold is 1, the check fails after two errors occur in 1 minute.
|Seconds
|`60`
|`READINESS_STATUS_RESET`
|Number of seconds that must elapse without any more errors for the readiness probe to reset to OK status. This value determines how long the Pod remains not ready before it returns to normal operation.
|Seconds
|`300`
|`READINESS_TIMEOUT`
a|Readiness tracks the timeout of two operations:

* How long it takes for storage requests to complete
* How long it takes for HTTP REST API requests to return a response

If either operation exceeds the configured timeout, {registry} reports a readiness issue or error. This value controls the timeouts for both operations.
|Seconds
|`5`
|===


[role="_additional-resources"]
.Additional resources
* xref:configuring-liveness-readiness-probes_{context}[]
* link:https://docs.openshift.com/container-platform/{registry-ocp-version}/applications/application-health.html[OpenShift documentation on monitoring application health]
