CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-amazonaws--aws-java-sdk-core

Core foundational library for AWS SDK for Java 1.x providing authentication, HTTP transport, regions, protocols, and shared utilities for all AWS service clients

Pending
Overview
Eval results
Files

metrics-monitoring.mddocs/

Metrics & Monitoring

The AWS Java SDK Core provides comprehensive metrics collection and monitoring capabilities, including client-side monitoring (CSM), request metrics, JMX integration, and custom metric collection for performance analysis and operational insights.

Core Metrics Framework

SDK Metrics

// Main SDK metrics class
class AwsSdkMetrics {
    // Global metrics control
    public static boolean isDefaultMetricsEnabled();
    public static void setDefaultMetricsEnabled(boolean enabled);
    
    // Request metric collector management
    public static RequestMetricCollector getRequestMetricCollector();
    public static void setRequestMetricCollector(RequestMetricCollector requestMetricCollector);
    
    // Machine metrics
    public static boolean isMachineMetricExcluded(MetricType metricType);
    public static void setMachineMetricExcluded(MetricType metricType, boolean exclude);
    
    // Predefined collectors
    public static final RequestMetricCollector NONE;
}

// Request metric collector interface
interface RequestMetricCollector {
    void collectMetrics(Request<?> request, Response<?> response);
    void collectMetrics(Request<?> request, Response<?> response, Exception exception);
    
    // Default implementation
    RequestMetricCollector NONE = new RequestMetricCollector() {
        public void collectMetrics(Request<?> request, Response<?> response) {}
        public void collectMetrics(Request<?> request, Response<?> response, Exception exception) {}
    };
}

Metric Types

// Base metric type interface
interface MetricType {
    String name();
}

// Request metric types enumeration
enum RequestMetricType implements MetricType {
    // HTTP client metrics
    HttpClientRetryCount("HttpClientRetryCount"),
    HttpClientPoolAvailableCount("HttpClientPoolAvailableCount"), 
    HttpClientPoolLeasedCount("HttpClientPoolLeasedCount"),
    HttpClientPoolPendingCount("HttpClientPoolPendingCount"),
    
    // Timing metrics
    HttpRequestTime("HttpRequestTime"),
    HttpResponseTime("HttpResponseTime"), 
    ResponseProcessingTime("ResponseProcessingTime"),
    RequestExecutionTime("RequestExecutionTime"),
    RequestSigningTime("RequestSigningTime"),
    
    // Data transfer metrics
    RequestCount("RequestCount"),
    RetryCount("RetryCount"),
    ThrottledRetryCount("ThrottledRetryCount"),
    ResponseSize("ResponseSize"),
    RequestSize("RequestSize"),
    
    // Error metrics
    ClientExecuteTime("ClientExecuteTime"),
    Exception("Exception"),
    ThrottleException("ThrottleException");
    
    private final String metricName;
    
    RequestMetricType(String metricName) {
        this.metricName = metricName;
    }
    
    public String name() {
        return metricName;
    }
}

// Service-specific metric type interface
interface ServiceMetricType extends MetricType {
    String getServiceName();
}

// Simple service metric implementation
class SimpleServiceMetricType implements ServiceMetricType {
    public SimpleServiceMetricType(String metricName, String serviceName);
    public String name();
    public String getServiceName();
}

// Throughput metric type interface
interface ThroughputMetricType extends MetricType {
    // Marker interface for throughput metrics
}

// Simple throughput metric implementation
class SimpleThroughputMetricType implements ThroughputMetricType {
    public SimpleThroughputMetricType(String metricName);
    public String name();
}

Metrics Administration

Metrics Admin Interface

// Administrative interface for metrics
interface MetricAdmin {
    // Region management
    String getRegion();
    void setRegion(String region);
    
    // Metric collection control
    boolean isEnabled();
    void setEnabled(boolean enabled);
    
    // Queue management
    Integer getRequestMetricQueueSize();
    void setRequestMetricQueueSize(Integer requestMetricQueueSize);
    
    // Predicate management
    String getRequestMetricQueueSizePredicate();
    void setRequestMetricQueueSizePredicate(String requestMetricQueueSizePredicate);
    
    // Host management
    String getMetricNameSpace();
    void setMetricNameSpace(String metricNameSpace);
    
    String getJvmMetricName();
    void setJvmMetricName(String jvmMetricName);
    
    String getHostMetricName();
    void setHostMetricName(String hostMetricName);
    
    // Credential provider
    String getCredentialProvider();
    void setCredentialProvider(String credentialProvider);
}

// JMX MBean for metrics administration
interface MetricAdminMBean extends MetricAdmin {
    // Inherits all MetricAdmin methods for JMX exposure
}

// Service latency provider interface
interface ServiceLatencyProvider {
    Double getServiceLatency(ServiceMetricType serviceMetricType);
    int getSampleCount(ServiceMetricType serviceMetricType);
    boolean isEnabled();
}

Metrics Collection

Specialized Metric Streams

// Input stream with metrics collection
class MetricFilterInputStream extends FilterInputStream {
    public MetricFilterInputStream(InputStream in);
    
    public int read() throws IOException;
    public int read(byte[] b, int off, int len) throws IOException;
    public long skip(long n) throws IOException;
    public void close() throws IOException;
    
    // Metrics access
    public long getBytesRead();
    public long getReadCount();
}

// HTTP entity with metrics collection
class MetricInputStreamEntity extends InputStreamEntity {
    public MetricInputStreamEntity(InputStream instream, long length);
    public MetricInputStreamEntity(InputStream instream, long length, ContentType contentType);
    
    public InputStream getContent() throws IOException;
    public void writeTo(OutputStream outstream) throws IOException;
    
    // Metrics access
    public long getBytesRead();
    public long getBytesWritten();
}

Client-Side Monitoring (CSM)

Monitoring Events

// Base class for monitoring events
abstract class MonitoringEvent {
    public abstract String toJsonString();
    public abstract MonitoringEvent withTimestamp(Date timestamp);
    
    public Date getTimestamp();
    public String getVersion();
    public String getUserAgent();
}

// Monitoring event for API calls
class ApiCallMonitoringEvent extends MonitoringEvent {
    // Service information
    public ApiCallMonitoringEvent withService(String service);
    public ApiCallMonitoringEvent withApi(String api);
    public ApiCallMonitoringEvent withVersion(int version);
    public ApiCallMonitoringEvent withUserAgent(String userAgent);
    public ApiCallMonitoringEvent withRegion(String region);
    
    // Timing information
    public ApiCallMonitoringEvent withTimestamp(Date timestamp);
    public ApiCallMonitoringEvent withLatency(Integer latency);
    
    // Attempt information
    public ApiCallMonitoringEvent withAttemptCount(Integer attemptCount);
    public ApiCallMonitoringEvent withMaxRetriesExceeded(Integer maxRetriesExceeded);
    
    // Result information
    public ApiCallMonitoringEvent withFinalHttpStatusCode(Integer finalHttpStatusCode);
    public ApiCallMonitoringEvent withFinalAwsException(String finalAwsException);
    public ApiCallMonitoringEvent withFinalAwsExceptionMessage(String finalAwsExceptionMessage);
    public ApiCallMonitoringEvent withFinalSdkException(String finalSdkException);
    public ApiCallMonitoringEvent withFinalSdkExceptionMessage(String finalSdkExceptionMessage);
    
    // Getters
    public String getService();
    public String getApi();
    public Integer getVersion();
    public String getRegion();
    public Integer getLatency();
    public Integer getAttemptCount();
    public Integer getMaxRetriesExceeded();
    public Integer getFinalHttpStatusCode();
    public String getFinalAwsException();
    public String getFinalAwsExceptionMessage();
    public String getFinalSdkException();
    public String getFinalSdkExceptionMessage();
    
    public String toJsonString();
}

// Monitoring event for API call attempts
class ApiCallAttemptMonitoringEvent extends MonitoringEvent {
    // Service information
    public ApiCallAttemptMonitoringEvent withService(String service);
    public ApiCallAttemptMonitoringEvent withApi(String api);
    public ApiCallAttemptMonitoringEvent withVersion(int version);
    public ApiCallAttemptMonitoringEvent withUserAgent(String userAgent);
    public ApiCallAttemptMonitoringEvent withRegion(String region);
    
    // Timing information
    public ApiCallAttemptMonitoringEvent withTimestamp(Date timestamp);
    public ApiCallAttemptMonitoringEvent withLatency(Integer latency);
    
    // Attempt information
    public ApiCallAttemptMonitoringEvent withAttemptLatency(Integer attemptLatency);
    public ApiCallAttemptMonitoringEvent withFqdn(String fqdn);
    
    // HTTP information  
    public ApiCallAttemptMonitoringEvent withHttpStatusCode(Integer httpStatusCode);
    public ApiCallAttemptMonitoringEvent withAwsException(String awsException);
    public ApiCallAttemptMonitoringEvent withAwsExceptionMessage(String awsExceptionMessage);
    public ApiCallAttemptMonitoringEvent withSdkException(String sdkException);
    public ApiCallAttemptMonitoringEvent withSdkExceptionMessage(String sdkExceptionMessage);
    
    // Getters
    public String getService();
    public String getApi(); 
    public Integer getVersion();
    public String getRegion();
    public Integer getLatency();
    public Integer getAttemptLatency();
    public String getFqdn();
    public Integer getHttpStatusCode();
    public String getAwsException();
    public String getAwsExceptionMessage();
    public String getSdkException();
    public String getSdkExceptionMessage();
    
    public String toJsonString();
}

CSM Configuration

// Client-side monitoring configuration
class CsmConfiguration {
    // Configuration parameters
    public CsmConfiguration withEnabled(boolean enabled);
    public CsmConfiguration withHost(String host);
    public CsmConfiguration withPort(int port);
    public CsmConfiguration withClientId(String clientId);
    
    // Getters
    public boolean isEnabled();
    public String getHost();
    public int getPort();
    public String getClientId();
    
    // Default values
    public static final String DEFAULT_HOST = "127.0.0.1";
    public static final int DEFAULT_PORT = 31000;
    public static final boolean DEFAULT_ENABLED = false;
}

// CSM configuration provider interface
interface CsmConfigurationProvider {
    CsmConfiguration getConfiguration() throws SdkClientException;
}

// CSM configuration provider chain
class CsmConfigurationProviderChain implements CsmConfigurationProvider {
    public CsmConfigurationProviderChain(CsmConfigurationProvider... providers);
    public CsmConfiguration getConfiguration() throws SdkClientException;
}

// Static CSM configuration provider
class StaticCsmConfigurationProvider implements CsmConfigurationProvider {
    public StaticCsmConfigurationProvider(CsmConfiguration configuration);
    public CsmConfiguration getConfiguration();
}

// Default CSM configuration provider chain
class DefaultCsmConfigurationProviderChain extends CsmConfigurationProviderChain {
    public static DefaultCsmConfigurationProviderChain getInstance();
    public CsmConfiguration getConfiguration() throws SdkClientException;
}

Usage Examples

Basic Metrics Collection

import com.amazonaws.metrics.*;
import com.amazonaws.*;

// Enable default metrics collection
AwsSdkMetrics.setDefaultMetricsEnabled(true);

// Check if metrics are enabled
boolean metricsEnabled = AwsSdkMetrics.isDefaultMetricsEnabled();
System.out.println("Metrics enabled: " + metricsEnabled);

// Get current metric collector
RequestMetricCollector collector = AwsSdkMetrics.getRequestMetricCollector();
System.out.println("Current collector: " + collector.getClass().getSimpleName());

Custom Request Metric Collector

import com.amazonaws.metrics.*;
import com.amazonaws.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

public class CustomMetricCollector implements RequestMetricCollector {
    private final Map<MetricType, AtomicLong> counters = new ConcurrentHashMap<>();
    private final Map<MetricType, AtomicLong> timings = new ConcurrentHashMap<>();
    
    @Override
    public void collectMetrics(Request<?> request, Response<?> response) {
        // Collect successful request metrics
        incrementCounter(RequestMetricType.RequestCount);
        
        if (response != null && response.getAwsResponse() != null) {
            // Track response processing time
            Long processingTime = getTimingValue(request, RequestMetricType.ResponseProcessingTime);
            if (processingTime != null) {
                addTiming(RequestMetricType.ResponseProcessingTime, processingTime);
            }
            
            // Track HTTP response time
            Long httpTime = getTimingValue(request, RequestMetricType.HttpResponseTime);
            if (httpTime != null) {
                addTiming(RequestMetricType.HttpResponseTime, httpTime);
            }
        }
    }
    
    @Override
    public void collectMetrics(Request<?> request, Response<?> response, Exception exception) {
        // Collect error metrics
        incrementCounter(RequestMetricType.Exception);
        
        if (exception instanceof AmazonServiceException) {
            AmazonServiceException ase = (AmazonServiceException) exception;
            if (ase.getErrorCode() != null && ase.getErrorCode().contains("Throttl")) {
                incrementCounter(RequestMetricType.ThrottleException);
            }
        }
        
        // Track retry count
        Integer retryCount = getRetryCount(request);
        if (retryCount != null && retryCount > 0) {
            addTiming(RequestMetricType.RetryCount, retryCount.longValue());
        }
    }
    
    private void incrementCounter(MetricType metricType) {
        counters.computeIfAbsent(metricType, k -> new AtomicLong(0)).incrementAndGet();
    }
    
    private void addTiming(MetricType metricType, long value) {
        timings.computeIfAbsent(metricType, k -> new AtomicLong(0)).addAndGet(value);
    }
    
    private Long getTimingValue(Request<?> request, MetricType metricType) {
        // Extract timing values from request context
        // Implementation depends on specific metric collection setup
        return null;
    }
    
    private Integer getRetryCount(Request<?> request) {
        // Extract retry count from request
        // Implementation depends on request context setup
        return null;
    }
    
    // Metrics reporting methods
    public long getCounter(MetricType metricType) {
        AtomicLong counter = counters.get(metricType);
        return counter != null ? counter.get() : 0;
    }
    
    public long getTiming(MetricType metricType) {
        AtomicLong timing = timings.get(metricType);
        return timing != null ? timing.get() : 0;
    }
    
    public void printMetrics() {
        System.out.println("=== Request Metrics ===");
        
        for (Map.Entry<MetricType, AtomicLong> entry : counters.entrySet()) {
            System.out.println(entry.getKey().name() + ": " + entry.getValue().get());
        }
        
        System.out.println("=== Timing Metrics ===");
        for (Map.Entry<MetricType, AtomicLong> entry : timings.entrySet()) {
            System.out.println(entry.getKey().name() + ": " + entry.getValue().get() + "ms");
        }
    }
}

// Use custom collector
CustomMetricCollector customCollector = new CustomMetricCollector();
AwsSdkMetrics.setRequestMetricCollector(customCollector);

// After some AWS operations...
customCollector.printMetrics();

Service-Specific Metrics

import com.amazonaws.metrics.*;

// Define service-specific metrics
ServiceMetricType s3PutObjectMetric = new SimpleServiceMetricType("PutObjectLatency", "S3");
ServiceMetricType dynamoQueryMetric = new SimpleServiceMetricType("QueryLatency", "DynamoDB");
ThroughputMetricType uploadThroughput = new SimpleThroughputMetricType("UploadThroughput");

// Custom service metric collector
public class ServiceMetricCollector implements RequestMetricCollector {
    private final Map<ServiceMetricType, List<Double>> serviceLatencies = new ConcurrentHashMap<>();
    
    @Override
    public void collectMetrics(Request<?> request, Response<?> response) {
        String serviceName = extractServiceName(request);
        String operationName = extractOperationName(request);
        Long latency = extractLatency(request);
        
        if (serviceName != null && operationName != null && latency != null) {
            ServiceMetricType metricType = new SimpleServiceMetricType(
                operationName + "Latency", serviceName
            );
            
            serviceLatencies.computeIfAbsent(metricType, k -> new ArrayList<>())
                           .add(latency.doubleValue());
        }
    }
    
    @Override
    public void collectMetrics(Request<?> request, Response<?> response, Exception exception) {
        // Handle error metrics for services
        String serviceName = extractServiceName(request);
        if (serviceName != null) {
            ServiceMetricType errorMetric = new SimpleServiceMetricType(
                "ErrorCount", serviceName
            );
            // Track error counts...
        }
    }
    
    public double getAverageLatency(ServiceMetricType metricType) {
        List<Double> latencies = serviceLatencies.get(metricType);
        if (latencies == null || latencies.isEmpty()) {
            return 0.0;
        }
        return latencies.stream().mapToDouble(Double::doubleValue).average().orElse(0.0);
    }
    
    public double getMaxLatency(ServiceMetricType metricType) {
        List<Double> latencies = serviceLatencies.get(metricType);
        if (latencies == null || latencies.isEmpty()) {
            return 0.0;
        }
        return latencies.stream().mapToDouble(Double::doubleValue).max().orElse(0.0);
    }
    
    private String extractServiceName(Request<?> request) {
        // Extract service name from request
        return request.getServiceName();
    }
    
    private String extractOperationName(Request<?> request) {
        // Extract operation name from request
        return request.getOriginalRequest().getClass().getSimpleName();
    }
    
    private Long extractLatency(Request<?> request) {
        // Extract latency from request timing
        // Implementation depends on request context
        return null;
    }
}

Client-Side Monitoring Setup

import com.amazonaws.monitoring.*;

// Enable CSM via environment variables or system properties
// Environment: AWS_CSM_ENABLED=true, AWS_CSM_PORT=31000, AWS_CSM_HOST=127.0.0.1

// Programmatic CSM configuration
CsmConfiguration csmConfig = new CsmConfiguration()
    .withEnabled(true)
    .withHost("127.0.0.1") 
    .withPort(31000)
    .withClientId("my-application");

// Static CSM configuration provider
CsmConfigurationProvider staticProvider = new StaticCsmConfigurationProvider(csmConfig);

// Use default provider chain (checks env vars, system properties, etc.)
CsmConfigurationProvider defaultProvider = DefaultCsmConfigurationProviderChain.getInstance();

try {
    CsmConfiguration resolvedConfig = defaultProvider.getConfiguration();
    System.out.println("CSM enabled: " + resolvedConfig.isEnabled());
    System.out.println("CSM host: " + resolvedConfig.getHost());
    System.out.println("CSM port: " + resolvedConfig.getPort());
} catch (SdkClientException e) {
    System.err.println("CSM configuration error: " + e.getMessage());
}

Monitoring Event Creation

import com.amazonaws.monitoring.*;
import java.util.Date;

// Create API call monitoring event
ApiCallMonitoringEvent apiCallEvent = new ApiCallMonitoringEvent()
    .withService("S3")
    .withApi("PutObject")
    .withVersion(1)
    .withRegion("us-east-1")
    .withTimestamp(new Date())
    .withLatency(150)
    .withAttemptCount(1)
    .withFinalHttpStatusCode(200);

String apiCallJson = apiCallEvent.toJsonString();
System.out.println("API Call Event: " + apiCallJson);

// Create API call attempt monitoring event  
ApiCallAttemptMonitoringEvent attemptEvent = new ApiCallAttemptMonitoringEvent()
    .withService("S3")
    .withApi("PutObject")
    .withVersion(1)
    .withRegion("us-east-1")
    .withTimestamp(new Date())
    .withLatency(150)
    .withAttemptLatency(145)
    .withFqdn("s3.amazonaws.com")
    .withHttpStatusCode(200);

String attemptJson = attemptEvent.toJsonString();
System.out.println("Attempt Event: " + attemptJson);

Metrics Stream Collection

import com.amazonaws.metrics.*;
import java.io.*;

// Wrap input stream with metrics collection
InputStream originalStream = new FileInputStream("large-file.dat");
MetricFilterInputStream metricsStream = new MetricFilterInputStream(originalStream);

try {
    // Read from the stream
    byte[] buffer = new byte[8192];
    int totalBytes = 0;
    int bytesRead;
    
    while ((bytesRead = metricsStream.read(buffer)) != -1) {
        totalBytes += bytesRead;
        // Process data...
    }
    
    // Get metrics after reading
    long totalBytesRead = metricsStream.getBytesRead();
    long readOperations = metricsStream.getReadCount();
    
    System.out.println("Total bytes read: " + totalBytesRead);
    System.out.println("Read operations: " + readOperations);
    System.out.println("Average bytes per read: " + (totalBytesRead / readOperations));
    
} finally {
    metricsStream.close();
}

// HTTP entity with metrics  
InputStream entityStream = new ByteArrayInputStream("HTTP entity content".getBytes());
MetricInputStreamEntity metricsEntity = new MetricInputStreamEntity(entityStream, -1);

// Use in HTTP request...
ByteArrayOutputStream output = new ByteArrayOutputStream();
metricsEntity.writeTo(output);

System.out.println("Bytes written: " + metricsEntity.getBytesWritten());

JMX Integration

import com.amazonaws.metrics.*;
import javax.management.*;
import java.lang.management.ManagementFactory;

// Custom metrics MBean implementation
public class CustomMetricsMBean implements MetricAdminMBean {
    private boolean enabled = true;
    private String region = "us-east-1";
    private Integer queueSize = 1000;
    
    @Override
    public String getRegion() { return region; }
    
    @Override
    public void setRegion(String region) { this.region = region; }
    
    @Override
    public boolean isEnabled() { return enabled; }
    
    @Override
    public void setEnabled(boolean enabled) { 
        this.enabled = enabled;
        AwsSdkMetrics.setDefaultMetricsEnabled(enabled);
    }
    
    @Override
    public Integer getRequestMetricQueueSize() { return queueSize; }
    
    @Override
    public void setRequestMetricQueueSize(Integer queueSize) { 
        this.queueSize = queueSize;
    }
    
    // Implement other MetricAdmin methods...
    public String getRequestMetricQueueSizePredicate() { return null; }
    public void setRequestMetricQueueSizePredicate(String predicate) {}
    public String getMetricNameSpace() { return "AWS/SDK"; }
    public void setMetricNameSpace(String nameSpace) {}
    public String getJvmMetricName() { return "JVM"; }
    public void setJvmMetricName(String name) {}
    public String getHostMetricName() { return "Host"; }
    public void setHostMetricName(String name) {}
    public String getCredentialProvider() { return "DefaultProvider"; }
    public void setCredentialProvider(String provider) {}
}

// Register MBean
try {
    MBeanServer server = ManagementFactory.getPlatformMBeanServer();
    ObjectName objectName = new ObjectName("com.amazonaws.metrics:type=MetricsAdmin");
    CustomMetricsMBean mbean = new CustomMetricsMBean();
    
    if (!server.isRegistered(objectName)) {
        server.registerMBean(mbean, objectName);
        System.out.println("Metrics MBean registered successfully");
    }
} catch (Exception e) {
    System.err.println("Failed to register metrics MBean: " + e.getMessage());
}

Best Practices

  1. Performance Impact: Be aware that metrics collection adds overhead; enable only necessary metrics in production.

  2. Memory Management: Implement bounded collections for metric storage to prevent memory leaks.

  3. Aggregation: Aggregate metrics over time windows rather than storing individual data points.

  4. Sampling: Use sampling for high-volume operations to reduce metrics overhead.

  5. Error Handling: Ensure metrics collection failures don't impact application functionality.

  6. Storage: Consider external metrics storage systems (CloudWatch, Prometheus) for production use.

  7. Monitoring: Monitor the metrics system itself for health and performance.

  8. Security: Protect sensitive information in metrics (don't log credentials or PII).

  9. Alerting: Set up alerts based on key metrics thresholds for operational awareness.

  10. Documentation: Document custom metrics for operational teams and monitoring setup.

The metrics and monitoring system provides comprehensive observability into AWS SDK operations, enabling performance optimization, troubleshooting, and operational insights for production applications.

Install with Tessl CLI

npx tessl i tessl/maven-com-amazonaws--aws-java-sdk-core

docs

arn-support.md

authentication.md

client-builders.md

endpoint-discovery.md

exception-handling.md

http-transport.md

index.md

metrics-monitoring.md

protocols.md

regions-endpoints.md

retry-policies.md

utilities.md

waiters.md

tile.json