CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-prometheus--simpleclient

Core instrumentation library for the Prometheus Java client, providing fundamental metric types for application monitoring

Pending
Overview
Eval results
Files

summary.mddocs/

Summary Metrics

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.

Capabilities

Summary Creation

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

/**
 * Create a new Summary builder
 * @return Builder instance for configuration
 */
public static Summary.Builder build();

/**
 * Create a new Summary builder with required fields
 * @param name The metric name (without _count/_sum suffixes)
 * @param help The help text describing the metric
 * @return Builder instance for configuration
 */
public static Summary.Builder build(String name, String help);

Usage Example:

import io.prometheus.client.Summary;

// Basic summary (count and sum only)
Summary requestLatency = Summary.build()
    .name("request_latency_seconds")
    .help("Request latency in seconds")
    .register();

// Summary with quantiles
Summary responseTime = Summary.build()
    .name("response_time_seconds")
    .help("Response time distribution")
    .quantile(0.5, 0.01)    // 50th percentile ±1%
    .quantile(0.95, 0.005)  // 95th percentile ±0.5%
    .quantile(0.99, 0.001)  // 99th percentile ±0.1%
    .register();

Summary Builder Configuration

Configure summary quantiles, time windows, and sampling parameters.

public static class Builder extends SimpleCollector.Builder<Builder, Summary> {
    /**
     * Add a quantile to track with specified error tolerance
     * @param quantile Quantile to track (0.0 to 1.0)
     * @param error Allowed error for quantile calculation
     * @return Builder for method chaining
     * @throws IllegalArgumentException if quantile not in [0,1] or error negative
     */
    public Builder quantile(double quantile, double error);
    
    /**
     * Set the maximum age of observations in seconds
     * @param ageSeconds Age in seconds (default: 600)
     * @return Builder for method chaining
     */
    public Builder maxAgeSeconds(long ageSeconds);
    
    /**
     * Set number of age buckets for sliding time window
     * @param ageBuckets Number of buckets (default: 5)
     * @return Builder for method chaining
     */
    public Builder ageBuckets(int ageBuckets);
}

Usage Examples:

// High-precision summary with custom time window
Summary preciseLatency = Summary.build()
    .name("precise_latency_seconds")
    .help("High precision latency tracking")
    .quantile(0.50, 0.01)   // Median ±1%
    .quantile(0.90, 0.005)  // 90th percentile ±0.5%
    .quantile(0.95, 0.005)  // 95th percentile ±0.5%
    .quantile(0.99, 0.001)  // 99th percentile ±0.1%
    .maxAgeSeconds(300)     // 5-minute window
    .ageBuckets(5)          // 5 buckets = 1 minute each
    .register();

// Min/max tracking (special cases with zero error)
Summary minMax = Summary.build()
    .name("processing_duration_seconds")
    .help("Processing duration with min/max")
    .quantile(0.0, 0.0)     // Minimum (no extra memory)
    .quantile(1.0, 0.0)     // Maximum (no extra memory)
    .quantile(0.5, 0.01)    // Median ±1%
    .register();

Summary Observations

Record values in summary metrics for quantile and statistical calculations.

/**
 * Record an observation in the summary
 * @param amt Value to observe
 */
public void observe(double amt);

Usage Examples:

// Basic observations
requestLatency.observe(0.123);  // 123ms request
responseTime.observe(0.045);    // 45ms response
responseTime.observe(1.234);    // 1.234s slower response

// Processing different types of operations
Summary operationDuration = Summary.build()
    .name("operation_duration_seconds")
    .help("Operation processing time")
    .labelNames("operation_type")
    .quantile(0.5, 0.01)
    .quantile(0.95, 0.005)
    .register();

operationDuration.labels("database_query").observe(0.025);
operationDuration.labels("file_write").observe(0.150);
operationDuration.labels("network_call").observe(0.300);

Timer Operations

Use summaries for automatic duration measurement and timing operations.

/**
 * Start a timer for duration measurement
 * @return Timer instance for duration tracking
 */
public Timer startTimer();

/**
 * Time a Runnable execution and observe duration
 * @param timeable Code to time
 * @return Duration in seconds
 */
public double time(Runnable timeable);

/**
 * Time a Callable execution and observe duration
 * @param timeable Code to time
 * @return Result from callable
 * @throws RuntimeException if callable throws exception
 */
public <E> E time(Callable<E> timeable);

Summary Timer Class

Timer provides duration measurement capabilities for summary metrics.

public static class Timer implements Closeable {
    /**
     * Observe elapsed duration since timer start
     * @return Elapsed duration in seconds
     */
    public double observeDuration();
    
    /**
     * Equivalent to observeDuration() - implements Closeable
     */
    public void close();
}

Usage Examples:

// Manual timer usage
Summary.Timer timer = requestLatency.startTimer();
try {
    processRequest();
} finally {
    double duration = timer.observeDuration();
    System.out.println("Request took: " + duration + " seconds");
}

// Try-with-resources timer
try (Summary.Timer timer = requestLatency.startTimer()) {
    processRequest(); // Automatically observes duration on close
}

// Lambda timing
double duration = requestLatency.time(() -> {
    processRequest();
});

// Timing with return value
String result = requestLatency.time(() -> {
    return generateResponse();
});

// Batch processing timing
Summary batchProcessing = Summary.build()
    .name("batch_processing_seconds")
    .help("Batch processing duration")
    .quantile(0.5, 0.01)
    .quantile(0.95, 0.005)
    .register();

List<String> results = batchProcessing.time(() -> {
    return processBatch();
});

Labeled Summary Operations

Work with multi-dimensional summaries using label values.

/**
 * Get summary child for specific label values
 * @param labelValues Values for each label name (must match count)
 * @return Summary.Child instance for the label combination
 * @throws IllegalArgumentException if wrong number of labels
 */
public Summary.Child labels(String... labelValues);

/**
 * Remove summary child for specific label values
 * @param labelValues Values identifying the child to remove
 */
public void remove(String... labelValues);

/**
 * Remove all summary children
 */
public void clear();

Summary Child Operations

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

public static class Child {
    /** Record observation in child summary */
    public void observe(double amt);
    
    /** Start timer for child summary */
    public Timer startTimer();
    
    /** Time operations for child summary */
    public double time(Runnable timeable);
    public <E> E time(Callable<E> timeable);
    
    /** Get summary data snapshot */
    public Value get();
}

Summary Value Data

Access summary count, sum, and quantile data.

public static class Value {
    /** Total number of observations */
    public final long count;
    
    /** Sum of all observed values */
    public final double sum;
    
    /** Map of quantile values (quantile -> value) */
    public final SortedMap<Double, Double> quantiles;
}

Usage Example:

// API endpoint monitoring
Summary apiLatency = Summary.build()
    .name("api_endpoint_duration_seconds")
    .help("API endpoint response time")
    .labelNames("endpoint", "method", "status")
    .quantile(0.5, 0.01)   // Median
    .quantile(0.95, 0.005) // 95th percentile
    .quantile(0.99, 0.001) // 99th percentile
    .register();

// Track different endpoints
Summary.Child getUserLatency = apiLatency.labels("/users", "GET", "200");
Summary.Child postUserLatency = apiLatency.labels("/users", "POST", "201");

// Time requests
getUserLatency.time(() -> handleGetUser());
postUserLatency.observe(0.156); // Manual observation

// Access summary statistics
Summary.Child.Value stats = getUserLatency.get();
System.out.println("Total requests: " + stats.count);
System.out.println("Average latency: " + (stats.sum / stats.count));
System.out.println("95th percentile: " + stats.quantiles.get(0.95));

Important Notes

Quantile Configuration

Quantile Range: Must be between 0.0 and 1.0

  • 0.0 = minimum value (special case, no extra memory)
  • 0.5 = median (50th percentile)
  • 0.95 = 95th percentile
  • 0.99 = 99th percentile
  • 1.0 = maximum value (special case, no extra memory)

Error Tolerance: Controls precision vs memory usage

  • 0.01 = ±1% error (good for most use cases)
  • 0.005 = ±0.5% error (higher precision)
  • 0.001 = ±0.1% error (very high precision)
  • 0.0 = exact tracking (uses more memory)

Time Window Behavior

Summary uses a sliding time window:

  • maxAgeSeconds: Total window duration (default: 10 minutes)
  • ageBuckets: Number of sub-windows (default: 5 buckets)
  • Window slides forward every maxAgeSeconds / ageBuckets interval
  • Old observations are automatically discarded

Example with defaults:

  • 10-minute total window
  • 5 buckets = 2-minute intervals
  • Window slides every 2 minutes

Memory Usage

  • Count and sum use minimal memory
  • Each quantile uses approximately 100 samples regardless of observation count
  • Min (0.0) and max (1.0) quantiles are memory-optimized special cases
  • Choose error tolerance based on precision needs vs memory constraints

Summary vs Histogram

Use Summary when:

  • You need precise quantiles (e.g., SLA monitoring)
  • You don't know the distribution shape in advance
  • You want automatic memory management
  • You need client-side quantile calculation

Use Histogram when:

  • You need server-side quantile calculation
  • You want to aggregate across multiple instances
  • You know appropriate bucket boundaries
  • You need Prometheus alerting on buckets

Common Patterns

// SLA monitoring
Summary slaLatency = Summary.build()
    .name("sla_response_time_seconds")
    .help("Response time for SLA monitoring")
    .quantile(0.95, 0.01)  // 95% of requests under X seconds
    .quantile(0.99, 0.005) // 99% of requests under Y seconds
    .maxAgeSeconds(300)    // 5-minute sliding window
    .register();

// Database query performance
Summary dbQueries = Summary.build()
    .name("database_query_duration_seconds")
    .help("Database query performance")
    .labelNames("query_type", "table")
    .quantile(0.5, 0.01)   // Median
    .quantile(0.9, 0.005)  // 90th percentile
    .quantile(0.99, 0.001) // 99th percentile
    .register();

// Batch processing monitoring
Summary batchJobs = Summary.build()
    .name("batch_job_duration_seconds")
    .help("Batch job processing time")
    .labelNames("job_type")
    .quantile(0.0, 0.0)    // Minimum (free)
    .quantile(0.5, 0.01)   // Median
    .quantile(1.0, 0.0)    // Maximum (free)
    .register();

Install with Tessl CLI

npx tessl i tessl/maven-io-prometheus--simpleclient

docs

counter.md

enumeration.md

exemplars.md

gauge.md

histogram.md

index.md

info.md

registry.md

summary.md

tile.json