or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

client-configuration.mdcontent-handling.mdengine-architecture.mdevents-monitoring.mdhttp-statement.mdindex.mdplugin-system.mdrequest-building.mdresponse-handling.mdwebsocket-support.md

events-monitoring.mddocs/

0

# Events and Monitoring

1

2

Client lifecycle events and monitoring hooks for observing request/response processing, error handling, and performance monitoring throughout the HTTP client lifecycle.

3

4

## Capabilities

5

6

### Client Events

7

8

Predefined event definitions for monitoring HTTP client operations.

9

10

```kotlin { .api }

11

/**

12

* Container for HTTP client event definitions

13

*/

14

object ClientEvents {

15

/** Fired when HTTP request is created */

16

val HttpRequestCreated: EventDefinition<HttpRequestBuilder>

17

18

/** Fired when HTTP request is ready for sending */

19

val HttpRequestIsReadyForSending: EventDefinition<HttpRequestBuilder>

20

21

/** Fired when HTTP response is received */

22

val HttpResponseReceived: EventDefinition<HttpResponse>

23

24

/** Fired when HTTP response receive fails */

25

val HttpResponseReceiveFailed: EventDefinition<HttpResponseReceiveFail>

26

27

/** Fired when HTTP response is cancelled */

28

val HttpResponseCancelled: EventDefinition<HttpResponse>

29

}

30

```

31

32

### Event Data Types

33

34

Data structures for event information.

35

36

```kotlin { .api }

37

/**

38

* Information about failed response receive

39

* @param request - The original HTTP request

40

* @param cause - Exception that caused the failure

41

*/

42

data class HttpResponseReceiveFail(

43

val request: HttpRequest,

44

val cause: Throwable

45

)

46

47

/**

48

* Event definition for typed events

49

* @param T - Type of event data

50

*/

51

interface EventDefinition<T>

52

```

53

54

### Event Monitoring

55

56

Subscribe to client events for monitoring and logging.

57

58

```kotlin { .api }

59

/**

60

* Event monitoring interface

61

*/

62

interface Events {

63

/** Subscribe to an event */

64

fun <T> subscribe(definition: EventDefinition<T>, handler: suspend (T) -> Unit)

65

66

/** Unsubscribe from an event */

67

fun <T> unsubscribe(definition: EventDefinition<T>, handler: suspend (T) -> Unit)

68

69

/** Raise an event */

70

suspend fun <T> raise(definition: EventDefinition<T>, value: T)

71

}

72

73

// Access events through HttpClient

74

val HttpClient.monitor: Events

75

```

76

77

**Usage Examples:**

78

79

```kotlin

80

import io.ktor.client.*

81

import io.ktor.client.request.*

82

import io.ktor.client.utils.*

83

84

val client = HttpClient()

85

86

// Subscribe to request creation events

87

client.monitor.subscribe(ClientEvents.HttpRequestCreated) { request ->

88

println("Request created: ${request.method.value} ${request.url}")

89

}

90

91

// Subscribe to response events

92

client.monitor.subscribe(ClientEvents.HttpResponseReceived) { response ->

93

println("Response received: ${response.status} from ${response.call.request.url}")

94

}

95

96

// Subscribe to failure events

97

client.monitor.subscribe(ClientEvents.HttpResponseReceiveFailed) { failure ->

98

println("Request failed: ${failure.request.url} - ${failure.cause.message}")

99

}

100

101

// Subscribe to cancellation events

102

client.monitor.subscribe(ClientEvents.HttpResponseCancelled) { response ->

103

println("Response cancelled: ${response.call.request.url}")

104

}

105

106

// Make requests - events will be fired automatically

107

val response = client.get("https://api.example.com/users")

108

```

109

110

### Custom Event Definitions

111

112

Create custom event definitions for application-specific monitoring.

113

114

```kotlin { .api }

115

/**

116

* Create custom event definition

117

*/

118

fun <T> EventDefinition(): EventDefinition<T>

119

```

120

121

**Custom Events Example:**

122

123

```kotlin

124

import io.ktor.client.*

125

import io.ktor.client.utils.*

126

127

// Define custom events

128

val CustomRequestStart = EventDefinition<String>()

129

val CustomRequestComplete = EventDefinition<Pair<String, Long>>()

130

131

val client = HttpClient()

132

133

// Subscribe to custom events

134

client.monitor.subscribe(CustomRequestStart) { url ->

135

println("Starting custom operation for: $url")

136

}

137

138

client.monitor.subscribe(CustomRequestComplete) { (url, duration) ->

139

println("Completed custom operation for: $url in ${duration}ms")

140

}

141

142

// Raise custom events

143

suspend fun monitoredRequest(url: String) {

144

client.monitor.raise(CustomRequestStart, url)

145

val start = System.currentTimeMillis()

146

147

try {

148

val response = client.get(url)

149

val duration = System.currentTimeMillis() - start

150

client.monitor.raise(CustomRequestComplete, url to duration)

151

} catch (e: Exception) {

152

// Handle error and still fire completion event

153

val duration = System.currentTimeMillis() - start

154

client.monitor.raise(CustomRequestComplete, url to duration)

155

throw e

156

}

157

}

158

```

159

160

### Event-Based Logging

161

162

Implement comprehensive logging using event monitoring.

163

164

```kotlin

165

import io.ktor.client.*

166

import io.ktor.client.utils.*

167

import kotlinx.coroutines.*

168

169

class HttpClientLogger(private val client: HttpClient) {

170

171

init {

172

setupEventMonitoring()

173

}

174

175

private fun setupEventMonitoring() {

176

// Log all requests

177

client.monitor.subscribe(ClientEvents.HttpRequestCreated) { request ->

178

println("[REQUEST] ${request.method.value} ${request.url}")

179

request.headers.entries().forEach { (name, values) ->

180

println("[REQUEST-HEADER] $name: ${values.joinToString(", ")}")

181

}

182

}

183

184

// Log successful responses

185

client.monitor.subscribe(ClientEvents.HttpResponseReceived) { response ->

186

println("[RESPONSE] ${response.status.value} ${response.status.description}")

187

println("[TIMING] Request: ${response.requestTime}, Response: ${response.responseTime}")

188

}

189

190

// Log failures

191

client.monitor.subscribe(ClientEvents.HttpResponseReceiveFailed) { failure ->

192

println("[ERROR] Request to ${failure.request.url} failed: ${failure.cause.message}")

193

failure.cause.printStackTrace()

194

}

195

196

// Log cancellations

197

client.monitor.subscribe(ClientEvents.HttpResponseCancelled) { response ->

198

println("[CANCELLED] Request to ${response.call.request.url} was cancelled")

199

}

200

}

201

}

202

203

// Usage

204

val client = HttpClient()

205

val logger = HttpClientLogger(client)

206

207

// All requests will now be logged automatically

208

val response = client.get("https://api.example.com/users")

209

```

210

211

### Performance Monitoring

212

213

Use events for performance tracking and metrics collection.

214

215

```kotlin

216

import io.ktor.client.*

217

import io.ktor.client.utils.*

218

219

class HttpPerformanceMonitor(private val client: HttpClient) {

220

private val requestTimes = mutableMapOf<HttpRequest, Long>()

221

222

init {

223

// Track request start times

224

client.monitor.subscribe(ClientEvents.HttpRequestIsReadyForSending) { request ->

225

requestTimes[request] = System.currentTimeMillis()

226

}

227

228

// Calculate and log response times

229

client.monitor.subscribe(ClientEvents.HttpResponseReceived) { response ->

230

val startTime = requestTimes.remove(response.call.request)

231

if (startTime != null) {

232

val duration = System.currentTimeMillis() - startTime

233

println("Request to ${response.call.request.url} took ${duration}ms")

234

235

// Could send to metrics system here

236

recordMetric("http.request.duration", duration,

237

mapOf("url" to response.call.request.url.toString(),

238

"method" to response.call.request.method.value,

239

"status" to response.status.value.toString()))

240

}

241

}

242

243

// Clean up on failures

244

client.monitor.subscribe(ClientEvents.HttpResponseReceiveFailed) { failure ->

245

requestTimes.remove(failure.request)

246

}

247

}

248

249

private fun recordMetric(name: String, value: Long, tags: Map<String, String>) {

250

// Implementation for your metrics system

251

println("METRIC: $name = $value, tags = $tags")

252

}

253

}

254

```

255

256

## Event Lifecycle

257

258

1. **HttpRequestCreated** - Fired when `HttpRequestBuilder` is created and configured

259

2. **HttpRequestIsReadyForSending** - Fired just before the request is sent to the engine

260

3. **HttpResponseReceived** - Fired when a successful response is received

261

4. **HttpResponseReceiveFailed** - Fired when response receiving fails

262

5. **HttpResponseCancelled** - Fired when response processing is cancelled

263

264

Events provide a clean way to implement cross-cutting concerns like logging, metrics, caching, and debugging without modifying core client code.