mirror of
https://github.com/signalapp/Signal-Server
synced 2026-04-20 00:08:04 +01:00
add OTLP logging appender factory
This commit is contained in:
committed by
GitHub
parent
f80e30f9f2
commit
007dde8d45
@@ -385,6 +385,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
|
||||
dynamicConfigurationManager.start();
|
||||
|
||||
MetricsUtil.configureRegistries(config, environment, dynamicConfigurationManager);
|
||||
MetricsUtil.configureLogging(config, environment);
|
||||
|
||||
ExperimentEnrollmentManager experimentEnrollmentManager = new ExperimentEnrollmentManager(dynamicConfigurationManager);
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ package org.whispersystems.textsecuregcm.metrics;
|
||||
import com.codahale.metrics.SharedMetricRegistries;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import io.dropwizard.core.setup.Environment;
|
||||
import io.dropwizard.lifecycle.Managed;
|
||||
import io.micrometer.core.instrument.Meter;
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.core.instrument.Metrics;
|
||||
@@ -21,6 +22,14 @@ import io.micrometer.core.instrument.config.MeterFilter;
|
||||
import io.micrometer.core.instrument.distribution.DistributionStatisticConfig;
|
||||
import io.micrometer.registry.otlp.OtlpMeterRegistry;
|
||||
import io.micrometer.statsd.StatsdMeterRegistry;
|
||||
import io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporter;
|
||||
import io.opentelemetry.instrumentation.logback.appender.v1_0.OpenTelemetryAppender;
|
||||
import io.opentelemetry.sdk.OpenTelemetrySdk;
|
||||
import io.opentelemetry.sdk.logs.SdkLoggerProvider;
|
||||
import io.opentelemetry.sdk.logs.export.BatchLogRecordProcessor;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import io.opentelemetry.semconv.ServiceAttributes;
|
||||
|
||||
import java.time.Duration;
|
||||
import org.whispersystems.textsecuregcm.WhisperServerConfiguration;
|
||||
import org.whispersystems.textsecuregcm.WhisperServerVersion;
|
||||
@@ -99,6 +108,34 @@ public class MetricsUtil {
|
||||
new MicrometerRegistryManager(Metrics.globalRegistry, shutdownWaitDuration));
|
||||
}
|
||||
|
||||
public static void configureLogging(final WhisperServerConfiguration config, final Environment environment) {
|
||||
if (!config.getOpenTelemetryConfiguration().enabled()) {
|
||||
return;
|
||||
}
|
||||
final OpenTelemetrySdk openTelemetry =
|
||||
OpenTelemetrySdk.builder()
|
||||
.setLoggerProvider(
|
||||
SdkLoggerProvider.builder()
|
||||
.setResource(
|
||||
Resource.builder()
|
||||
.put(ServiceAttributes.SERVICE_NAME, "chat")
|
||||
.put(ServiceAttributes.SERVICE_VERSION, WhisperServerVersion.getServerVersion())
|
||||
.build())
|
||||
.addLogRecordProcessor(
|
||||
BatchLogRecordProcessor.builder(OtlpHttpLogRecordExporter.getDefault()).build())
|
||||
.build())
|
||||
.build();
|
||||
|
||||
OpenTelemetryAppender.install(openTelemetry);
|
||||
|
||||
environment.lifecycle().manage(new Managed() {
|
||||
@Override
|
||||
public void stop() {
|
||||
openTelemetry.shutdown();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static void configureMeterFilters(MeterRegistry.Config config,
|
||||
final DynamicConfigurationManager<DynamicConfiguration> dynamicConfigurationManager) {
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2025 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.metrics;
|
||||
|
||||
import ch.qos.logback.classic.LoggerContext;
|
||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||
import ch.qos.logback.core.Appender;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import io.dropwizard.logging.common.AbstractAppenderFactory;
|
||||
import io.dropwizard.logging.common.async.AsyncAppenderFactory;
|
||||
import io.dropwizard.logging.common.filter.LevelFilterFactory;
|
||||
import io.dropwizard.logging.common.layout.LayoutFactory;
|
||||
import io.opentelemetry.instrumentation.logback.appender.v1_0.OpenTelemetryAppender;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
|
||||
@JsonTypeName("otlp")
|
||||
public class OpenTelemetryAppenderFactory extends AbstractAppenderFactory<ILoggingEvent> {
|
||||
|
||||
@JsonProperty
|
||||
private String destination;
|
||||
|
||||
@Override
|
||||
public Appender<ILoggingEvent> build(
|
||||
final LoggerContext context,
|
||||
final String applicationName,
|
||||
final LayoutFactory<ILoggingEvent> layoutFactory,
|
||||
final LevelFilterFactory<ILoggingEvent> levelFilterFactory,
|
||||
final AsyncAppenderFactory<ILoggingEvent> asyncAppenderFactory) {
|
||||
|
||||
final OpenTelemetryAppender appender = new OpenTelemetryAppender();
|
||||
appender.setCaptureCodeAttributes(true);
|
||||
appender.setCaptureLoggerContext(true);
|
||||
|
||||
// The installation of an OpenTelemetry configuration happens in
|
||||
// WhisperServerService (or CommandDependencies), in order to let us tie
|
||||
// into Dropwizard's lifecycle management; this allows us to buffer any
|
||||
// logs emitted between now and that happening.
|
||||
appender.setNumLogsCapturedBeforeOtelInstall(1000);
|
||||
|
||||
appender.addFilter(levelFilterFactory.build(threshold));
|
||||
getFilterFactories().forEach(f -> appender.addFilter(f.build()));
|
||||
appender.start();
|
||||
|
||||
return wrapAsync(appender, asyncAppenderFactory);
|
||||
}
|
||||
}
|
||||
@@ -45,6 +45,7 @@ import org.whispersystems.textsecuregcm.experiment.ExperimentEnrollmentManager;
|
||||
import org.whispersystems.textsecuregcm.experiment.PushNotificationExperimentSamples;
|
||||
import org.whispersystems.textsecuregcm.grpc.net.GrpcClientConnectionManager;
|
||||
import org.whispersystems.textsecuregcm.limits.RateLimiters;
|
||||
import org.whispersystems.textsecuregcm.metrics.MetricsUtil;
|
||||
import org.whispersystems.textsecuregcm.metrics.MicrometerAwsSdkMetricPublisher;
|
||||
import org.whispersystems.textsecuregcm.push.APNSender;
|
||||
import org.whispersystems.textsecuregcm.push.FcmSender;
|
||||
@@ -127,6 +128,8 @@ record CommandDependencies(
|
||||
throws IOException, GeneralSecurityException, InvalidInputException {
|
||||
Clock clock = Clock.systemUTC();
|
||||
|
||||
MetricsUtil.configureLogging(configuration, environment);
|
||||
|
||||
environment.getObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
|
||||
final AwsCredentialsProvider awsCredentialsProvider = configuration.getAwsCredentialsConfiguration().build();
|
||||
|
||||
Reference in New Issue
Block a user