Observability - fieldenms/tg GitHub Wiki

This page is about observability in TG applications (metrics, monitoring, tracing, logging, reporting).

Introductory resources

Metrics

Micrometer

Micrometer is a Java library that provides a vendor-independent API for metrics and tracing.

The TG metrics API is directly using Micrometer. At this stage, only the Prometheus integration is supported, and so is assumed by default.

Prometheus

Deployment and configuration is described in https://github.com/fieldenms/devops/tree/master/prometheus.

Visualisation

Grafana

Deployment and configuration is described in https://github.com/fieldenms/devops/tree/master/grafana.

Configuring TG applications

This section describes how to enable metrics in a TG application.

Core configuration

  1. Locate the base IoC module for the application server. Typically, this is ApplicationServerIocModule in app-dao, so let us assume that.

  2. Add the following dependency to app-dao/pom.xml:

    <dependency>
      <groupId>fielden</groupId>
      <artifactId>platform-metrics-core</artifactId>
      <version>${platform.version}</version>
    </dependency>
  3. Install core IoC modules for metrics in ApplicationServerIocModule.

    install(new MetricsCoreIocModule(...));
    install(new CommonMetricsIocModule());

    The CommonMetricsIocModule registers a set of built-in metrics. In future versions, a more granular approach may be employed.

    If necessary, application developers may manipulate the meter registry directly, which corresponds to the IoC binding for io.micrometer.core.instrument.MeterRegistry.

For configuration options, refer to MetricsConfig.

Expose an HTTP endpoint to serve metrics

To configure the web server to serve metrics:

  1. Add the following dependency to app-web-server/pom.xml:

    <dependency>
      <groupId>fielden</groupId>
      <artifactId>platform-metrics-web-server</artifactId>
      <version>${platform.version}</version>
    </dependency>
  2. Configure the main Restlet component. Typically, this is ApplicationConfiguration extends Component.

    Here, you should attach a web resource that will handle metrics requests. In general, the setup will depend on the model of metrics collection. Since currently only Prometheus is supported, let us assume it will be used, which means that Prometheus scrapes metrics served by an application.

    // Metrics should be served only if they are enabled.
    if (injector.getInstance(MetricsConfig.class).mode() == MetricsConfig.Mode.ENABLED) {
        // Authentication goes first.
        final var metricsAuthenticator = injector.getInstance(MetricsAuthenticator.class);
        // The resource itself goes second.
        metricsAuthenticator.setNext(injector.getInstance(MetricsResourceFactory.class));
        getDefaultHost().attach("/metrics", metricsAuthenticator);
    }

    In this snippet, /metrics, as expected by Prometheus, is used to serve metrics.

  3. Enable authentication.

    For authentication (MetricsAuthenticator) to be used, a corresponding IoC module needs to be installed. Typically, app-web-server contains IoC module WebApplicationServerIocModule extends ApplicationServerIocModule, which needs to install the authentication module like so:

    install(new MetricsAuthenticationIocModule());

Web server metrics

This section describes how to add metrics that are specific to the web server of a TG application.

As a prerequisite, ensure that app-web-server/pom.xml includes the following dependency:

<dependency>
  <groupId>fielden</groupId>
  <artifactId>platform-metrics</artifactId>
  <artifactId>platform-metrics-web-server</artifactId>
  <version>${platform.version}</version>
</dependency>

MetricsFilter

Refer to the Javadoc for a detailed description.

Since MetricsFilter is implemented as a Restlet filter, it should be installed like one.

Typically, Restlet filters are configured in the main method of a Start (or StartOverHttp) class. MetricsFilter should be configured as the topmost filter, like so:

ApplicationConfiguration app = ...
org.restlet.Server server = ...

var metricsFilter = app.injector().getInstance(MetricsFilter.class);
var otherFilter = ...

server.setNext(metricsFilter);
metricsFilter.setNext(otherFilter);
⚠️ **GitHub.com Fallback** ⚠️