diff --git a/app/client/packages/rts/src/instrumentation.ts b/app/client/packages/rts/src/instrumentation.ts index 083c5ca6663d..24d40d408f98 100644 --- a/app/client/packages/rts/src/instrumentation.ts +++ b/app/client/packages/rts/src/instrumentation.ts @@ -16,7 +16,7 @@ const provider = new NodeTracerProvider({ resource: new Resource({ [ATTR_DEPLOYMENT_NAME]: `${process.env.APPSMITH_DEPLOYMENT_NAME || "self-hosted"}`, [ATTR_SERVICE_INSTANCE_ID]: `${process.env.HOSTNAME || "appsmith-0"}`, - [ATTR_SERVICE_NAME]: "rts", + [ATTR_SERVICE_NAME]: "appsmith-rts", }), }); diff --git a/app/client/src/ce/configs/index.ts b/app/client/src/ce/configs/index.ts index b29d56ee4231..62cd798fb269 100644 --- a/app/client/src/ce/configs/index.ts +++ b/app/client/src/ce/configs/index.ts @@ -283,7 +283,7 @@ export const getAppsmithConfigs = (): AppsmithUIConfigs => { observability: { deploymentName: observabilityDeploymentName.value, serviceInstanceId: observabilityServiceInstanceId.value, - serviceName: "frontend", + serviceName: "appsmith-client", }, fusioncharts: { enabled: fusioncharts.enabled, diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/constants/MDCConstants.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/constants/MDCConstants.java index 2f78969b21d3..375c429c0bac 100644 --- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/constants/MDCConstants.java +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/constants/MDCConstants.java @@ -7,5 +7,6 @@ public class MDCConstants { public static final String THREAD = "thread"; public static final String OBSERVATION = "micrometer.observation"; public static final String TRACE_ID = "traceId"; + public static final String TRACE_PARENT = "traceparent"; public static final String SPAN_ID = "spanId"; } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/annotations/ConditionalOnMicrometerMetricsEnabled.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/annotations/ConditionalOnMicrometerMetricsEnabled.java index 9627906664b7..adb895737897 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/annotations/ConditionalOnMicrometerMetricsEnabled.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/annotations/ConditionalOnMicrometerMetricsEnabled.java @@ -15,5 +15,5 @@ @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented -@ConditionalOnExpression("${appsmith.micrometer.metrics.enabled}") +@ConditionalOnExpression("${appsmith.observability.metrics.enabled}") public @interface ConditionalOnMicrometerMetricsEnabled {} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/CommonConfig.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/CommonConfig.java index 9ff767657283..00efcaa7626c 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/CommonConfig.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/CommonConfig.java @@ -64,13 +64,13 @@ public class CommonConfig { @Value("${disable.telemetry:true}") private boolean isTelemetryDisabled; - @Value("${appsmith.micrometer.tracing.detail.enabled:false}") + @Value("${appsmith.observability.tracing.detail.enabled:false}") private boolean tracingDetail; - @Value("${appsmith.micrometer.metrics.detail.enabled:false}") + @Value("${appsmith.observability.metrics.detail.enabled:false}") private boolean metricsDetail; - @Value("${appsmith.micrometer.metrics.interval.millis:60000}") + @Value("${appsmith.observability.metrics.interval.millis:60000}") private int metricsIntervalMillis; private List allowedDomains; diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/MetricsConfig.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/MetricsConfig.java index a4a6d1576ee8..a2664353746f 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/MetricsConfig.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/MetricsConfig.java @@ -33,20 +33,21 @@ public class MetricsConfig { public static final String NEW_RELIC_MICROMETER_METRICS_ENDPOINT = "https://otlp.nr-data.net:4317"; public static final String API_KEY = "api-key"; - public static final String CONTAINER_NAME_KEY = "container.name"; - + public static final String DEPLOYMENT_NAME_KEY = "deployment.name"; + public static final String SERVICE_INSTANCE_ID_KEY = "service.instance.id"; public static final String SERVICE_NAME_KEY = "service.name"; + public static final String SERVICE_NAME = "appsmith-server"; public static final String INSTRUMENTATION_PROVIDER_KEY = "instrumentation.provider"; public static final String MICROMETER = "micrometer"; - @Value("${appsmith.newrelic.micrometer.metrics.application.name}") - private String newRelicApplicationName; - @Value("${appsmith.newrelic.licensekey}") private String newRelicKey; - @Value("${appsmith.newrelic.micrometer.metrics.container.name}") - private String newRelicContainerName; + @Value("${appsmith.observability.deployment.name}") + private String deploymentName; + + @Value("${appsmith.observability.service.instance.id}") + private String serviceInstanceId; private final CommonConfig commonConfig; @@ -68,11 +69,12 @@ public OpenTelemetry openTelemetry() { return OpenTelemetrySdk.builder() .setMeterProvider(SdkMeterProvider.builder() .setResource(Resource.getDefault().toBuilder() - .put(SERVICE_NAME_KEY, newRelicApplicationName) + .put(DEPLOYMENT_NAME_KEY, deploymentName) + .put(SERVICE_NAME_KEY, SERVICE_NAME) // Include instrumentation.provider=micrometer to enable micrometer metrics // experience in New Relic .put(INSTRUMENTATION_PROVIDER_KEY, MICROMETER) - .put(CONTAINER_NAME_KEY, newRelicContainerName) + .put(SERVICE_INSTANCE_ID_KEY, serviceInstanceId) .build()) .registerMetricReader(PeriodicMetricReader.builder(OtlpGrpcMetricExporter.builder() .setEndpoint(NEW_RELIC_MICROMETER_METRICS_ENDPOINT) diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/MicrometerTraceHeaderWebFilter.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/MicrometerTraceHeaderWebFilter.java deleted file mode 100644 index 2f1e28a8c509..000000000000 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/MicrometerTraceHeaderWebFilter.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.appsmith.server.configurations; - -import org.springframework.core.Ordered; -import org.springframework.core.annotation.Order; -import org.springframework.http.HttpHeaders; -import org.springframework.http.server.reactive.ServerHttpRequest; -import org.springframework.stereotype.Component; -import org.springframework.web.server.ServerWebExchange; -import org.springframework.web.server.WebFilter; -import org.springframework.web.server.WebFilterChain; -import reactor.core.publisher.Mono; - -import static org.springframework.util.CollectionUtils.isEmpty; - -/** - * This webfilter copies the value of traceparent-otlp header into traceparent header. This is required because at - * the moment the client application has two different services that creates traces and sends to the NewRelic server - * - one that gathers web vitals information like LCP, FCP etc. and another one that creates user defined traces. They - * both have different traceparent header and hence to overcome this conflict of headers the client has copied the - * user defined trace header into traceparent-otlp. However, Micrometer expects the traceparent information to be - * present in the traceparent header - hence this method copies the correct header data into traceparent header - * before it gets set into Micrometer context. - * In cases where traceparent-otlp header is not present but the traceparent header is present, this method removes - * the traceparent header because if it is present then the Micrometer trace would use its value for trace id (which - * is incorrect). - * As per measurement on my local setup this webFilter generally takes around 0.5 milliseconds to complete hence should - * not have any practical impact on response times. - */ -@Order(Ordered.HIGHEST_PRECEDENCE) -@Component -public class MicrometerTraceHeaderWebFilter implements WebFilter { - - public static final String TRACEPARENT_OTLP_HEADER_KEY = "traceparent-otlp"; - public static final String TRACEPARENT_HEADER_KEY = "traceparent"; - - @Override - public Mono filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) { - HttpHeaders requestHeaders = serverWebExchange.getRequest().getHeaders(); - - if (isTraceparentOtlpHeaderPresent(requestHeaders)) { - ServerHttpRequest newRequest = serverWebExchange - .getRequest() - .mutate() - .header( - TRACEPARENT_HEADER_KEY, - requestHeaders.get(TRACEPARENT_OTLP_HEADER_KEY).get(0)) - .build(); - ServerWebExchange newExchange = - serverWebExchange.mutate().request(newRequest).build(); - - return webFilterChain.filter(newExchange); - } else if (isTraceparentHeaderPresent(requestHeaders)) { - ServerHttpRequest newRequest = serverWebExchange - .getRequest() - .mutate() - .headers((httpHeader) -> { - httpHeader.remove(TRACEPARENT_HEADER_KEY); - }) - .build(); - ServerWebExchange newExchange = - serverWebExchange.mutate().request(newRequest).build(); - - return webFilterChain.filter(newExchange); - } - - return webFilterChain.filter(serverWebExchange); - } - - private boolean isTraceparentHeaderPresent(HttpHeaders requestHeaders) { - return requestHeaders != null - && requestHeaders.containsKey(TRACEPARENT_HEADER_KEY) - && !isEmpty(requestHeaders.get(TRACEPARENT_HEADER_KEY)); - } - - private boolean isTraceparentOtlpHeaderPresent(HttpHeaders requestHeaders) { - return requestHeaders != null && requestHeaders.containsKey(TRACEPARENT_OTLP_HEADER_KEY); - } -} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/TracingConfig.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/TracingConfig.java index fc22c4af4790..2e4a1ef2254f 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/TracingConfig.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/TracingConfig.java @@ -3,16 +3,10 @@ import io.micrometer.observation.Observation; import io.micrometer.observation.ObservationPredicate; import io.micrometer.observation.ObservationView; -import io.micrometer.tracing.Span; -import io.micrometer.tracing.exporter.SpanExportingPredicate; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.server.reactive.observation.ServerRequestObservationContext; -import static com.appsmith.external.constants.spans.BaseSpan.APPSMITH_SPAN_PREFIX; -import static com.appsmith.external.constants.spans.BaseSpan.AUTHENTICATE; -import static com.appsmith.external.constants.spans.BaseSpan.AUTHORIZE; - /** * This configuration file creates beans that are required to filter just Appsmith specific spans */ @@ -42,19 +36,4 @@ ObservationPredicate noActuatorServerObservations() { } }; } - - @Bean - SpanExportingPredicate onlyAppsmithSpans() { - return (finishedSpan) -> { - if ((finishedSpan.getKind() != null && finishedSpan.getKind().equals(Span.Kind.SERVER)) - || finishedSpan.getName().startsWith(APPSMITH_SPAN_PREFIX) - || finishedSpan.getName().startsWith(AUTHENTICATE) - || finishedSpan.getName().startsWith(AUTHORIZE)) { - // A span is either an http server request root or Appsmith specific or login related or signup related - return true; - } else { - return false; - } - }; - } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/RTSCaller.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/RTSCaller.java index d14132a352e7..ff7f9ac934f1 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/RTSCaller.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/RTSCaller.java @@ -1,5 +1,6 @@ package com.appsmith.server.helpers; +import io.micrometer.observation.ObservationRegistry; import jakarta.annotation.PostConstruct; import lombok.NonNull; import org.springframework.beans.factory.annotation.Value; @@ -24,6 +25,8 @@ @Component public class RTSCaller { + private final ObservationRegistry observationRegistry; + private WebClient webClient; @Value("${appsmith.rts.port:}") @@ -31,6 +34,10 @@ public class RTSCaller { private static final int MAX_IN_MEMORY_SIZE_IN_BYTES = 16 * 1024 * 1024; + public RTSCaller(ObservationRegistry observationRegistry) { + this.observationRegistry = observationRegistry; + } + @PostConstruct private void makeWebClient() { if (isEmpty(rtsPort)) { @@ -53,6 +60,7 @@ private void makeWebClient() { .build()) .clientConnector(new ReactorClientHttpConnector(HttpClient.create(connectionProvider))) .baseUrl("http://127.0.0.1:" + rtsPort) + .observationRegistry(observationRegistry) .build(); } diff --git a/app/server/appsmith-server/src/main/resources/application.properties b/app/server/appsmith-server/src/main/resources/application.properties index 3db4bfbfa753..e1794aa238a3 100644 --- a/app/server/appsmith-server/src/main/resources/application.properties +++ b/app/server/appsmith-server/src/main/resources/application.properties @@ -1,3 +1,4 @@ +spring.application.name=appsmith-server server.port=${PORT:8080} # Allow the Spring context to close all active requests before shutting down the server # Please ref: https://docs.spring.io/spring-boot/docs/2.3.0.RELEASE/reference/html/spring-boot-features.html#boot-features-graceful-shutdown @@ -95,6 +96,16 @@ management.tracing.sampling.probability=${APPSMITH_SAMPLING_PROBABILITY:0.1} management.prometheus.metrics.export.descriptions=true management.metrics.distribution.percentiles-histogram.http.server.requests=true +# Observability and Micrometer related configs +# Keeping this license key around, until later +appsmith.newrelic.licensekey=${APPSMITH_NEW_RELIC_OTLP_LICENSE_KEY:} +appsmith.observability.deployment.name=${APPSMITH_DEPLOYMENT_NAME:self-hosted} +appsmith.observability.service.instance.id=${HOSTNAME:appsmith-0} +appsmith.observability.metrics.enabled=${APPSMITH_MICROMETER_METRICS_ENABLED:false} +appsmith.observability.tracing.detail.enabled=${APPSMITH_ENABLE_TRACING_DETAIL:false} +appsmith.observability.metrics.detail.enabled=${APPSMITH_ENABLE_METRICS_DETAIL:false} +appsmith.observability.metrics.interval.millis=${APPSMITH_METRICS_INTERVAL_MILLIS:60000} + # Support disabling signup with an environment variable signup.disabled = ${APPSMITH_SIGNUP_DISABLED:false} signup.allowed-domains=${APPSMITH_SIGNUP_ALLOWED_DOMAINS:} @@ -117,15 +128,5 @@ appsmith.internal.password=${APPSMITH_INTERNAL_PASSWORD:} # GIT stale index.lock file valid time appsmith.index.lock.file.time=${APPSMITH_INDEX_LOCK_FILE_TIME:300} -# NewRelic and Micrometer related configs -appsmith.newrelic.licensekey=${APPSMITH_NEW_RELIC_OTLP_LICENSE_KEY:} -appsmith.newrelic.micrometer.metrics.container.name=${NEW_RELIC_METADATA_KUBERNETES_POD_NAME:appsmith-0} -appsmith.newrelic.micrometer.metrics.application.name=${APPSMITH_NEWRELIC_MICROMETER_SERVICE_NAME:} -spring.application.name=${OTEL_SERVICE_NAME:appsmith-anonymous} -appsmith.micrometer.metrics.enabled=${APPSMITH_MICROMETER_METRICS_ENABLED:false} -appsmith.micrometer.tracing.detail.enabled=${APPSMITH_ENABLE_TRACING_DETAIL:false} -appsmith.micrometer.metrics.detail.enabled=${APPSMITH_ENABLE_METRICS_DETAIL:false} -appsmith.micrometer.metrics.interval.millis=${APPSMITH_METRICS_INTERVAL_MILLIS:60000} - springdoc.api-docs.path=/v3/docs springdoc.swagger-ui.path=/v3/swagger