or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

counter.mdenumeration.mdexemplars.mdgauge.mdhistogram.mdindex.mdinfo.mdregistry.mdsummary.md

summary.mddocs/

0

# Summary Metrics

1

2

Summary metrics track quantiles and distributions with configurable sliding time windows and precise quantile calculations. They provide count, sum, and quantile values without requiring predefined buckets like histograms.

3

4

## Capabilities

5

6

### Summary Creation

7

8

Create summary metrics using the builder pattern with optional quantile configuration.

9

10

```java { .api }

11

/**

12

* Create a new Summary builder

13

* @return Builder instance for configuration

14

*/

15

public static Summary.Builder build();

16

17

/**

18

* Create a new Summary builder with required fields

19

* @param name The metric name (without _count/_sum suffixes)

20

* @param help The help text describing the metric

21

* @return Builder instance for configuration

22

*/

23

public static Summary.Builder build(String name, String help);

24

```

25

26

**Usage Example:**

27

28

```java

29

import io.prometheus.client.Summary;

30

31

// Basic summary (count and sum only)

32

Summary requestLatency = Summary.build()

33

.name("request_latency_seconds")

34

.help("Request latency in seconds")

35

.register();

36

37

// Summary with quantiles

38

Summary responseTime = Summary.build()

39

.name("response_time_seconds")

40

.help("Response time distribution")

41

.quantile(0.5, 0.01) // 50th percentile ±1%

42

.quantile(0.95, 0.005) // 95th percentile ±0.5%

43

.quantile(0.99, 0.001) // 99th percentile ±0.1%

44

.register();

45

```

46

47

### Summary Builder Configuration

48

49

Configure summary quantiles, time windows, and sampling parameters.

50

51

```java { .api }

52

public static class Builder extends SimpleCollector.Builder<Builder, Summary> {

53

/**

54

* Add a quantile to track with specified error tolerance

55

* @param quantile Quantile to track (0.0 to 1.0)

56

* @param error Allowed error for quantile calculation

57

* @return Builder for method chaining

58

* @throws IllegalArgumentException if quantile not in [0,1] or error negative

59

*/

60

public Builder quantile(double quantile, double error);

61

62

/**

63

* Set the maximum age of observations in seconds

64

* @param ageSeconds Age in seconds (default: 600)

65

* @return Builder for method chaining

66

*/

67

public Builder maxAgeSeconds(long ageSeconds);

68

69

/**

70

* Set number of age buckets for sliding time window

71

* @param ageBuckets Number of buckets (default: 5)

72

* @return Builder for method chaining

73

*/

74

public Builder ageBuckets(int ageBuckets);

75

}

76

```

77

78

**Usage Examples:**

79

80

```java

81

// High-precision summary with custom time window

82

Summary preciseLatency = Summary.build()

83

.name("precise_latency_seconds")

84

.help("High precision latency tracking")

85

.quantile(0.50, 0.01) // Median ±1%

86

.quantile(0.90, 0.005) // 90th percentile ±0.5%

87

.quantile(0.95, 0.005) // 95th percentile ±0.5%

88

.quantile(0.99, 0.001) // 99th percentile ±0.1%

89

.maxAgeSeconds(300) // 5-minute window

90

.ageBuckets(5) // 5 buckets = 1 minute each

91

.register();

92

93

// Min/max tracking (special cases with zero error)

94

Summary minMax = Summary.build()

95

.name("processing_duration_seconds")

96

.help("Processing duration with min/max")

97

.quantile(0.0, 0.0) // Minimum (no extra memory)

98

.quantile(1.0, 0.0) // Maximum (no extra memory)

99

.quantile(0.5, 0.01) // Median ±1%

100

.register();

101

```

102

103

### Summary Observations

104

105

Record values in summary metrics for quantile and statistical calculations.

106

107

```java { .api }

108

/**

109

* Record an observation in the summary

110

* @param amt Value to observe

111

*/

112

public void observe(double amt);

113

```

114

115

**Usage Examples:**

116

117

```java

118

// Basic observations

119

requestLatency.observe(0.123); // 123ms request

120

responseTime.observe(0.045); // 45ms response

121

responseTime.observe(1.234); // 1.234s slower response

122

123

// Processing different types of operations

124

Summary operationDuration = Summary.build()

125

.name("operation_duration_seconds")

126

.help("Operation processing time")

127

.labelNames("operation_type")

128

.quantile(0.5, 0.01)

129

.quantile(0.95, 0.005)

130

.register();

131

132

operationDuration.labels("database_query").observe(0.025);

133

operationDuration.labels("file_write").observe(0.150);

134

operationDuration.labels("network_call").observe(0.300);

135

```

136

137

### Timer Operations

138

139

Use summaries for automatic duration measurement and timing operations.

140

141

```java { .api }

142

/**

143

* Start a timer for duration measurement

144

* @return Timer instance for duration tracking

145

*/

146

public Timer startTimer();

147

148

/**

149

* Time a Runnable execution and observe duration

150

* @param timeable Code to time

151

* @return Duration in seconds

152

*/

153

public double time(Runnable timeable);

154

155

/**

156

* Time a Callable execution and observe duration

157

* @param timeable Code to time

158

* @return Result from callable

159

* @throws RuntimeException if callable throws exception

160

*/

161

public <E> E time(Callable<E> timeable);

162

```

163

164

### Summary Timer Class

165

166

Timer provides duration measurement capabilities for summary metrics.

167

168

```java { .api }

169

public static class Timer implements Closeable {

170

/**

171

* Observe elapsed duration since timer start

172

* @return Elapsed duration in seconds

173

*/

174

public double observeDuration();

175

176

/**

177

* Equivalent to observeDuration() - implements Closeable

178

*/

179

public void close();

180

}

181

```

182

183

**Usage Examples:**

184

185

```java

186

// Manual timer usage

187

Summary.Timer timer = requestLatency.startTimer();

188

try {

189

processRequest();

190

} finally {

191

double duration = timer.observeDuration();

192

System.out.println("Request took: " + duration + " seconds");

193

}

194

195

// Try-with-resources timer

196

try (Summary.Timer timer = requestLatency.startTimer()) {

197

processRequest(); // Automatically observes duration on close

198

}

199

200

// Lambda timing

201

double duration = requestLatency.time(() -> {

202

processRequest();

203

});

204

205

// Timing with return value

206

String result = requestLatency.time(() -> {

207

return generateResponse();

208

});

209

210

// Batch processing timing

211

Summary batchProcessing = Summary.build()

212

.name("batch_processing_seconds")

213

.help("Batch processing duration")

214

.quantile(0.5, 0.01)

215

.quantile(0.95, 0.005)

216

.register();

217

218

List<String> results = batchProcessing.time(() -> {

219

return processBatch();

220

});

221

```

222

223

### Labeled Summary Operations

224

225

Work with multi-dimensional summaries using label values.

226

227

```java { .api }

228

/**

229

* Get summary child for specific label values

230

* @param labelValues Values for each label name (must match count)

231

* @return Summary.Child instance for the label combination

232

* @throws IllegalArgumentException if wrong number of labels

233

*/

234

public Summary.Child labels(String... labelValues);

235

236

/**

237

* Remove summary child for specific label values

238

* @param labelValues Values identifying the child to remove

239

*/

240

public void remove(String... labelValues);

241

242

/**

243

* Remove all summary children

244

*/

245

public void clear();

246

```

247

248

### Summary Child Operations

249

250

Summary.Child provides the same observation and timing operations for labeled instances.

251

252

```java { .api }

253

public static class Child {

254

/** Record observation in child summary */

255

public void observe(double amt);

256

257

/** Start timer for child summary */

258

public Timer startTimer();

259

260

/** Time operations for child summary */

261

public double time(Runnable timeable);

262

public <E> E time(Callable<E> timeable);

263

264

/** Get summary data snapshot */

265

public Value get();

266

}

267

```

268

269

### Summary Value Data

270

271

Access summary count, sum, and quantile data.

272

273

```java { .api }

274

public static class Value {

275

/** Total number of observations */

276

public final long count;

277

278

/** Sum of all observed values */

279

public final double sum;

280

281

/** Map of quantile values (quantile -> value) */

282

public final SortedMap<Double, Double> quantiles;

283

}

284

```

285

286

**Usage Example:**

287

288

```java

289

// API endpoint monitoring

290

Summary apiLatency = Summary.build()

291

.name("api_endpoint_duration_seconds")

292

.help("API endpoint response time")

293

.labelNames("endpoint", "method", "status")

294

.quantile(0.5, 0.01) // Median

295

.quantile(0.95, 0.005) // 95th percentile

296

.quantile(0.99, 0.001) // 99th percentile

297

.register();

298

299

// Track different endpoints

300

Summary.Child getUserLatency = apiLatency.labels("/users", "GET", "200");

301

Summary.Child postUserLatency = apiLatency.labels("/users", "POST", "201");

302

303

// Time requests

304

getUserLatency.time(() -> handleGetUser());

305

postUserLatency.observe(0.156); // Manual observation

306

307

// Access summary statistics

308

Summary.Child.Value stats = getUserLatency.get();

309

System.out.println("Total requests: " + stats.count);

310

System.out.println("Average latency: " + (stats.sum / stats.count));

311

System.out.println("95th percentile: " + stats.quantiles.get(0.95));

312

```

313

314

## Important Notes

315

316

### Quantile Configuration

317

318

**Quantile Range**: Must be between 0.0 and 1.0

319

- `0.0` = minimum value (special case, no extra memory)

320

- `0.5` = median (50th percentile)

321

- `0.95` = 95th percentile

322

- `0.99` = 99th percentile

323

- `1.0` = maximum value (special case, no extra memory)

324

325

**Error Tolerance**: Controls precision vs memory usage

326

- `0.01` = ±1% error (good for most use cases)

327

- `0.005` = ±0.5% error (higher precision)

328

- `0.001` = ±0.1% error (very high precision)

329

- `0.0` = exact tracking (uses more memory)

330

331

### Time Window Behavior

332

333

Summary uses a sliding time window:

334

- **maxAgeSeconds**: Total window duration (default: 10 minutes)

335

- **ageBuckets**: Number of sub-windows (default: 5 buckets)

336

- Window slides forward every `maxAgeSeconds / ageBuckets` interval

337

- Old observations are automatically discarded

338

339

Example with defaults:

340

- 10-minute total window

341

- 5 buckets = 2-minute intervals

342

- Window slides every 2 minutes

343

344

### Memory Usage

345

346

- Count and sum use minimal memory

347

- Each quantile uses approximately 100 samples regardless of observation count

348

- Min (0.0) and max (1.0) quantiles are memory-optimized special cases

349

- Choose error tolerance based on precision needs vs memory constraints

350

351

### Summary vs Histogram

352

353

**Use Summary when**:

354

- You need precise quantiles (e.g., SLA monitoring)

355

- You don't know the distribution shape in advance

356

- You want automatic memory management

357

- You need client-side quantile calculation

358

359

**Use Histogram when**:

360

- You need server-side quantile calculation

361

- You want to aggregate across multiple instances

362

- You know appropriate bucket boundaries

363

- You need Prometheus alerting on buckets

364

365

### Common Patterns

366

367

```java

368

// SLA monitoring

369

Summary slaLatency = Summary.build()

370

.name("sla_response_time_seconds")

371

.help("Response time for SLA monitoring")

372

.quantile(0.95, 0.01) // 95% of requests under X seconds

373

.quantile(0.99, 0.005) // 99% of requests under Y seconds

374

.maxAgeSeconds(300) // 5-minute sliding window

375

.register();

376

377

// Database query performance

378

Summary dbQueries = Summary.build()

379

.name("database_query_duration_seconds")

380

.help("Database query performance")

381

.labelNames("query_type", "table")

382

.quantile(0.5, 0.01) // Median

383

.quantile(0.9, 0.005) // 90th percentile

384

.quantile(0.99, 0.001) // 99th percentile

385

.register();

386

387

// Batch processing monitoring

388

Summary batchJobs = Summary.build()

389

.name("batch_job_duration_seconds")

390

.help("Batch job processing time")

391

.labelNames("job_type")

392

.quantile(0.0, 0.0) // Minimum (free)

393

.quantile(0.5, 0.01) // Median

394

.quantile(1.0, 0.0) // Maximum (free)

395

.register();

396

```