|
5 | 5 | from functools import cached_property |
6 | 6 | from typing import Any, Literal, cast |
7 | 7 |
|
| 8 | +from packaging.version import parse |
| 9 | +from pydantic import field_validator, model_validator |
8 | 10 | from pydantic.dataclasses import dataclass |
9 | 11 |
|
10 | 12 | from vllm import version |
@@ -79,25 +81,43 @@ def compute_hash(self) -> str: |
79 | 81 | hash_str = hashlib.md5(str(factors).encode(), usedforsecurity=False).hexdigest() |
80 | 82 | return hash_str |
81 | 83 |
|
82 | | - def __post_init__(self): |
83 | | - if ( |
84 | | - self.collect_detailed_traces is not None |
85 | | - and len(self.collect_detailed_traces) == 1 |
86 | | - and "," in self.collect_detailed_traces[0] |
87 | | - ): |
88 | | - self._parse_collect_detailed_traces() |
89 | | - |
90 | | - from vllm.tracing import is_otel_available, otel_import_error_traceback |
91 | | - |
92 | | - if not is_otel_available() and self.otlp_traces_endpoint is not None: |
| 84 | + @field_validator("show_hidden_metrics_for_version") |
| 85 | + @classmethod |
| 86 | + def _validate_show_hidden_metrics_for_version(cls, value: str | None) -> str | None: |
| 87 | + if value is not None: |
| 88 | + # Raises an exception if the string is not a valid version. |
| 89 | + parse(value) |
| 90 | + return value |
| 91 | + |
| 92 | + @field_validator("otlp_traces_endpoint") |
| 93 | + @classmethod |
| 94 | + def _validate_otlp_traces_endpoint(cls, value: str | None) -> str | None: |
| 95 | + if value is not None: |
| 96 | + from vllm.tracing import is_otel_available, otel_import_error_traceback |
| 97 | + |
| 98 | + if not is_otel_available(): |
| 99 | + raise ValueError( |
| 100 | + "OpenTelemetry is not available. Unable to configure " |
| 101 | + "'otlp_traces_endpoint'. Ensure OpenTelemetry packages are " |
| 102 | + f"installed. Original error:\n{otel_import_error_traceback}" |
| 103 | + ) |
| 104 | + return value |
| 105 | + |
| 106 | + @field_validator("collect_detailed_traces") |
| 107 | + @classmethod |
| 108 | + def _validate_collect_detailed_traces( |
| 109 | + cls, value: list[DetailedTraceModules] | None |
| 110 | + ) -> list[DetailedTraceModules] | None: |
| 111 | + """Handle the legacy case where users might provide a comma-separated |
| 112 | + string instead of a list of strings.""" |
| 113 | + if value is not None and len(value) == 1 and "," in value[0]: |
| 114 | + value = cast(list[DetailedTraceModules], value[0].split(",")) |
| 115 | + return value |
| 116 | + |
| 117 | + @model_validator(mode="after") |
| 118 | + def _validate_tracing_config(self): |
| 119 | + if self.collect_detailed_traces and not self.otlp_traces_endpoint: |
93 | 120 | raise ValueError( |
94 | | - "OpenTelemetry is not available. Unable to configure " |
95 | | - "'otlp_traces_endpoint'. Ensure OpenTelemetry packages are " |
96 | | - f"installed. Original error:\n{otel_import_error_traceback}" |
| 121 | + "collect_detailed_traces requires `--otlp-traces-endpoint` to be set." |
97 | 122 | ) |
98 | | - |
99 | | - def _parse_collect_detailed_traces(self): |
100 | | - assert isinstance(self.collect_detailed_traces, list) |
101 | | - self.collect_detailed_traces = cast( |
102 | | - list[DetailedTraceModules], self.collect_detailed_traces[0].split(",") |
103 | | - ) |
| 123 | + return self |
0 commit comments