Ktor 3.0.2 Help

Application monitoring

Ktor provides the ability to monitor your server application by using events. You can handle predefined events related to an application's lifecycle (application starting, stopping, etc.), or you can use custom events to handle specific cases. You can also handle events for custom plugins using the MonitoringEvent hook.

Event definition

Each event is represented by the EventDefinition class instance. This class has a T type parameter specifying the type of value passed to the event. This value can be accessed in the event handler as a lambda argument. For example, most of the predefined events accept Application as a parameter allowing you to access application properties inside the event handler.

For a custom event, you can pass a type parameter required for this event. The code snippet below shows how to create a custom NotFoundEvent that accepts the ApplicationCall instance.

val NotFoundEvent: EventDefinition<ApplicationCall> = EventDefinition()

The Custom events section shows how to raise this event in a custom plugin when a server returns the 404 Not Found status code for a resource.

Predefined application events

Ktor provides the following predefined events related to an application's lifecycle:

For example, you can subscribe to the ApplicationStopped event to release application resources.

Handle events in an application

To handle events for the specified Application instance, use the monitor property. This property provides access to the Events instance that exposes the following functions allowing you to handle application events:

The subscribe/unsubscribe functions accept the EventDefinition instance with the T value as a lambda argument. The example below shows how to subscribe to the ApplicationStarted event and log a message in the event handler:

fun Application.module() { monitor.subscribe(ApplicationStarted) { application -> application.environment.log.info("Server is started") } }

In this example, you can see how to handle the ApplicationStopped event:

fun Application.module() { monitor.subscribe(ApplicationStopped) { application -> application.environment.log.info("Server is stopped") // Release resources and unsubscribe from events monitor.unsubscribe(ApplicationStarted) {} monitor.unsubscribe(ApplicationStopped) {} } }

For the full example, see events.

Handle events in a custom plugin

You can handle events in custom plugins using the MonitoringEvent hook. The example below shows how to create the ApplicationMonitoringPlugin plugin and handle the ApplicationStarted and ApplicationStopped events:

import io.ktor.events.EventDefinition import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.application.hooks.* val ApplicationMonitoringPlugin = createApplicationPlugin(name = "ApplicationMonitoringPlugin") { on(MonitoringEvent(ApplicationStarted)) { application -> application.log.info("Server is started") } on(MonitoringEvent(ApplicationStopped)) { application -> application.log.info("Server is stopped") // Release resources and unsubscribe from events application.monitor.unsubscribe(ApplicationStarted) {} application.monitor.unsubscribe(ApplicationStopped) {} } }

You can find the full example here: events.

Custom events

In this section, we'll take a look at how to create a custom event raised when a server returns the 404 Not Found status code for a resource.

  1. First, you need to create the event definition. The code snippet below shows how to create a custom NotFoundEvent event that accepts ApplicationCall as a parameter.

    val NotFoundEvent: EventDefinition<ApplicationCall> = EventDefinition()
  2. To raise the event, call the Events.raise function. The sample below shows how to handle the ResponseSent hook to raise the newly created event if the status code for a call is 404.

    import io.ktor.events.EventDefinition import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.application.hooks.* val ApplicationMonitoringPlugin = createApplicationPlugin(name = "ApplicationMonitoringPlugin") { on(ResponseSent) { call -> if (call.response.status() == HttpStatusCode.NotFound) { this@createApplicationPlugin.application.monitor.raise(NotFoundEvent, call) } } }
  3. To handle the created event in the Application, install the plugin:

    fun Application.module() { install(ApplicationMonitoringPlugin) }
  4. Then, subscribe to the event using Events.subscribe:

    fun Application.module() { install(ApplicationMonitoringPlugin) monitor.subscribe(NotFoundEvent) { call -> log.info("No page was found for the URI: ${call.request.uri}") } }

For the full example, see events.

Last modified: 23 August 2024