Unverified Commit efd863d6 authored by Keiven C's avatar Keiven C Committed by GitHub
Browse files

fix: dynamo_component to be added in metric names (#2180)


Co-authored-by: default avatarKeiven Chang <keivenchang@users.noreply.github.com>
parent 1ad6abed
# Generic Profiling for Work Handlers # Generic Metrics for Component Endpoints
This example demonstrates how to add automatic Prometheus metrics profiling to any work handler without modifying the handler code itself. This example demonstrates the automatic metrics provided to component endpoints by default.
## Overview ## Overview
The `WorkHandlerMetrics` system provides automatic profiling capabilities that are applied to all work handlers automatically. It automatically tracks: Component endpoints are measured automatically when using the DistributedRuntime code. The DistributedRuntime uses the `MetricsRegistry` trait which provides automatic measurement capabilities that are applied to all component endpoints automatically. It automatically tracks:
- **Request Count**: Total number of requests processed - **Request Count**: Total number of requests processed
- **Request Duration**: Time spent processing each request - **Request Duration**: Time spent processing each request
- **Request/Response Bytes**: Total bytes received and sent - **Request/Response Bytes**: Total bytes received and sent
- **Error Count**: Total number of errors encountered - **Error Count**: Total number of errors encountered
Additionally, the example demonstrates how to add custom metrics with data bytes tracking in `MySystemStatsMetrics`. Additionally, the example demonstrates how to add custom metrics with data bytes tracking.
## How It Works ## How It Works
**Automatic Metrics**: All work handlers automatically get profiling metrics without any code changes. **Automatic Metrics**: All component endpoints automatically get measurement metrics without any code changes.
**Custom Metrics**: If you want to add custom metrics IN ADDITION to the automatic ones, you can use the `add_metrics` method: **Custom Metrics**: If you want to add custom metrics IN ADDITION to the automatic ones, you can use the `add_metrics` method:
```rust ```rust
use dynamo_runtime::pipeline::network::Ingress; use dynamo_runtime::pipeline::network::Ingress;
// Automatic profiling - no code changes needed! // Automatic measurements - no code changes needed!
let ingress = Ingress::for_engine(my_handler)?; let ingress = Ingress::for_engine(my_handler)?;
// Optional: Add custom metrics IN ADDITION to automatic ones // Optional: Add custom metrics IN ADDITION to automatic ones
ingress.add_metrics(&endpoint)?; ingress.add_metrics(&endpoint)?;
``` ```
The endpoint automatically provides proper labeling (namespace, component, endpoint) for all metrics. The endpoint automatically provides proper labeling (dynamo_namespace, dynamo_component, dynamo_endpoint) for all metrics. These labels are prefixed with "dynamo_" to avoid collisions with Kubernetes and other monitoring system labels.
## Available Methods ## Available Methods
The `Ingress` struct provides methods for metrics: The `Ingress` struct provides methods for metrics:
- **Automatic**: All handlers get profiling metrics automatically - **Automatic**: All component endpoints get measurement metrics automatically
- `Ingress::add_metrics(&endpoint)` - Add custom metrics IN ADDITION to automatic ones (optional) - `Ingress::add_metrics(&endpoint)` - Add custom metrics IN ADDITION to automatic ones (optional)
## Metrics Generated ## Metrics Generated
### Automatic Metrics (No Code Changes Required) ### Automatic Metrics (No Code Changes Required)
The following Prometheus metrics are automatically created for all work handlers: The following Prometheus metrics are automatically created for all component endpoints:
### Counters ### Counters
- `requests_total` - Total requests processed - `dynamo_component_requests_total` - Total requests processed
- `request_bytes_total` - Total bytes received in requests - `dynamo_component_request_bytes_total` - Total bytes received in requests
- `response_bytes_total` - Total bytes sent in responses - `dynamo_component_response_bytes_total` - Total bytes sent in responses
- `errors_total` - Total errors encountered (with error_type labels) - `dynamo_component_errors_total` - Total errors encountered (with error_type labels)
### Error Types ### Error Types
The `errors_total` metric includes the following error types: The `dynamo_component_errors_total` metric includes the following error types:
- `deserialization` - Errors parsing request messages - `deserialization` - Errors parsing request messages
- `invalid_message` - Unexpected message format - `invalid_message` - Unexpected message format
- `response_stream` - Errors creating response streams - `response_stream` - Errors creating response streams
...@@ -59,92 +59,76 @@ The `errors_total` metric includes the following error types: ...@@ -59,92 +59,76 @@ The `errors_total` metric includes the following error types:
- `publish_final` - Errors publishing final response - `publish_final` - Errors publishing final response
### Histograms ### Histograms
- `request_duration_seconds` - Request processing time - `dynamo_component_request_duration_seconds` - Request processing time
### Gauges ### Gauges
- `concurrent_requests` - Number of requests currently being processed - `dynamo_component_concurrent_requests` - Number of requests currently being processed
### Custom Metrics (Optional) ### Custom Metrics (Optional)
- `my_custom_bytes_processed_total` - Total data bytes processed by system handler (example) - `dynamo_component_bytes_processed_total` - Total data bytes processed by system handler (example)
### Labels ### Labels
All metrics automatically include these labels from the endpoint: All metrics automatically include these labels from the endpoint:
- `namespace` - The namespace name - `dynamo_namespace` - The namespace name
- `component` - The component name - `dynamo_component` - The component name
- `endpoint` - The endpoint name - `dynamo_endpoint` - The endpoint name
These labels are prefixed with "dynamo_" to avoid collisions with Kubernetes and other monitoring system labels.
## Example Metrics Output ## Example Metrics Output
When the system is running, you'll see metrics from the /metrics HTTP path like this: When the system is running, you'll see metrics from the /metrics HTTP path like this:
```prometheus ```prometheus
# HELP concurrent_requests Number of requests currently being processed by work handler # HELP dynamo_component_concurrent_requests Number of requests currently being processed by component endpoint
# TYPE concurrent_requests gauge # TYPE dynamo_component_concurrent_requests gauge
concurrent_requests{component="dyn_example_component",endpoint="dyn_example_endpoint9881",namespace="dyn_example_namespace"} 0 dynamo_component_concurrent_requests{dynamo_component="example_component",dynamo_endpoint="example_endpoint9881",dynamo_namespace="example_namespace"} 0
# HELP my_custom_bytes_processed_total Example of a custom metric. Total number of data bytes processed by system handler # HELP dynamo_component_bytes_processed_total Example of a custom metric. Total number of data bytes processed by system handler
# TYPE my_custom_bytes_processed_total counter # TYPE dynamo_component_bytes_processed_total counter
my_custom_bytes_processed_total{component="dyn_example_component",endpoint="dyn_example_endpoint9881",namespace="dyn_example_namespace"} 42 dynamo_component_bytes_processed_total{dynamo_component="example_component",dynamo_endpoint="example_endpoint9881",dynamo_namespace="example_namespace"} 42
# HELP request_bytes_total Total number of bytes received in requests by work handler # HELP dynamo_component_request_bytes_total Total number of bytes received in requests by component endpoint
# TYPE request_bytes_total counter # TYPE dynamo_component_request_bytes_total counter
request_bytes_total{component="dyn_example_component",endpoint="dyn_example_endpoint9881",namespace="dyn_example_namespace"} 1098 dynamo_component_request_bytes_total{dynamo_component="example_component",dynamo_endpoint="example_endpoint9881",dynamo_namespace="example_namespace"} 1098
# HELP request_duration_seconds Time spent processing requests by work handler # HELP dynamo_component_request_duration_seconds Time spent processing requests by component endpoint
# TYPE request_duration_seconds histogram # TYPE dynamo_component_request_duration_seconds histogram
request_duration_seconds_bucket{component="dyn_example_component",endpoint="dyn_example_endpoint9881",namespace="dyn_example_namespace",le="0.005"} 3 dynamo_component_request_duration_seconds_bucket{dynamo_component="example_component",dynamo_endpoint="example_endpoint9881",dynamo_namespace="example_namespace",le="0.005"} 3
request_duration_seconds_bucket{component="dyn_example_component",endpoint="dyn_example_endpoint9881",namespace="dyn_example_namespace",le="0.01"} 3 dynamo_component_request_duration_seconds_bucket{dynamo_component="example_component",dynamo_endpoint="example_endpoint9881",dynamo_namespace="example_namespace",le="0.01"} 3
request_duration_seconds_bucket{component="dyn_example_component",endpoint="dyn_example_endpoint9881",namespace="dyn_example_namespace",le="0.025"} 3 dynamo_component_request_duration_seconds_bucket{dynamo_component="example_component",dynamo_endpoint="example_endpoint9881",dynamo_namespace="example_namespace",le="0.025"} 3
request_duration_seconds_bucket{component="dyn_example_component",endpoint="dyn_example_endpoint9881",namespace="dyn_example_namespace",le="0.05"} 3 dynamo_component_request_duration_seconds_bucket{dynamo_component="example_component",dynamo_endpoint="example_endpoint9881",dynamo_namespace="example_namespace",le="0.05"} 3
request_duration_seconds_bucket{component="dyn_example_component",endpoint="dyn_example_endpoint9881",namespace="dyn_example_namespace",le="0.1"} 3 dynamo_component_request_duration_seconds_bucket{dynamo_component="example_component",dynamo_endpoint="example_endpoint9881",dynamo_namespace="example_namespace",le="0.1"} 3
request_duration_seconds_bucket{component="dyn_example_component",endpoint="dyn_example_endpoint9881",namespace="dyn_example_namespace",le="0.25"} 3 dynamo_component_request_duration_seconds_bucket{dynamo_component="example_component",dynamo_endpoint="example_endpoint9881",dynamo_namespace="example_namespace",le="0.25"} 3
request_duration_seconds_bucket{component="dyn_example_component",endpoint="dyn_example_endpoint9881",namespace="dyn_example_namespace",le="0.5"} 3 dynamo_component_request_duration_seconds_bucket{dynamo_component="example_component",dynamo_endpoint="example_endpoint9881",dynamo_namespace="example_namespace",le="0.5"} 3
request_duration_seconds_bucket{component="dyn_example_component",endpoint="dyn_example_endpoint9881",namespace="dyn_example_namespace",le="1"} 3 dynamo_component_request_duration_seconds_bucket{dynamo_component="example_component",dynamo_endpoint="example_endpoint9881",dynamo_namespace="example_namespace",le="1"} 3
request_duration_seconds_bucket{component="dyn_example_component",endpoint="dyn_example_endpoint9881",namespace="dyn_example_namespace",le="2.5"} 3 dynamo_component_request_duration_seconds_bucket{dynamo_component="example_component",dynamo_endpoint="example_endpoint9881",dynamo_namespace="example_namespace",le="2.5"} 3
request_duration_seconds_bucket{component="dyn_example_component",endpoint="dyn_example_endpoint9881",namespace="dyn_example_namespace",le="5"} 3 dynamo_component_request_duration_seconds_bucket{dynamo_component="example_component",dynamo_endpoint="example_endpoint9881",dynamo_namespace="example_namespace",le="5"} 3
request_duration_seconds_bucket{component="dyn_example_component",endpoint="dyn_example_endpoint9881",namespace="dyn_example_namespace",le="10"} 3 dynamo_component_request_duration_seconds_bucket{dynamo_component="example_component",dynamo_endpoint="example_endpoint9881",dynamo_namespace="example_namespace",le="10"} 3
request_duration_seconds_bucket{component="dyn_example_component",endpoint="dyn_example_endpoint9881",namespace="dyn_example_namespace",le="+Inf"} 3 dynamo_component_request_duration_seconds_bucket{dynamo_component="example_component",dynamo_endpoint="example_endpoint9881",dynamo_namespace="example_namespace",le="+Inf"} 3
request_duration_seconds_sum{component="dyn_example_component",endpoint="dyn_example_endpoint9881",namespace="dyn_example_namespace"} 0.00048793700000000003 dynamo_component_request_duration_seconds_sum{dynamo_component="example_component",dynamo_endpoint="example_endpoint9881",dynamo_namespace="example_namespace"} 0.00048793700000000003
request_duration_seconds_count{component="dyn_example_component",endpoint="dyn_example_endpoint9881",namespace="dyn_example_namespace"} 3 dynamo_component_request_duration_seconds_count{dynamo_component="example_component",dynamo_endpoint="example_endpoint9881",dynamo_namespace="example_namespace"} 3
# HELP requests_total Total number of requests processed by work handler # HELP dynamo_component_requests_total Total number of requests processed by component endpoint
# TYPE requests_total counter # TYPE dynamo_component_requests_total counter
requests_total{component="dyn_example_component",endpoint="dyn_example_endpoint9881",namespace="dyn_example_namespace"} 3 dynamo_component_requests_total{dynamo_component="example_component",dynamo_endpoint="example_endpoint9881",dynamo_namespace="example_namespace"} 3
# HELP response_bytes_total Total number of bytes sent in responses by work handler # HELP dynamo_component_response_bytes_total Total number of bytes sent in responses by component endpoint
# TYPE response_bytes_total counter # TYPE dynamo_component_response_bytes_total counter
response_bytes_total{component="dyn_example_component",endpoint="dyn_example_endpoint9881",namespace="dyn_example_namespace"} 1917 dynamo_component_response_bytes_total{dynamo_component="example_component",dynamo_endpoint="example_endpoint9881",dynamo_namespace="example_namespace"} 1917
# HELP uptime_seconds Total uptime of the DistributedRuntime in seconds # HELP uptime_seconds Total uptime of the DistributedRuntime in seconds
# TYPE uptime_seconds gauge # TYPE uptime_seconds gauge
uptime_seconds{namespace="http_server"} 1.8226759879999999 uptime_seconds{dynamo_namespace="http_server"} 1.8226759879999999
``` ```
## Examples ## Example
### Example 1: Simple Handler with Automatic Profiling ### Component Endpoint with Automatic Measurements and Optional Custom Metrics
```rust
struct SimpleHandler;
#[async_trait]
impl AsyncEngine<SingleIn<String>, ManyOut<Annotated<String>>, Error> for SimpleHandler {
async fn generate(&self, input: SingleIn<String>) -> Result<ManyOut<Annotated<String>>> {
// Your business logic here
// No need to add any metrics code!
Ok(ResponseStream::new(Box::pin(stream), ctx.context()))
}
}
// Automatic profiling - no additional code needed!
let ingress = Ingress::for_engine(SimpleHandler::new())?;
```
### Example 2: Custom Handler with Data Bytes Tracking
```rust ```rust
struct RequestHandler { struct RequestHandler {
metrics: Option<Arc<MySystemStatsMetrics>>, metrics: Option<Arc<CustomMetrics>>,
} }
#[async_trait] #[async_trait]
...@@ -152,36 +136,43 @@ impl AsyncEngine<SingleIn<String>, ManyOut<Annotated<String>>, Error> for Reques ...@@ -152,36 +136,43 @@ impl AsyncEngine<SingleIn<String>, ManyOut<Annotated<String>>, Error> for Reques
async fn generate(&self, input: SingleIn<String>) -> Result<ManyOut<Annotated<String>>> { async fn generate(&self, input: SingleIn<String>) -> Result<ManyOut<Annotated<String>>> {
let (data, ctx) = input.into_parts(); let (data, ctx) = input.into_parts();
// Track data bytes processed (custom metric) // Optional: Track custom metrics
if let Some(metrics) = &self.metrics { if let Some(metrics) = &self.metrics {
metrics.data_bytes_processed.inc_by(data.len() as u64); metrics.data_bytes_processed.inc_by(data.len() as u64);
} }
// Your business logic here... // Your business logic here...
// No need to add any automatic measurement code!
Ok(ResponseStream::new(Box::pin(stream), ctx.context())) Ok(ResponseStream::new(Box::pin(stream), ctx.context()))
} }
} }
// Create custom metrics and handler // Create handler (with or without custom metrics)
let system_metrics = MySystemStatsMetrics::from_endpoint(&endpoint)?; let handler = if enable_custom_metrics {
let handler = RequestHandler::with_metrics(system_metrics); let custom_metrics = CustomMetrics::from_endpoint(&endpoint)?;
RequestHandler::with_metrics(custom_metrics)
} else {
RequestHandler::new()
};
// Automatic measurements - no additional code needed!
let ingress = Ingress::for_engine(handler)?; let ingress = Ingress::for_engine(handler)?;
// Add custom metrics IN ADDITION to automatic ones // Optional: Add custom metrics IN ADDITION to automatic ones
// You'll get both: automatic metrics (requests_total, request_duration_seconds, etc.) if enable_custom_metrics {
// AND custom metrics (my_custom_bytes_processed_total) ingress.add_metrics(&endpoint)?;
ingress.add_metrics(&endpoint)?; }
// Endpoint code to add ingress to the handler below...
``` ```
## Benefits ## Benefits
1. **Zero Code Changes**: Existing handlers automatically get profiling metrics 1. **Little/No Code Changes**: Existing handlers automatically get measurement metrics, and easy to add custom metrics for your particular application.
2. **Simple API**: Just create an Ingress and you get metrics automatically 2. **Simple API**: Simply swap out Prometheus constructors with one of the endpoint's factory methods.
3. **Optional Custom Metrics**: Add custom metrics when needed 3. **Automatic Measurements**: Request count, duration, and error tracking out of the box for component endpoints.
4. **Automatic Profiling**: Request count, duration, and error tracking out of the box 4. **Automatic Labeling**: Endpoint provides proper namespace/component/endpoint labels
5. **Automatic Labeling**: Endpoint provides proper namespace/component/endpoint labels
6. **Performance**: Minimal overhead, metrics are only recorded when provided
## Running the Example ## Running the Example
...@@ -207,15 +198,9 @@ Then make curl requests to the frontend (see the [main README](../../../../READM ...@@ -207,15 +198,9 @@ Then make curl requests to the frontend (see the [main README](../../../../READM
Once running, you can query the metrics: Once running, you can query the metrics:
```bash ```bash
# Get all work handler metrics # Get all component endpoint metrics for components
curl http://localhost:8081/metrics | grep -E "(requests_total|request_bytes_total|response_bytes_total|errors_total|request_duration_seconds|concurrent_requests)" curl http://localhost:8081/metrics | grep -E "dynamo_component"
# Get request count for specific endpoint
curl http://localhost:8081/metrics | grep 'requests_total{endpoint="dyn_example_endpoint"}'
# Get request duration histogram
curl http://localhost:8081/metrics | grep 'request_duration_seconds'
# Get custom system metrics # Get all frontend metrics
curl http://localhost:8081/metrics | grep 'my_custom_bytes_processed_total' curl http://localhost:8080/metrics | grep -E "dynamo_frontend"
``` ```
\ No newline at end of file
...@@ -347,9 +347,9 @@ mod tests { ...@@ -347,9 +347,9 @@ mod tests {
println!("Full metrics response:\n{}", response); println!("Full metrics response:\n{}", response);
let expected = "\ let expected = "\
# HELP dynamo_uptime_seconds Total uptime of the DistributedRuntime in seconds # HELP dynamo_component_dynamo_uptime_seconds Total uptime of the DistributedRuntime in seconds
# TYPE dynamo_uptime_seconds gauge # TYPE dynamo_component_dynamo_uptime_seconds gauge
dynamo_uptime_seconds 42 dynamo_component_dynamo_uptime_seconds 42
"; ";
assert_eq!(response, expected); assert_eq!(response, expected);
} }
......
...@@ -16,7 +16,8 @@ ...@@ -16,7 +16,8 @@
//! Metric Registry Framework for Dynamo. //! Metric Registry Framework for Dynamo.
//! //!
//! This module provides registry classes for Prometheus metrics //! This module provides registry classes for Prometheus metrics
//! that auto populates the labels with the namespace-component-endpoint hierarchy. //! that auto populates the labels with the component-endpoint hierarchy.
//! All metrics are prefixed with "dynamo_component_" to avoid collisions with Kubernetes and other monitoring system labels.
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use regex::Regex; use regex::Regex;
...@@ -24,18 +25,15 @@ use std::any::Any; ...@@ -24,18 +25,15 @@ use std::any::Any;
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
// If set to true, then metrics will be labeled with the namespace, component, and endpoint. // If set to true, then metrics will be labeled with the dynamo_namespace, dynamo_component, and dynamo_endpoint.
// These labels are prefixed with "dynamo_" to avoid collisions with Kubernetes and other monitoring system labels.
pub const USE_AUTO_LABELS: bool = true; pub const USE_AUTO_LABELS: bool = true;
// Prometheus imports // Prometheus imports
use prometheus::Encoder; use prometheus::Encoder;
fn build_metric_name(namespace: &str, metric_name: &str) -> String { fn build_metric_name(metric_name: &str) -> String {
if !namespace.is_empty() { format!("dynamo_component_{}", metric_name)
format!("{}_{}", namespace, metric_name)
} else {
metric_name.to_string()
}
} }
/// Lints a metric name component by stripping off invalid characters and validating Prometheus naming pattern /// Lints a metric name component by stripping off invalid characters and validating Prometheus naming pattern
...@@ -206,18 +204,7 @@ fn create_metric<T: PrometheusMetric, R: MetricsRegistry + ?Sized>( ...@@ -206,18 +204,7 @@ fn create_metric<T: PrometheusMetric, R: MetricsRegistry + ?Sized>(
// Build hierarchy: parent_hierarchy + [basename] // Build hierarchy: parent_hierarchy + [basename]
let hierarchy = [parent_hierarchy.clone(), vec![basename.clone()]].concat(); let hierarchy = [parent_hierarchy.clone(), vec![basename.clone()]].concat();
let namespace = if hierarchy.len() >= 2 { let metric_name = build_metric_name(metric_name);
let potential_namespace = &hierarchy[1];
if !potential_namespace.is_empty() {
lint_prometheus_name(potential_namespace)?
} else {
"".to_string()
}
} else {
"".to_string()
};
let metric_name = build_metric_name(&namespace, metric_name);
// Validate that user-provided labels don't have duplicate keys // Validate that user-provided labels don't have duplicate keys
for (key, _) in labels { for (key, _) in labels {
...@@ -234,7 +221,8 @@ fn create_metric<T: PrometheusMetric, R: MetricsRegistry + ?Sized>( ...@@ -234,7 +221,8 @@ fn create_metric<T: PrometheusMetric, R: MetricsRegistry + ?Sized>(
if USE_AUTO_LABELS { if USE_AUTO_LABELS {
// Validate that user-provided labels don't conflict with auto-generated labels // Validate that user-provided labels don't conflict with auto-generated labels
for (key, _) in labels { for (key, _) in labels {
if *key == "namespace" || *key == "component" || *key == "endpoint" { if *key == "dynamo_namespace" || *key == "dynamo_component" || *key == "dynamo_endpoint"
{
return Err(anyhow::anyhow!( return Err(anyhow::anyhow!(
"Label '{}' is automatically added by auto_label feature and cannot be manually set", "Label '{}' is automatically added by auto_label feature and cannot be manually set",
key key
...@@ -243,15 +231,21 @@ fn create_metric<T: PrometheusMetric, R: MetricsRegistry + ?Sized>( ...@@ -243,15 +231,21 @@ fn create_metric<T: PrometheusMetric, R: MetricsRegistry + ?Sized>(
} }
// Add auto-generated labels with sanitized values // Add auto-generated labels with sanitized values
if !namespace.is_empty() { if hierarchy.len() > 1 {
updated_labels.push(("namespace".to_string(), namespace.to_string())); let namespace = &hierarchy[1];
if !namespace.is_empty() {
let valid_namespace = lint_prometheus_name(namespace)?;
if !valid_namespace.is_empty() {
updated_labels.push(("dynamo_namespace".to_string(), valid_namespace));
}
}
} }
if hierarchy.len() > 2 { if hierarchy.len() > 2 {
let component = &hierarchy[2]; let component = &hierarchy[2];
if !component.is_empty() { if !component.is_empty() {
let valid_component = lint_prometheus_name(component)?; let valid_component = lint_prometheus_name(component)?;
if !valid_component.is_empty() { if !valid_component.is_empty() {
updated_labels.push(("component".to_string(), valid_component)); updated_labels.push(("dynamo_component".to_string(), valid_component));
} }
} }
} }
...@@ -260,7 +254,7 @@ fn create_metric<T: PrometheusMetric, R: MetricsRegistry + ?Sized>( ...@@ -260,7 +254,7 @@ fn create_metric<T: PrometheusMetric, R: MetricsRegistry + ?Sized>(
if !endpoint.is_empty() { if !endpoint.is_empty() {
let valid_endpoint = lint_prometheus_name(endpoint)?; let valid_endpoint = lint_prometheus_name(endpoint)?;
if !valid_endpoint.is_empty() { if !valid_endpoint.is_empty() {
updated_labels.push(("endpoint".to_string(), valid_endpoint)); updated_labels.push(("dynamo_endpoint".to_string(), valid_endpoint));
} }
} }
} }
...@@ -560,12 +554,12 @@ mod tests { ...@@ -560,12 +554,12 @@ mod tests {
#[test] #[test]
fn test_build_metric_name_with_prefix() { fn test_build_metric_name_with_prefix() {
// Test that build_metric_name correctly prepends the namespace // Test that build_metric_name correctly prepends the dynamo_component prefix
let result = build_metric_name("", "requests"); let result = build_metric_name("requests");
assert_eq!(result, "requests"); assert_eq!(result, "dynamo_component_requests");
let result = build_metric_name("dynamo", "requests"); let result = build_metric_name("counter");
assert_eq!(result, "dynamo_requests"); assert_eq!(result, "dynamo_component_counter");
} }
#[test] #[test]
...@@ -816,10 +810,10 @@ mod test_prefixes { ...@@ -816,10 +810,10 @@ mod test_prefixes {
println!("Result with invalid namespace '@@123':"); println!("Result with invalid namespace '@@123':");
println!("{:?}", result); println!("{:?}", result);
// The result should fail because even after sanitization, the name "123" doesn't follow Prometheus naming pattern // The result should be an error because '@@123' gets sanitized to '123' which is invalid
assert!( assert!(
result.is_err(), result.is_err(),
"Creating metric with invalid namespace should fail even after sanitization" "Creating metric with namespace '@@123' should fail because it gets sanitized to '123' which is invalid"
); );
// Verify the error message indicates the sanitized name is still invalid // Verify the error message indicates the sanitized name is still invalid
...@@ -879,9 +873,9 @@ mod test_simple_metricsregistry_trait { ...@@ -879,9 +873,9 @@ mod test_simple_metricsregistry_trait {
println!("{}", endpoint_output); println!("{}", endpoint_output);
let expected_endpoint_output = format!( let expected_endpoint_output = format!(
r#"# HELP testnamespace_testcounter A test counter r#"# HELP dynamo_component_testcounter A test counter
# TYPE testnamespace_testcounter counter # TYPE dynamo_component_testcounter counter
testnamespace_testcounter{{component="testcomponent",endpoint="testendpoint",namespace="testnamespace"}} 123.456789 dynamo_component_testcounter{{dynamo_component="testcomponent",dynamo_endpoint="testendpoint",dynamo_namespace="testnamespace"}} 123.456789
"# "#
); );
...@@ -907,12 +901,12 @@ testnamespace_testcounter{{component="testcomponent",endpoint="testendpoint",nam ...@@ -907,12 +901,12 @@ testnamespace_testcounter{{component="testcomponent",endpoint="testendpoint",nam
println!("{}", component_output); println!("{}", component_output);
let expected_component_output = format!( let expected_component_output = format!(
r#"# HELP testnamespace_testcounter A test counter r#"# HELP dynamo_component_testcounter A test counter
# TYPE testnamespace_testcounter counter # TYPE dynamo_component_testcounter counter
testnamespace_testcounter{{component="testcomponent",endpoint="testendpoint",namespace="testnamespace"}} 123.456789 dynamo_component_testcounter{{dynamo_component="testcomponent",dynamo_endpoint="testendpoint",dynamo_namespace="testnamespace"}} 123.456789
# HELP testnamespace_testgauge A test gauge # HELP dynamo_component_testgauge A test gauge
# TYPE testnamespace_testgauge gauge # TYPE dynamo_component_testgauge gauge
testnamespace_testgauge{{component="testcomponent",namespace="testnamespace"}} 50000 dynamo_component_testgauge{{dynamo_component="testcomponent",dynamo_namespace="testnamespace"}} 50000
"# "#
); );
...@@ -937,15 +931,15 @@ testnamespace_testgauge{{component="testcomponent",namespace="testnamespace"}} 5 ...@@ -937,15 +931,15 @@ testnamespace_testgauge{{component="testcomponent",namespace="testnamespace"}} 5
println!("{}", namespace_output); println!("{}", namespace_output);
let expected_namespace_output = format!( let expected_namespace_output = format!(
r#"# HELP testnamespace_testcounter A test counter r#"# HELP dynamo_component_testcounter A test counter
# TYPE testnamespace_testcounter counter # TYPE dynamo_component_testcounter counter
testnamespace_testcounter{{component="testcomponent",endpoint="testendpoint",namespace="testnamespace"}} 123.456789 dynamo_component_testcounter{{dynamo_component="testcomponent",dynamo_endpoint="testendpoint",dynamo_namespace="testnamespace"}} 123.456789
# HELP testnamespace_testgauge A test gauge # HELP dynamo_component_testgauge A test gauge
# TYPE testnamespace_testgauge gauge # TYPE dynamo_component_testgauge gauge
testnamespace_testgauge{{component="testcomponent",namespace="testnamespace"}} 50000 dynamo_component_testgauge{{dynamo_component="testcomponent",dynamo_namespace="testnamespace"}} 50000
# HELP testnamespace_testintcounter A test int counter # HELP dynamo_component_testintcounter A test int counter
# TYPE testnamespace_testintcounter counter # TYPE dynamo_component_testintcounter counter
testnamespace_testintcounter{{namespace="testnamespace"}} 12345 dynamo_component_testintcounter{{dynamo_namespace="testnamespace"}} 12345
"# "#
); );
...@@ -1013,35 +1007,35 @@ testnamespace_testintcounter{{namespace="testnamespace"}} 12345 ...@@ -1013,35 +1007,35 @@ testnamespace_testintcounter{{namespace="testnamespace"}} 12345
println!("{}", drt_output); println!("{}", drt_output);
let expected_drt_output = format!( let expected_drt_output = format!(
r#"# HELP testcountervec A test counter vector r#"# HELP dynamo_component_testcounter A test counter
# TYPE testcountervec counter # TYPE dynamo_component_testcounter counter
testcountervec{{method="GET",service="api",status="200"}} 10 dynamo_component_testcounter{{dynamo_component="testcomponent",dynamo_endpoint="testendpoint",dynamo_namespace="testnamespace"}} 123.456789
testcountervec{{method="POST",service="api",status="201"}} 5 # HELP dynamo_component_testcountervec A test counter vector
# HELP testhistogram A test histogram # TYPE dynamo_component_testcountervec counter
# TYPE testhistogram histogram dynamo_component_testcountervec{{method="GET",service="api",status="200"}} 10
testhistogram_bucket{{le="1"}} 0 dynamo_component_testcountervec{{method="POST",service="api",status="201"}} 5
testhistogram_bucket{{le="2.5"}} 2 # HELP dynamo_component_testgauge A test gauge
testhistogram_bucket{{le="5"}} 3 # TYPE dynamo_component_testgauge gauge
testhistogram_bucket{{le="10"}} 3 dynamo_component_testgauge{{dynamo_component="testcomponent",dynamo_namespace="testnamespace"}} 50000
testhistogram_bucket{{le="+Inf"}} 3 # HELP dynamo_component_testhistogram A test histogram
testhistogram_sum 7.5 # TYPE dynamo_component_testhistogram histogram
testhistogram_count 3 dynamo_component_testhistogram_bucket{{le="1"}} 0
# HELP testintgauge A test int gauge dynamo_component_testhistogram_bucket{{le="2.5"}} 2
# TYPE testintgauge gauge dynamo_component_testhistogram_bucket{{le="5"}} 3
testintgauge 42 dynamo_component_testhistogram_bucket{{le="10"}} 3
# HELP testintgaugevec A test int gauge vector dynamo_component_testhistogram_bucket{{le="+Inf"}} 3
# TYPE testintgaugevec gauge dynamo_component_testhistogram_sum 7.5
testintgaugevec{{instance="server1",service="api",status="active"}} 10 dynamo_component_testhistogram_count 3
testintgaugevec{{instance="server2",service="api",status="inactive"}} 0 # HELP dynamo_component_testintcounter A test int counter
# HELP testnamespace_testcounter A test counter # TYPE dynamo_component_testintcounter counter
# TYPE testnamespace_testcounter counter dynamo_component_testintcounter{{dynamo_namespace="testnamespace"}} 12345
testnamespace_testcounter{{component="testcomponent",endpoint="testendpoint",namespace="testnamespace"}} 123.456789 # HELP dynamo_component_testintgauge A test int gauge
# HELP testnamespace_testgauge A test gauge # TYPE dynamo_component_testintgauge gauge
# TYPE testnamespace_testgauge gauge dynamo_component_testintgauge 42
testnamespace_testgauge{{component="testcomponent",namespace="testnamespace"}} 50000 # HELP dynamo_component_testintgaugevec A test int gauge vector
# HELP testnamespace_testintcounter A test int counter # TYPE dynamo_component_testintgaugevec gauge
# TYPE testnamespace_testintcounter counter dynamo_component_testintgaugevec{{instance="server1",service="api",status="active"}} 10
testnamespace_testintcounter{{namespace="testnamespace"}} 12345 dynamo_component_testintgaugevec{{instance="server2",service="api",status="inactive"}} 0
"# "#
); );
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment