-
Notifications
You must be signed in to change notification settings - Fork 25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
chore: support OpenTelemetry metrics #1465
Changes from all commits
7c32521
6b1fbf9
7fa50c8
7e5536d
58e7193
fc9419c
14a82f0
68b244d
1e04b21
0c8347d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
@@ -1,7 +1,8 @@ | ||||||||||
# Open Telemetry in PGAdapter | ||||||||||
# OpenTelemetry in PGAdapter | ||||||||||
|
||||||||||
PGAdapter supports Open Telemetry tracing. You can enable this by adding the `-enable_otel` command | ||||||||||
line argument when starting PGAdapter. | ||||||||||
PGAdapter supports OpenTelemetry tracing and metrics. You can enable the tracing or the metrics | ||||||||||
by adding the `-enable_otel` or `-enable_otel_metrics` command line argument when starting | ||||||||||
PGAdapter. Tracing and metrics can be enabled at the same time. | ||||||||||
|
||||||||||
Optionally, you can also set a trace sample ratio to limit the number of traces that will be | ||||||||||
collected and set with the `-otel_trace_ratio=<ratio>` command line argument. If you omit this | ||||||||||
|
@@ -16,7 +17,8 @@ docker run \ | |||||||||
gcr.io/cloud-spanner-pg-adapter/pgadapter \ | ||||||||||
-p my-project -i my-instance \ | ||||||||||
-c /credentials.json -x \ | ||||||||||
-enable_otel -otel_trace_ratio=0.1 | ||||||||||
-enable_otel -otel_trace_ratio=0.1 \ | ||||||||||
-enable_otel_metrics | ||||||||||
``` | ||||||||||
|
||||||||||
## Exporter | ||||||||||
|
@@ -144,6 +146,15 @@ statements consists of the following spans: | |||||||||
|
||||||||||
![PGAdapter Cloud Trace - Batch DML example](img/dml_batch_trace_sample.png?raw=true "PGAdapter Cloud Trace - Batch DML example") | ||||||||||
|
||||||||||
## Metrics | ||||||||||
|
||||||||||
The available metrics in PGAdapter are: | ||||||||||
|
||||||||||
* `spanner/pgadapter/roundtrip_latencies`: Latency between PGAdapter receiving a statement from | ||||||||||
the client and PGAdapter returning the last row of the response to the client. | ||||||||||
* `spanner/pgadapter/client_lib_latencies`: Latency when the Spanner's client library receives | ||||||||||
a call and returns a response. | ||||||||||
|
||||||||||
Comment on lines
+155
to
+156
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
## Frequently Asked Questions | ||||||||||
|
||||||||||
#### How can I find all the statements that were executed on the same connection as the trace I'm looking at? | ||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,8 @@ | |
package com.google.cloud.spanner.pgadapter; | ||
|
||
import com.google.auth.Credentials; | ||
import com.google.cloud.opentelemetry.metric.GoogleCloudMetricExporter; | ||
import com.google.cloud.opentelemetry.metric.MetricConfiguration; | ||
import com.google.cloud.opentelemetry.trace.TraceConfiguration; | ||
import com.google.cloud.opentelemetry.trace.TraceExporter; | ||
import com.google.cloud.spanner.pgadapter.metadata.OptionsMetadata; | ||
|
@@ -23,6 +25,9 @@ | |
import com.google.devtools.cloudtrace.v2.TruncatableString; | ||
import io.opentelemetry.api.OpenTelemetry; | ||
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; | ||
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdkBuilder; | ||
import io.opentelemetry.sdk.metrics.export.MetricExporter; | ||
import io.opentelemetry.sdk.metrics.export.PeriodicMetricReader; | ||
import io.opentelemetry.sdk.trace.export.BatchSpanProcessor; | ||
import io.opentelemetry.sdk.trace.export.SpanExporter; | ||
import io.opentelemetry.sdk.trace.samplers.Sampler; | ||
|
@@ -56,7 +61,8 @@ public static void main(String[] args) { | |
|
||
/** Creates an {@link OpenTelemetry} object from the given options. */ | ||
static OpenTelemetry setupOpenTelemetry(OptionsMetadata optionsMetadata) { | ||
if (!optionsMetadata.isEnableOpenTelemetry()) { | ||
if (!optionsMetadata.isEnableOpenTelemetry() | ||
&& !optionsMetadata.isEnableOpenTelemetryMetrics()) { | ||
return OpenTelemetry.noop(); | ||
} | ||
|
||
|
@@ -73,45 +79,62 @@ static OpenTelemetry setupOpenTelemetry(OptionsMetadata optionsMetadata) { | |
System.setProperty("otel.service.name", "pgadapter"); | ||
} | ||
|
||
TraceConfiguration.Builder builder = | ||
TraceConfiguration.builder().setDeadline(Duration.ofSeconds(60L)); | ||
String projectId = optionsMetadata.getTelemetryProjectId(); | ||
if (projectId != null) { | ||
builder.setProjectId(projectId); | ||
} | ||
try { | ||
String projectId = optionsMetadata.getTelemetryProjectId(); | ||
Credentials credentials = optionsMetadata.getTelemetryCredentials(); | ||
if (credentials != null) { | ||
builder.setCredentials(credentials); | ||
AutoConfiguredOpenTelemetrySdkBuilder openTelemetryBuilder = | ||
AutoConfiguredOpenTelemetrySdk.builder(); | ||
if (optionsMetadata.isEnableOpenTelemetry()) { | ||
TraceConfiguration.Builder builder = | ||
TraceConfiguration.builder().setDeadline(Duration.ofSeconds(60L)); | ||
if (projectId != null) { | ||
builder.setProjectId(projectId); | ||
} | ||
if (credentials != null) { | ||
builder.setCredentials(credentials); | ||
} | ||
builder.setFixedAttributes( | ||
ImmutableMap.of( | ||
"service.name", | ||
AttributeValue.newBuilder() | ||
.setStringValue( | ||
TruncatableString.newBuilder() | ||
.setValue( | ||
Objects.requireNonNull( | ||
getOpenTelemetrySetting("otel.service.name"))) | ||
.build()) | ||
.build())); | ||
TraceConfiguration configuration = builder.build(); | ||
SpanExporter traceExporter = TraceExporter.createWithConfiguration(configuration); | ||
Sampler sampler; | ||
if (optionsMetadata.getOpenTelemetryTraceRatio() == null) { | ||
sampler = Sampler.parentBased(Sampler.traceIdRatioBased(0.05d)); | ||
} else { | ||
sampler = | ||
Sampler.parentBased( | ||
Sampler.traceIdRatioBased(optionsMetadata.getOpenTelemetryTraceRatio())); | ||
} | ||
openTelemetryBuilder.addTracerProviderCustomizer( | ||
(sdkTracerProviderBuilder, configProperties) -> | ||
sdkTracerProviderBuilder | ||
.setSampler(sampler) | ||
.addSpanProcessor(BatchSpanProcessor.builder(traceExporter).build())); | ||
} | ||
builder.setFixedAttributes( | ||
ImmutableMap.of( | ||
"service.name", | ||
AttributeValue.newBuilder() | ||
.setStringValue( | ||
TruncatableString.newBuilder() | ||
.setValue( | ||
Objects.requireNonNull(getOpenTelemetrySetting("otel.service.name"))) | ||
.build()) | ||
.build())); | ||
TraceConfiguration configuration = builder.build(); | ||
SpanExporter traceExporter = TraceExporter.createWithConfiguration(configuration); | ||
Sampler sampler; | ||
if (optionsMetadata.getOpenTelemetryTraceRatio() == null) { | ||
sampler = Sampler.parentBased(Sampler.traceIdRatioBased(0.05d)); | ||
} else { | ||
sampler = | ||
Sampler.parentBased( | ||
Sampler.traceIdRatioBased(optionsMetadata.getOpenTelemetryTraceRatio())); | ||
if (optionsMetadata.isEnableOpenTelemetryMetrics()) { | ||
MetricExporter cloudMonitoringExporter = | ||
GoogleCloudMetricExporter.createWithConfiguration( | ||
MetricConfiguration.builder() | ||
// Configure the cloud project id. | ||
.setProjectId(projectId) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This needs a null check, as
|
||
// Set the credentials to use when writing to the Cloud Monitoring API | ||
.setCredentials(credentials) | ||
.build()); | ||
openTelemetryBuilder.addMeterProviderCustomizer( | ||
(sdkMeterProviderBuilder, configProperties) -> | ||
sdkMeterProviderBuilder.registerMetricReader( | ||
PeriodicMetricReader.builder(cloudMonitoringExporter).build())); | ||
} | ||
return AutoConfiguredOpenTelemetrySdk.builder() | ||
.addTracerProviderCustomizer( | ||
(sdkTracerProviderBuilder, configProperties) -> | ||
sdkTracerProviderBuilder | ||
.setSampler(sampler) | ||
.addSpanProcessor(BatchSpanProcessor.builder(traceExporter).build())) | ||
.build() | ||
.getOpenTelemetrySdk(); | ||
return openTelemetryBuilder.build().getOpenTelemetrySdk(); | ||
} catch (IOException exception) { | ||
throw new RuntimeException(exception); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: