or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdexceptions.mdexecution.mdexpressions.mdindex.mdjdbc.mdmapreduce.mdmonitoring.mdquery-compilation.mdschema-metadata.mdserver.mdtransactions.mdtypes.md

monitoring.mddocs/

0

# Monitoring and Metrics

1

2

Phoenix provides comprehensive monitoring and metrics collection capabilities to track query performance, resource usage, and system health. The monitoring framework enables detailed analysis of Phoenix operations and supports performance optimization efforts.

3

4

## Core Imports

5

6

```java

7

import org.apache.phoenix.monitoring.*;

8

import org.apache.phoenix.jdbc.*;

9

import java.util.Map;

10

import java.util.concurrent.TimeUnit;

11

```

12

13

## Metric Types

14

15

### MetricType

16

17

Enumeration of all Phoenix metric types with detailed performance and resource monitoring.

18

19

```java{ .api }

20

public enum MetricType {

21

// Query performance metrics

22

QUERY_TIME("Query execution time", true),

23

QUERY_TIMEOUT("Query timeout occurrences", false),

24

QUERY_FAILED("Failed query count", false),

25

QUERY_EXECUTED("Executed query count", false),

26

27

// Scan metrics

28

SCAN_BYTES("Bytes scanned", true),

29

SCAN_ROWS("Rows scanned", true),

30

SCAN_TIME("Scan execution time", true),

31

32

// Memory metrics

33

MEMORY_CHUNK_BYTES("Memory chunk size in bytes", true),

34

MEMORY_WAIT_TIME("Memory wait time", true),

35

SPOOL_FILE_SIZE("Spool file size", true),

36

SPOOL_FILE_COUNTER("Number of spool files", false),

37

38

// Network and RPC metrics

39

BYTES_RECEIVED("Bytes received over network", true),

40

BYTES_SENT("Bytes sent over network", true),

41

RPC_TIME("RPC call time", true),

42

RPC_CALLS("Number of RPC calls", false),

43

44

// Cache metrics

45

CACHE_REFRESH_SPLITS_COUNTER("Cache refresh splits", false),

46

METADATA_CACHE_MISS_COUNTER("Metadata cache misses", false),

47

METADATA_CACHE_HIT_COUNTER("Metadata cache hits", false),

48

49

// Mutation metrics

50

MUTATION_BATCH_SIZE("Mutation batch size", true),

51

MUTATION_COMMIT_TIME("Mutation commit time", true),

52

MUTATION_BYTES("Mutation data size", true),

53

54

// Connection metrics

55

OPEN_PHOENIX_CONNECTIONS("Open Phoenix connections", false),

56

QUERY_SERVICES_COUNTER("Query services operations", false),

57

HCONNECTIONS_COUNTER("HBase connections", false);

58

59

private final String description;

60

private final boolean isTimeMetric;

61

62

MetricType(String description, boolean isTimeMetric) {

63

this.description = description;

64

this.isTimeMetric = isTimeMetric;

65

}

66

67

public String getDescription()

68

public String getMetricName()

69

public boolean isTimer()

70

public boolean isHistogram()

71

public boolean isCounter()

72

}

73

```

74

75

**Usage:**

76

```java

77

// Access metric information

78

for (MetricType metricType : MetricType.values()) {

79

System.out.println("Metric: " + metricType.getMetricName());

80

System.out.println("Description: " + metricType.getDescription());

81

System.out.println("Is Timer: " + metricType.isTimer());

82

System.out.println("Is Counter: " + metricType.isCounter());

83

System.out.println();

84

}

85

86

// Check specific metric properties

87

MetricType queryTime = MetricType.QUERY_TIME;

88

if (queryTime.isTimer()) {

89

System.out.println("Query time is measured as a timer metric");

90

}

91

92

MetricType queryCount = MetricType.QUERY_EXECUTED;

93

if (queryCount.isCounter()) {

94

System.out.println("Query executed is a counter metric");

95

}

96

```

97

98

## Global Client Metrics

99

100

### GlobalClientMetrics

101

102

Global client-side metrics collection providing system-wide monitoring.

103

104

```java{ .api }

105

public class GlobalClientMetrics {

106

// Global metric instances

107

public static final GlobalMetric GLOBAL_QUERY_TIME =

108

GlobalClientMetrics.getInstance(MetricType.QUERY_TIME);

109

public static final GlobalMetric GLOBAL_SCAN_BYTES =

110

GlobalClientMetrics.getInstance(MetricType.SCAN_BYTES);

111

public static final GlobalMetric GLOBAL_MEMORY_CHUNK_BYTES =

112

GlobalClientMetrics.getInstance(MetricType.MEMORY_CHUNK_BYTES);

113

public static final GlobalMetric GLOBAL_MUTATION_BATCH_SIZE =

114

GlobalClientMetrics.getInstance(MetricType.MUTATION_BATCH_SIZE);

115

116

// Metric factory methods

117

public static GlobalMetric getInstance(MetricType metricType)

118

public static boolean isMetricsEnabled()

119

public static void setMetricsEnabled(boolean enabled)

120

121

// Metric collection methods

122

public static Map<MetricType, Long> getGlobalMetrics()

123

public static long getGlobalMetricValue(MetricType metricType)

124

public static void resetGlobalMetrics()

125

126

// Metric aggregation

127

public static Map<String, Object> getMetricsSummary()

128

public static String getMetricsReport()

129

}

130

```

131

132

### GlobalMetric

133

134

Individual global metric implementation with thread-safe operations.

135

136

```java{ .api }

137

public class GlobalMetric {

138

// Metric operations

139

public void increment()

140

public void increment(long delta)

141

public void update(long value)

142

public void decrement()

143

public void decrement(long delta)

144

145

// Metric queries

146

public long getValue()

147

public long getCount()

148

public double getMean()

149

public long getMax()

150

public long getMin()

151

152

// Reset operations

153

public void reset()

154

public MetricType getMetricType()

155

}

156

```

157

158

**Usage:**

159

```java

160

// Enable global metrics collection

161

GlobalClientMetrics.setMetricsEnabled(true);

162

163

// Use global metrics during operations

164

Connection connection = DriverManager.getConnection(url);

165

Statement stmt = connection.createStatement();

166

167

// Query execution automatically updates metrics

168

long startTime = System.currentTimeMillis();

169

ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM large_table");

170

171

// Access global metrics

172

long totalQueryTime = GlobalClientMetrics.GLOBAL_QUERY_TIME.getValue();

173

long totalScanBytes = GlobalClientMetrics.GLOBAL_SCAN_BYTES.getValue();

174

175

System.out.println("Total query time across all queries: " + totalQueryTime + "ms");

176

System.out.println("Total bytes scanned: " + totalScanBytes);

177

178

// Get comprehensive metrics summary

179

Map<String, Object> summary = GlobalClientMetrics.getMetricsSummary();

180

for (Map.Entry<String, Object> entry : summary.entrySet()) {

181

System.out.println(entry.getKey() + ": " + entry.getValue());

182

}

183

184

// Generate metrics report

185

String report = GlobalClientMetrics.getMetricsReport();

186

System.out.println("=== Phoenix Metrics Report ===");

187

System.out.println(report);

188

189

// Reset metrics for new measurement period

190

GlobalClientMetrics.resetGlobalMetrics();

191

```

192

193

## Table-Level Metrics

194

195

### TableMetricsManager

196

197

Manages metrics collection for individual Phoenix tables.

198

199

```java{ .api }

200

public class TableMetricsManager {

201

// Singleton access

202

public static TableMetricsManager getInstance()

203

204

// Table metrics management

205

public TableClientMetrics getTableMetrics(String tableName)

206

public void updateTableMetrics(String tableName, MetricType metricType, long value)

207

public void resetTableMetrics(String tableName)

208

public void removeTableMetrics(String tableName)

209

210

// Bulk operations

211

public Map<String, TableClientMetrics> getAllTableMetrics()

212

public void resetAllTableMetrics()

213

public int getTrackedTableCount()

214

215

// Configuration

216

public void setMaxTrackedTables(int maxTables)

217

public boolean isTableMetricsEnabled()

218

public void setTableMetricsEnabled(boolean enabled)

219

}

220

```

221

222

### TableClientMetrics

223

224

Client-side metrics for individual Phoenix tables.

225

226

```java{ .api }

227

public class TableClientMetrics {

228

// Constructor

229

public TableClientMetrics(String tableName)

230

231

// Metric operations

232

public void incrementMetric(MetricType metricType)

233

public void incrementMetric(MetricType metricType, long delta)

234

public void updateMetric(MetricType metricType, long value)

235

236

// Metric queries

237

public long getMetricValue(MetricType metricType)

238

public Map<MetricType, Long> getAllMetrics()

239

public String getTableName()

240

241

// Statistics

242

public long getTotalQueryTime()

243

public long getTotalScanBytes()

244

public long getQueryCount()

245

public double getAverageQueryTime()

246

247

// Reset operations

248

public void reset()

249

public void resetMetric(MetricType metricType)

250

}

251

```

252

253

**Usage:**

254

```java

255

// Enable table-level metrics

256

TableMetricsManager manager = TableMetricsManager.getInstance();

257

manager.setTableMetricsEnabled(true);

258

manager.setMaxTrackedTables(100);

259

260

// Execute queries on specific tables

261

String tableName = "users";

262

Connection connection = DriverManager.getConnection(url);

263

264

// Table metrics are automatically collected during query execution

265

Statement stmt = connection.createStatement();

266

ResultSet rs = stmt.executeQuery("SELECT * FROM " + tableName + " WHERE age > 25");

267

268

// Process results...

269

while (rs.next()) {

270

// Result processing

271

}

272

273

// Access table-specific metrics

274

TableClientMetrics tableMetrics = manager.getTableMetrics(tableName);

275

long queryTime = tableMetrics.getMetricValue(MetricType.QUERY_TIME);

276

long scanBytes = tableMetrics.getMetricValue(MetricType.SCAN_BYTES);

277

long queryCount = tableMetrics.getQueryCount();

278

double avgQueryTime = tableMetrics.getAverageQueryTime();

279

280

System.out.println("Table: " + tableName);

281

System.out.println("Total query time: " + queryTime + "ms");

282

System.out.println("Total scan bytes: " + scanBytes);

283

System.out.println("Query count: " + queryCount);

284

System.out.println("Average query time: " + String.format("%.2f", avgQueryTime) + "ms");

285

286

// Get metrics for all tables

287

Map<String, TableClientMetrics> allMetrics = manager.getAllTableMetrics();

288

for (Map.Entry<String, TableClientMetrics> entry : allMetrics.entrySet()) {

289

String table = entry.getKey();

290

TableClientMetrics metrics = entry.getValue();

291

292

System.out.println("\n=== Metrics for table: " + table + " ===");

293

Map<MetricType, Long> tableMetricValues = metrics.getAllMetrics();

294

295

for (Map.Entry<MetricType, Long> metricEntry : tableMetricValues.entrySet()) {

296

System.out.println(metricEntry.getKey().getMetricName() + ": " + metricEntry.getValue());

297

}

298

}

299

300

// Reset metrics for specific table

301

manager.resetTableMetrics(tableName);

302

```

303

304

## Query-Level Monitoring

305

306

### PhoenixMonitoredConnection

307

308

Connection interface providing access to metrics and monitoring information.

309

310

```java{ .api }

311

public interface PhoenixMonitoredConnection extends Connection {

312

// Metrics access

313

ReadMetricQueue getReadMetricsQueue()

314

WriteMetricQueue getWriteMetricsQueue()

315

OverAllQueryMetrics getOverallQueryMetrics()

316

317

// Query monitoring

318

QueryLogger getQueryLogger()

319

void enableQueryLogging(boolean enable)

320

boolean isQueryLoggingEnabled()

321

322

// Connection metrics

323

ConnectionMetrics getConnectionMetrics()

324

}

325

```

326

327

### ReadMetricQueue

328

329

Queue for collecting read operation metrics during query execution.

330

331

```java{ .api }

332

public class ReadMetricQueue {

333

// Queue operations

334

public void addMetric(ReadMetric metric)

335

public ReadMetric pollMetric()

336

public List<ReadMetric> drainMetrics()

337

338

// Queue state

339

public int size()

340

public boolean isEmpty()

341

public void clear()

342

343

// Aggregated metrics

344

public long getTotalReadTime()

345

public long getTotalBytesRead()

346

public long getTotalRowsRead()

347

public int getReadOperationCount()

348

}

349

```

350

351

### WriteMetricQueue

352

353

Queue for collecting write operation metrics during mutation execution.

354

355

```java{ .api }

356

public class WriteMetricQueue {

357

// Queue operations

358

public void addMetric(WriteMetric metric)

359

public WriteMetric pollMetric()

360

public List<WriteMetric> drainMetrics()

361

362

// Queue state

363

public int size()

364

public boolean isEmpty()

365

public void clear()

366

367

// Aggregated metrics

368

public long getTotalWriteTime()

369

public long getTotalBytesWritten()

370

public long getTotalRowsWritten()

371

public int getWriteOperationCount()

372

}

373

```

374

375

**Usage:**

376

```java

377

// Access query-level monitoring

378

PhoenixConnection phoenixConn = connection.unwrap(PhoenixConnection.class);

379

PhoenixMonitoredConnection monitoredConn = (PhoenixMonitoredConnection) phoenixConn;

380

381

// Enable query logging

382

monitoredConn.enableQueryLogging(true);

383

384

// Execute monitored query

385

Statement stmt = connection.createStatement();

386

ResultSet rs = stmt.executeQuery("SELECT * FROM orders WHERE order_date > '2023-01-01'");

387

388

// Process results

389

int rowCount = 0;

390

while (rs.next()) {

391

rowCount++;

392

}

393

394

// Access read metrics

395

ReadMetricQueue readMetrics = monitoredConn.getReadMetricsQueue();

396

System.out.println("Read operations: " + readMetrics.getReadOperationCount());

397

System.out.println("Total read time: " + readMetrics.getTotalReadTime() + "ms");

398

System.out.println("Total bytes read: " + readMetrics.getTotalBytesRead());

399

System.out.println("Total rows read: " + readMetrics.getTotalRowsRead());

400

401

// Drain metrics for processing

402

List<ReadMetric> allReadMetrics = readMetrics.drainMetrics();

403

for (ReadMetric metric : allReadMetrics) {

404

System.out.println("Read operation: " + metric.toString());

405

}

406

407

// For write operations

408

PreparedStatement pstmt = connection.prepareStatement("UPSERT INTO orders VALUES (?, ?, ?)");

409

for (int i = 0; i < 1000; i++) {

410

pstmt.setLong(1, i);

411

pstmt.setString(2, "Product " + i);

412

pstmt.setBigDecimal(3, new BigDecimal(Math.random() * 1000));

413

pstmt.executeUpdate();

414

}

415

connection.commit();

416

417

// Access write metrics

418

WriteMetricQueue writeMetrics = monitoredConn.getWriteMetricsQueue();

419

System.out.println("Write operations: " + writeMetrics.getWriteOperationCount());

420

System.out.println("Total write time: " + writeMetrics.getTotalWriteTime() + "ms");

421

System.out.println("Total bytes written: " + writeMetrics.getTotalBytesWritten());

422

System.out.println("Total rows written: " + writeMetrics.getTotalRowsWritten());

423

```

424

425

## Custom Monitoring Implementation

426

427

### MetricsCollector

428

429

Custom metrics collection and reporting system.

430

431

```java

432

// Custom metrics collector for Phoenix operations

433

public class PhoenixMetricsCollector {

434

private final Map<String, QueryMetrics> queryMetrics = new ConcurrentHashMap<>();

435

private final TableMetricsManager tableManager = TableMetricsManager.getInstance();

436

private final ExecutorService reportingExecutor = Executors.newSingleThreadExecutor();

437

438

public void startMetricsCollection() {

439

// Enable all metrics

440

GlobalClientMetrics.setMetricsEnabled(true);

441

tableManager.setTableMetricsEnabled(true);

442

443

// Start periodic reporting

444

reportingExecutor.submit(this::periodicReporting);

445

}

446

447

public void recordQueryStart(String queryId, String sql, String tableName) {

448

QueryMetrics metrics = new QueryMetrics(queryId, sql, tableName);

449

metrics.setStartTime(System.currentTimeMillis());

450

queryMetrics.put(queryId, metrics);

451

}

452

453

public void recordQueryEnd(String queryId, int rowCount, boolean success) {

454

QueryMetrics metrics = queryMetrics.get(queryId);

455

if (metrics != null) {

456

metrics.setEndTime(System.currentTimeMillis());

457

metrics.setRowCount(rowCount);

458

metrics.setSuccess(success);

459

460

// Update table metrics

461

if (success) {

462

String tableName = metrics.getTableName();

463

long executionTime = metrics.getExecutionTime();

464

tableManager.updateTableMetrics(tableName, MetricType.QUERY_TIME, executionTime);

465

tableManager.updateTableMetrics(tableName, MetricType.QUERY_EXECUTED, 1);

466

} else {

467

tableManager.updateTableMetrics(metrics.getTableName(), MetricType.QUERY_FAILED, 1);

468

}

469

}

470

}

471

472

public void recordSlowQuery(String queryId, long thresholdMs) {

473

QueryMetrics metrics = queryMetrics.get(queryId);

474

if (metrics != null && metrics.getExecutionTime() > thresholdMs) {

475

System.out.println("SLOW QUERY DETECTED:");

476

System.out.println("Query ID: " + queryId);

477

System.out.println("Execution time: " + metrics.getExecutionTime() + "ms");

478

System.out.println("SQL: " + metrics.getSql());

479

System.out.println("Table: " + metrics.getTableName());

480

}

481

}

482

483

public MetricsSummary generateSummary() {

484

MetricsSummary summary = new MetricsSummary();

485

486

// Global metrics

487

Map<MetricType, Long> globalMetrics = GlobalClientMetrics.getGlobalMetrics();

488

summary.setGlobalMetrics(globalMetrics);

489

490

// Table metrics

491

Map<String, TableClientMetrics> allTableMetrics = tableManager.getAllTableMetrics();

492

summary.setTableMetrics(allTableMetrics);

493

494

// Query metrics

495

summary.setQueryMetrics(new HashMap<>(queryMetrics));

496

497

return summary;

498

}

499

500

private void periodicReporting() {

501

try {

502

while (!Thread.currentThread().isInterrupted()) {

503

Thread.sleep(60000); // Report every minute

504

505

MetricsSummary summary = generateSummary();

506

generateReport(summary);

507

508

// Clean up old query metrics (keep last hour)

509

cleanupOldMetrics();

510

}

511

} catch (InterruptedException e) {

512

Thread.currentThread().interrupt();

513

}

514

}

515

516

private void generateReport(MetricsSummary summary) {

517

System.out.println("\n=== Phoenix Metrics Report ===");

518

System.out.println("Report time: " + new Date());

519

520

// Global metrics report

521

Map<MetricType, Long> globalMetrics = summary.getGlobalMetrics();

522

System.out.println("\n--- Global Metrics ---");

523

for (Map.Entry<MetricType, Long> entry : globalMetrics.entrySet()) {

524

if (entry.getValue() > 0) {

525

System.out.println(entry.getKey().getDescription() + ": " + entry.getValue());

526

}

527

}

528

529

// Table metrics report

530

Map<String, TableClientMetrics> tableMetrics = summary.getTableMetrics();

531

System.out.println("\n--- Table Metrics ---");

532

for (Map.Entry<String, TableClientMetrics> entry : tableMetrics.entrySet()) {

533

String tableName = entry.getKey();

534

TableClientMetrics metrics = entry.getValue();

535

536

System.out.println("Table: " + tableName);

537

System.out.println(" Query count: " + metrics.getQueryCount());

538

System.out.println(" Average query time: " +

539

String.format("%.2f", metrics.getAverageQueryTime()) + "ms");

540

System.out.println(" Total scan bytes: " +

541

formatBytes(metrics.getMetricValue(MetricType.SCAN_BYTES)));

542

}

543

544

// Recent slow queries

545

System.out.println("\n--- Recent Slow Queries (>5s) ---");

546

long currentTime = System.currentTimeMillis();

547

int slowQueryCount = 0;

548

549

for (QueryMetrics queryMetrics : summary.getQueryMetrics().values()) {

550

if (queryMetrics.getExecutionTime() > 5000 &&

551

(currentTime - queryMetrics.getStartTime()) < 300000) { // Last 5 minutes

552

System.out.println("Query: " + queryMetrics.getQueryId());

553

System.out.println(" Time: " + queryMetrics.getExecutionTime() + "ms");

554

System.out.println(" Table: " + queryMetrics.getTableName());

555

System.out.println(" Rows: " + queryMetrics.getRowCount());

556

slowQueryCount++;

557

}

558

}

559

560

if (slowQueryCount == 0) {

561

System.out.println("No slow queries detected in the last 5 minutes.");

562

}

563

564

System.out.println("=== End Report ===\n");

565

}

566

567

private void cleanupOldMetrics() {

568

long cutoffTime = System.currentTimeMillis() - 3600000; // 1 hour ago

569

queryMetrics.entrySet().removeIf(entry ->

570

entry.getValue().getStartTime() < cutoffTime

571

);

572

}

573

574

private String formatBytes(long bytes) {

575

if (bytes < 1024) return bytes + " B";

576

if (bytes < 1024 * 1024) return String.format("%.2f KB", bytes / 1024.0);

577

if (bytes < 1024 * 1024 * 1024) return String.format("%.2f MB", bytes / (1024.0 * 1024.0));

578

return String.format("%.2f GB", bytes / (1024.0 * 1024.0 * 1024.0));

579

}

580

581

public void shutdown() {

582

reportingExecutor.shutdown();

583

try {

584

if (!reportingExecutor.awaitTermination(5, TimeUnit.SECONDS)) {

585

reportingExecutor.shutdownNow();

586

}

587

} catch (InterruptedException e) {

588

reportingExecutor.shutdownNow();

589

Thread.currentThread().interrupt();

590

}

591

}

592

}

593

594

// Supporting classes

595

public class QueryMetrics {

596

private final String queryId;

597

private final String sql;

598

private final String tableName;

599

private long startTime;

600

private long endTime;

601

private int rowCount;

602

private boolean success;

603

604

public QueryMetrics(String queryId, String sql, String tableName) {

605

this.queryId = queryId;

606

this.sql = sql;

607

this.tableName = tableName;

608

}

609

610

public long getExecutionTime() {

611

return endTime - startTime;

612

}

613

614

// Getters and setters

615

public String getQueryId() { return queryId; }

616

public String getSql() { return sql; }

617

public String getTableName() { return tableName; }

618

public long getStartTime() { return startTime; }

619

public void setStartTime(long startTime) { this.startTime = startTime; }

620

public long getEndTime() { return endTime; }

621

public void setEndTime(long endTime) { this.endTime = endTime; }

622

public int getRowCount() { return rowCount; }

623

public void setRowCount(int rowCount) { this.rowCount = rowCount; }

624

public boolean isSuccess() { return success; }

625

public void setSuccess(boolean success) { this.success = success; }

626

}

627

628

public class MetricsSummary {

629

private Map<MetricType, Long> globalMetrics;

630

private Map<String, TableClientMetrics> tableMetrics;

631

private Map<String, QueryMetrics> queryMetrics;

632

633

// Getters and setters

634

public Map<MetricType, Long> getGlobalMetrics() { return globalMetrics; }

635

public void setGlobalMetrics(Map<MetricType, Long> globalMetrics) { this.globalMetrics = globalMetrics; }

636

public Map<String, TableClientMetrics> getTableMetrics() { return tableMetrics; }

637

public void setTableMetrics(Map<String, TableClientMetrics> tableMetrics) { this.tableMetrics = tableMetrics; }

638

public Map<String, QueryMetrics> getQueryMetrics() { return queryMetrics; }

639

public void setQueryMetrics(Map<String, QueryMetrics> queryMetrics) { this.queryMetrics = queryMetrics; }

640

}

641

```

642

643

### Usage Example

644

645

```java

646

// Integration with Phoenix application

647

public class MonitoredPhoenixApplication {

648

private final PhoenixMetricsCollector metricsCollector = new PhoenixMetricsCollector();

649

private final Connection connection;

650

651

public MonitoredPhoenixApplication(String phoenixUrl) throws SQLException {

652

this.connection = DriverManager.getConnection(phoenixUrl);

653

metricsCollector.startMetricsCollection();

654

}

655

656

public void executeQuery(String sql, String tableName) throws SQLException {

657

String queryId = UUID.randomUUID().toString();

658

659

// Record query start

660

metricsCollector.recordQueryStart(queryId, sql, tableName);

661

662

try {

663

Statement stmt = connection.createStatement();

664

ResultSet rs = stmt.executeQuery(sql);

665

666

int rowCount = 0;

667

while (rs.next()) {

668

rowCount++;

669

// Process row

670

}

671

672

// Record successful completion

673

metricsCollector.recordQueryEnd(queryId, rowCount, true);

674

675

// Check for slow queries

676

metricsCollector.recordSlowQuery(queryId, 1000); // 1 second threshold

677

678

rs.close();

679

stmt.close();

680

681

} catch (SQLException e) {

682

// Record failed query

683

metricsCollector.recordQueryEnd(queryId, 0, false);

684

throw e;

685

}

686

}

687

688

public void generateMetricsReport() {

689

MetricsSummary summary = metricsCollector.generateSummary();

690

// Process summary as needed

691

}

692

693

public void close() throws SQLException {

694

metricsCollector.shutdown();

695

connection.close();

696

}

697

698

public static void main(String[] args) throws SQLException {

699

MonitoredPhoenixApplication app = new MonitoredPhoenixApplication("jdbc:phoenix:localhost:2181");

700

701

try {

702

// Execute various queries

703

app.executeQuery("SELECT COUNT(*) FROM users", "users");

704

app.executeQuery("SELECT * FROM orders WHERE order_date > '2023-01-01'", "orders");

705

app.executeQuery("SELECT customer_id, SUM(amount) FROM transactions GROUP BY customer_id", "transactions");

706

707

// Generate report

708

app.generateMetricsReport();

709

710

} finally {

711

app.close();

712

}

713

}

714

}

715

```