Repository navigation
feat(serve): describe an endpoint's traffic and size workloads from it - #6552
Conversation
7b0f173 to
6dfdea9
Compare
6dfdea9 to
f234e56
Compare
There was a problem hiding this comment.
🤖 AI code review
This PR adds describe_endpoint_traffic() and Workload.from_endpoint() to sagemaker.serve.ai_inference_recommender, deriving concurrency from CloudWatch invocation metrics and token-size distributions from the serving container's token histograms read through CloudWatch's Prometheus-compatible query API. The implementation is well-structured, follows the module's established conventions (session resolution via _boto_session, @_telemetry_emitter with Feature.INFERENCE_RECOMMENDER), and is backed by an extensive, well-targeted unit test suite covering windowing, histogram math, target resolution, data capture, query-API errors, and from_endpoint paths. I found only minor robustness/doc nits; no correctness or breaking-change issues.
Reviewed commit f234e56. Automated review; verify before acting.
Add describe_endpoint_traffic(), which describes the traffic one model on an endpoint served over a window, relative (lookback back from end_time, seven days by default) or absolute (start_time to end_time), up to seven days. Times must be timezone-aware and are reported in UTC. - Concurrency for the whole deployment: each hour's maximum ConcurrentRequestsPerCopy or ConcurrentRequestsPerModel times the current copies or instances. - With detailed observability on, the request count and the prompt and generated tokens of the requests the model completed, from the serving container's token histograms. They're read through CloudWatch's Prometheus-compatible query API with the session's credentials, over the CloudWatch client's HTTP session (its proxy, CA bundle and timeouts), with retries on throttling, server errors and dropped connections. The read is best effort: a failure is reported in token_metrics_error and logged. The histograms are listed per serving framework (vLLM today), and the result names the framework read. They aren't read when the endpoint configuration turns detailed observability off. - Tokens and concurrency are TrafficStats: min, p25, p50, p70, p80, p90, p95, p99, max (p100), mean and standard deviation. Token percentiles interpolate within the histograms' buckets. Concurrency's are over the window's hourly maximums, so its max is the busiest hour's. - The variant's Data Capture prefix, when the endpoint captures requests. The histograms are cumulative, so a series' traffic in the window is the sum of its increments between daily snapshots, from the start's to the window's last. A snapshot below the one before it follows a restart of its container and counts from zero. An adapter's requests run in its base component's container, which publishes the concurrency and the token histograms for them, so an adapter is described by its base component, and finding the component skips adapters. Add Workload.from_endpoint(), which builds a synthetic workload from the token metrics at the busiest hour's concurrency, or with use_data_capture=True replays the variant's captured requests, so a benchmark or recommendation job can be sized from what an endpoint serves today. Other workload parameters, such as tokenizer and hf_token, pass through to the workload. Integration tests: a no-GPU check that the signed token query is accepted and parsed by CloudWatch's query API, and an e2e step that describes the benchmarked endpoint's traffic and runs a benchmark sized from it.
f234e56 to
7f0f2fd
Compare
There was a problem hiding this comment.
🤖 AI code review
This PR adds describe_endpoint_traffic() and Workload.from_endpoint() to sagemaker.serve.ai_inference_recommender, letting a benchmark/recommendation workload be sized from an endpoint's live traffic. It reads concurrency from CloudWatch GetMetricStatistics and token-size histograms through CloudWatch's Prometheus-compatible query API (SigV4-signed GETs), estimating percentiles/stddev from histogram buckets. The implementation follows established module conventions (_boto_session reuse, @_telemetry_emitter with Feature.INFERENCE_RECOMMENDER as in listing.py) and is backed by a large, well-targeted unit test suite plus integration coverage. Overall the code is clean and correct; I only have minor observations.
Reviewed commit 7f0f2fd. Automated review; verify before acting.
| if response.status_code == 403: | ||
| raise RuntimeError( | ||
| "CloudWatch denied the query (HTTP 403). Reading token metrics needs " | ||
| f"cloudwatch:GetMetricData and cloudwatch:ListMetrics. {detail}" |
There was a problem hiding this comment.
🟡 Low: _PromQLClient reaches into botocore internals (cloudwatch.meta.endpoint_url and cloudwatch._endpoint.http_session). The latter is a private attribute and is not part of botocore's public contract, so it can break silently on a botocore upgrade. This is a known risk given the Prometheus-query API isn't exposed by boto3, but it would be worth pinning a minimum botocore version or adding a focused test that fails loudly if http_session disappears, so the breakage surfaces at test time rather than at runtime.
|
The sagemaker-mlops integ test failure is unrelated to this change - it's caused by a JS change and will be fixed in #6553. |
Issue #, if available:
Description of changes:
Adds
describe_endpoint_traffic()andWorkload.from_endpoint()tosagemaker.serve.ai_inference_recommender, so a benchmark or recommendation job can be sized from the traffic an endpoint serves today.describe_endpoint_traffic(endpoint_name, *, inference_component_name=None, variant_name=None, lookback=None, start_time=None, end_time=None, sagemaker_session=None)returns anEndpointTrafficfor one model on the endpoint:concurrencyConcurrentRequestsPerCopy(inference component) orConcurrentRequestsPerModel(production variant), times the current copies or instances.maxis the busiest hour's.requests,input_tokens,output_tokensframework"vllm"), orNone.detailed_observabilityMetricsConfig.EnableDetailedObservability. The token histograms aren't read when it'sFalse.data_capture_s3_uristart_time,end_timeconcurrency,input_tokensandoutput_tokensareTrafficStats:min,p25,p50,p70,p80,p90,p95,p99,max(p100),meanandstddev.lookbackback fromend_time, seven days by default) or absolute (start_timetoend_time), up to seven days. Times must be timezone-aware; naive datetimes are refused.cloudwatch:GetMetricData,cloudwatch:ListMetrics). The histograms are listed per framework (today vLLM'svllm:request_prompt_tokensandvllm:request_generation_tokens), so adding a framework is one entry.Workload.from_endpoint(endpoint_name, ...)replays the variant's captured requests (from_dataset(..., custom_dataset_type="sagemaker-datacapture")) when the endpoint has Data Capture on. Otherwise it builds a synthetic workload from the token metrics' means and standard deviations. Either way, the concurrency is the busiest hour's unlessconcurrencyis passed.use_data_capture=Falseopts out of replaying captured requests, which can contain end users' data. Other workload parameters (tokenizer,hf_token,request_count,streaming, ...) pass through.Testing done:
sagemaker-serve/tests/unit/test_ai_inference_recommender/test_traffic.py(61 tests, 100% line coverage oftraffic.py). Thetest_ai_inference_recommendersuite passes (284 tests).By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.