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

registry.mddocs/

0

# Registry Management

1

2

The CollectorRegistry manages metric registration, collection, and provides access to metric samples for export to monitoring systems. It serves as the central hub for all metric collectors in an application.

3

4

## Capabilities

5

6

### Registry Creation and Access

7

8

Access the default registry or create custom registries for specific use cases.

9

10

```java { .api }

11

/**

12

* Default registry singleton for most applications

13

*/

14

public static final CollectorRegistry defaultRegistry;

15

16

/**

17

* Create a new CollectorRegistry instance

18

*/

19

public CollectorRegistry();

20

21

/**

22

* Create a new CollectorRegistry with auto-describe option

23

* @param autoDescribe Whether to automatically describe collectors

24

*/

25

public CollectorRegistry(boolean autoDescribe);

26

```

27

28

**Usage Example:**

29

30

```java

31

import io.prometheus.client.CollectorRegistry;

32

import io.prometheus.client.Counter;

33

34

// Use default registry (most common)

35

Counter requests = Counter.build()

36

.name("requests_total")

37

.help("Total requests")

38

.register(); // Registers to defaultRegistry

39

40

// Create custom registry for testing

41

CollectorRegistry testRegistry = new CollectorRegistry();

42

Counter testCounter = Counter.build()

43

.name("test_counter")

44

.help("Test counter")

45

.register(testRegistry);

46

47

// Registry with auto-describe for development

48

CollectorRegistry devRegistry = new CollectorRegistry(true);

49

```

50

51

### Collector Registration

52

53

Register and unregister metric collectors with the registry.

54

55

```java { .api }

56

/**

57

* Register a collector with this registry

58

* @param collector Collector to register

59

* @throws IllegalArgumentException if collector names conflict

60

*/

61

public void register(Collector collector);

62

63

/**

64

* Unregister a collector from this registry

65

* @param collector Collector to unregister

66

*/

67

public void unregister(Collector collector);

68

69

/**

70

* Unregister all collectors from this registry

71

*/

72

public void clear();

73

```

74

75

**Usage Examples:**

76

77

```java

78

// Register collectors explicitly

79

CollectorRegistry customRegistry = new CollectorRegistry();

80

81

Counter requests = Counter.build()

82

.name("requests_total")

83

.help("Total requests")

84

.create(); // Create without registering

85

86

Gauge memory = Gauge.build()

87

.name("memory_usage_bytes")

88

.help("Memory usage")

89

.create();

90

91

// Register to custom registry

92

customRegistry.register(requests);

93

customRegistry.register(memory);

94

95

// Unregister when no longer needed

96

customRegistry.unregister(requests);

97

98

// Name conflict detection

99

Counter duplicate = Counter.build()

100

.name("requests_total") // Same name as existing

101

.help("Duplicate counter")

102

.create();

103

104

try {

105

customRegistry.register(duplicate); // Throws IllegalArgumentException

106

} catch (IllegalArgumentException e) {

107

System.err.println("Name conflict: " + e.getMessage());

108

}

109

```

110

111

### Metric Sample Collection

112

113

Collect metric samples from all registered collectors for export.

114

115

```java { .api }

116

/**

117

* Get all metric family samples from registered collectors

118

* @return Enumeration of MetricFamilySamples

119

*/

120

public Enumeration<MetricFamilySamples> metricFamilySamples();

121

122

/**

123

* Get filtered metric family samples

124

* @param sampleNameFilter Predicate to filter sample names

125

* @return Enumeration of filtered MetricFamilySamples

126

*/

127

public Enumeration<MetricFamilySamples> filteredMetricFamilySamples(Predicate<String> sampleNameFilter);

128

129

/**

130

* Get metric family samples for specific metric names

131

* @param includedNames Set of metric names to include

132

* @return Enumeration of MetricFamilySamples for specified names

133

*/

134

public Enumeration<MetricFamilySamples> filteredMetricFamilySamples(Set<String> includedNames);

135

```

136

137

**Usage Examples:**

138

139

```java

140

// Collect all metrics

141

Enumeration<MetricFamilySamples> allMetrics =

142

CollectorRegistry.defaultRegistry.metricFamilySamples();

143

144

while (allMetrics.hasMoreElements()) {

145

MetricFamilySamples family = allMetrics.nextElement();

146

System.out.println("Metric: " + family.name + " (" + family.type + ")");

147

148

for (MetricFamilySamples.Sample sample : family.samples) {

149

System.out.println(" " + sample.name + " = " + sample.value);

150

}

151

}

152

153

// Filter metrics by name pattern

154

Predicate<String> httpMetricsFilter = name -> name.startsWith("http_");

155

Enumeration<MetricFamilySamples> httpMetrics =

156

CollectorRegistry.defaultRegistry.metricFamilySamples(httpMetricsFilter);

157

158

// Get specific metrics by name

159

Set<String> requestMetrics = Set.of("requests_total", "request_duration_seconds");

160

Enumeration<MetricFamilySamples> specificMetrics =

161

CollectorRegistry.defaultRegistry.filteredMetricFamilySamples(requestMetrics);

162

```

163

164

### Single Sample Value Access

165

166

Retrieve individual metric values for specific use cases.

167

168

```java { .api }

169

/**

170

* Get sample value for metric without labels

171

* @param name Metric name

172

* @return Sample value or null if not found

173

*/

174

public Double getSampleValue(String name);

175

176

/**

177

* Get sample value for labeled metric

178

* @param name Metric name

179

* @param labelNames Array of label names

180

* @param labelValues Array of label values (must match labelNames)

181

* @return Sample value or null if not found

182

*/

183

public Double getSampleValue(String name, String[] labelNames, String[] labelValues);

184

```

185

186

**Usage Examples:**

187

188

```java

189

// Get simple metric value

190

Double totalRequests = CollectorRegistry.defaultRegistry

191

.getSampleValue("requests_total");

192

193

if (totalRequests != null) {

194

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

195

}

196

197

// Get labeled metric value

198

String[] labelNames = {"method", "status"};

199

String[] labelValues = {"GET", "200"};

200

Double getRequests = CollectorRegistry.defaultRegistry

201

.getSampleValue("http_requests_total", labelNames, labelValues);

202

203

// Null check for missing metrics

204

if (getRequests != null) {

205

System.out.println("GET 200 requests: " + getRequests);

206

} else {

207

System.out.println("Metric not found or no samples");

208

}

209

210

// Utility method for safe value retrieval

211

public double getMetricValueOrDefault(String name, double defaultValue) {

212

Double value = CollectorRegistry.defaultRegistry.getSampleValue(name);

213

return value != null ? value : defaultValue;

214

}

215

```

216

217

## Important Notes

218

219

### Default Registry Usage

220

221

Most applications should use the default registry:

222

223

```java

224

// Recommended approach for most applications

225

Counter requests = Counter.build()

226

.name("requests_total")

227

.help("Total requests")

228

.register(); // Uses defaultRegistry automatically

229

230

// Equivalent explicit registration

231

Counter requests2 = Counter.build()

232

.name("requests_total_2")

233

.help("Total requests")

234

.register(CollectorRegistry.defaultRegistry);

235

```

236

237

### Custom Registry Use Cases

238

239

Create custom registries for:

240

241

- **Unit Testing**: Isolated metrics for test cases

242

- **Subsystem Isolation**: Separate metrics for different components

243

- **Partial Export**: Export subset of metrics to different endpoints

244

- **Development/Debug**: Enhanced introspection with auto-describe

245

246

```java

247

// Testing with isolated registry

248

@Test

249

public void testMetrics() {

250

CollectorRegistry testRegistry = new CollectorRegistry();

251

Counter testCounter = Counter.build()

252

.name("test_operations")

253

.help("Test operations")

254

.register(testRegistry);

255

256

testCounter.inc();

257

258

Double value = testRegistry.getSampleValue("test_operations_total");

259

assertEquals(1.0, value, 0.001);

260

}

261

262

// Subsystem-specific registry

263

public class DatabaseMetrics {

264

private static final CollectorRegistry dbRegistry = new CollectorRegistry();

265

266

public static final Counter queries = Counter.build()

267

.name("db_queries_total")

268

.help("Database queries")

269

.register(dbRegistry);

270

271

public static Enumeration<MetricFamilySamples> getMetrics() {

272

return dbRegistry.metricFamilySamples();

273

}

274

}

275

```

276

277

### Name Conflict Resolution

278

279

The registry prevents duplicate metric names:

280

281

```java

282

CollectorRegistry registry = new CollectorRegistry();

283

284

// First registration succeeds

285

Counter counter1 = Counter.build()

286

.name("operations")

287

.help("First counter")

288

.create();

289

registry.register(counter1);

290

291

// Second registration with same name fails

292

Counter counter2 = Counter.build()

293

.name("operations") // Conflict!

294

.help("Second counter")

295

.create();

296

297

try {

298

registry.register(counter2);

299

} catch (IllegalArgumentException e) {

300

// Handle name conflict

301

System.err.println("Metric name already exists: " + e.getMessage());

302

}

303

304

// Solution: Use different names or unregister first

305

registry.unregister(counter1);

306

registry.register(counter2); // Now succeeds

307

```

308

309

### Thread Safety

310

311

All registry operations are thread-safe:

312

313

```java

314

// Safe concurrent registration

315

CollectorRegistry registry = new CollectorRegistry();

316

317

// Multiple threads can safely register different collectors

318

Thread t1 = new Thread(() -> {

319

Counter c1 = Counter.build().name("metric1").help("M1").create();

320

registry.register(c1);

321

});

322

323

Thread t2 = new Thread(() -> {

324

Gauge g1 = Gauge.build().name("metric2").help("M2").create();

325

registry.register(g1);

326

});

327

328

t1.start();

329

t2.start();

330

```

331

332

### Sample Name Filtering

333

334

Use filtering for performance and relevance:

335

336

```java

337

// Performance: Only collect metrics you need

338

Predicate<String> relevantMetrics = name ->

339

name.startsWith("app_") || name.startsWith("business_");

340

341

Enumeration<MetricFamilySamples> filtered =

342

registry.metricFamilySamples(relevantMetrics);

343

344

// Custom filter implementation

345

public class MetricNameFilter implements Predicate<String> {

346

private final Set<String> allowedPrefixes;

347

348

public MetricNameFilter(String... prefixes) {

349

this.allowedPrefixes = Set.of(prefixes);

350

}

351

352

@Override

353

public boolean test(String name) {

354

return allowedPrefixes.stream().anyMatch(name::startsWith);

355

}

356

}

357

358

// Usage

359

MetricNameFilter filter = new MetricNameFilter("http_", "db_", "cache_");

360

Enumeration<MetricFamilySamples> metrics = registry.metricFamilySamples(filter);

361

```

362

363

### Integration Patterns

364

365

```java

366

// Metrics exporter pattern

367

public class PrometheusExporter {

368

private final CollectorRegistry registry;

369

370

public PrometheusExporter(CollectorRegistry registry) {

371

this.registry = registry;

372

}

373

374

public String exportMetrics() {

375

StringBuilder output = new StringBuilder();

376

Enumeration<MetricFamilySamples> samples = registry.metricFamilySamples();

377

378

while (samples.hasMoreElements()) {

379

MetricFamilySamples family = samples.nextElement();

380

// Format for Prometheus text format

381

output.append(formatFamily(family));

382

}

383

384

return output.toString();

385

}

386

}

387

388

// Health check integration

389

public class MetricsHealthCheck {

390

public boolean isHealthy() {

391

Double errorRate = CollectorRegistry.defaultRegistry

392

.getSampleValue("error_rate");

393

394

return errorRate == null || errorRate < 0.05; // 5% threshold

395

}

396

397

public Map<String, Object> getHealthDetails() {

398

Map<String, Object> details = new HashMap<>();

399

400

details.put("total_requests",

401

CollectorRegistry.defaultRegistry.getSampleValue("requests_total"));

402

details.put("error_count",

403

CollectorRegistry.defaultRegistry.getSampleValue("errors_total"));

404

405

return details;

406

}

407

}

408

```