Skip to content

feat(serve): describe an endpoint's traffic and size workloads from it - #6552

Merged
rsareddy0329 merged 1 commit into
aws:masterfrom
ZealSV:feat/workload-from-endpoint
Oct 30, 2026
Merged

rsareddy0329 merged 1 commit into
aws:masterfrom
ZealSV:feat/workload-from-endpoint

Conversation

@ZealSV

@ZealSV ZealSV commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Issue #, if available:

Description of changes:

Adds describe_endpoint_traffic() and Workload.from_endpoint() to sagemaker.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 an EndpointTraffic for one model on the endpoint:

Field What it is
concurrency Concurrent requests on the whole deployment: each hour's maximum ConcurrentRequestsPerCopy (inference component) or ConcurrentRequestsPerModel (production variant), times the current copies or instances. max is the busiest hour's.
requests, input_tokens, output_tokens The requests the model completed in the window, and their prompt and generated tokens, from the serving container's token histograms.
framework The serving framework whose histograms were read ("vllm"), or None.
detailed_observability The endpoint configuration's MetricsConfig.EnableDetailedObservability. The token histograms aren't read when it's False.
data_capture_s3_uri The variant's Data Capture prefix, when the endpoint captures requests.
start_time, end_time The window, in UTC.

concurrency, input_tokens and output_tokens are TrafficStats: min, p25, p50, p70, p80, p90, p95, p99, max (p100), mean and stddev.

  • 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; naive datetimes are refused.
  • Token metrics: with detailed observability on, the serving container's per-request token histograms are published to CloudWatch. They're read through CloudWatch's Prometheus-compatible query API, signed with the session's credentials (cloudwatch:GetMetricData, cloudwatch:ListMetrics). The histograms are listed per framework (today vLLM's vllm:request_prompt_tokens and vllm:request_generation_tokens), so adding a framework is one entry.
  • Method: the histograms are cumulative, so a series' requests in the window are its newest snapshot in the window less its snapshot at the start, read with one instant query per day of the window. A series that started in the window, or restarted, counts from zero. The request count and the token means are exact. The percentiles interpolate within the buckets, and the standard deviation uses the bucket midpoints.
  • Adapters: an adapter's requests run in its base component's container, which publishes their concurrency and token histograms. So passing an adapter describes its base component, and finding the component skips adapters.

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 unless concurrency is passed. use_data_capture=False opts out of replaying captured requests, which can contain end users' data. Other workload parameters (tokenizer, hf_token, request_count, streaming, ...) pass through.

from datetime import timedelta
from sagemaker.serve.ai_inference_recommender import Workload, describe_endpoint_traffic

traffic = describe_endpoint_traffic("my-endpoint", inference_component_name="my-ic", lookback=timedelta(days=3))
print(traffic.concurrency.max, traffic.input_tokens.p50, traffic.output_tokens.p99)

workload = Workload.from_endpoint("my-endpoint", inference_component_name="my-ic", tokenizer="Qwen/Qwen3-0.6B")

Testing done:

  • Unit tests: sagemaker-serve/tests/unit/test_ai_inference_recommender/test_traffic.py (61 tests, 100% line coverage of traffic.py). The test_ai_inference_recommender suite passes (284 tests).
  • black, flake8, pylint (10.00/10) and pydocstyle pass on the changed files.
  • Read-only runs against live endpoints in a test account. On an inference component under benchmark load, the request count matched the component's Invocations exactly (169, then 401 requests) on windows that ended a few minutes earlier. Runs also covered a LoRA adapter, components and variants without traffic, and an endpoint whose endpoint configuration was deleted while it was in service.

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@ZealSV
ZealSV force-pushed the feat/workload-from-endpoint branch from 7b0f173 to 6dfdea9 Compare October 30, 2026 16:45
@ZealSV
ZealSV force-pushed the feat/workload-from-endpoint branch from 6dfdea9 to f234e56 Compare October 30, 2026 17:07
@ZealSV ZealSV changed the title feat(serve): size workloads from an endpoint's traffic feat(serve): describe an endpoint's traffic and size workloads from it Oct 30, 2026
@ZealSV
ZealSV deployed to manual-approval October 30, 2026 17:12 — with GitHub Actions Active
@ZealSV
ZealSV deployed to manual-approval October 30, 2026 17:12 — with GitHub Actions Active
@ZealSV
ZealSV deployed to manual-approval October 30, 2026 17:12 — with GitHub Actions Active

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 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.
@ZealSV
ZealSV force-pushed the feat/workload-from-endpoint branch from f234e56 to 7f0f2fd Compare October 30, 2026 19:53
@ZealSV
ZealSV deployed to manual-approval October 30, 2026 19:54 — with GitHub Actions Active
@ZealSV
ZealSV deployed to manual-approval October 30, 2026 19:54 — with GitHub Actions Active
@ZealSV
ZealSV deployed to manual-approval October 30, 2026 19:54 — with GitHub Actions Active

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 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}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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.

@rsareddy0329

Copy link
Copy Markdown
Contributor

The sagemaker-mlops integ test failure is unrelated to this change - it's caused by a JS change and will be fixed in #6553.
Merging this PR since the failure isn't from it.

@rsareddy0329
rsareddy0329 merged commit 73fafda into aws:master Oct 30, 2026
21 of 24 checks passed

This branch was successfully deployed

1 active deployment
manual-approval — 7f0f2fd8 Deployed Oct 30, 2026 by ZealSV via wait-for-approval #1879
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants