feat: support custom OTLP trace service name (#35802)
This commit is contained in:
@@ -589,6 +589,7 @@ class ServerArgs(DisaggServerArgsMixin):
|
|||||||
# Tracing
|
# Tracing
|
||||||
enable_trace: bool = False
|
enable_trace: bool = False
|
||||||
otlp_traces_endpoint: str = "localhost:4317"
|
otlp_traces_endpoint: str = "localhost:4317"
|
||||||
|
otlp_service_name: str | None = None
|
||||||
|
|
||||||
# SGLang backend for encoder stage
|
# SGLang backend for encoder stage
|
||||||
srt_encoder_url: str | None = None
|
srt_encoder_url: str | None = None
|
||||||
@@ -2893,6 +2894,13 @@ class ServerArgs(DisaggServerArgsMixin):
|
|||||||
default=ServerArgs.otlp_traces_endpoint,
|
default=ServerArgs.otlp_traces_endpoint,
|
||||||
help="OTLP collector endpoint when --enable-trace is set. Format: <host>:<port>",
|
help="OTLP collector endpoint when --enable-trace is set. Format: <host>:<port>",
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--otlp-service-name",
|
||||||
|
type=str,
|
||||||
|
default=ServerArgs.otlp_service_name,
|
||||||
|
help="Service name for OTLP traces (displayed as 'service.name' in trace backends). "
|
||||||
|
"If unset, falls back to the OTEL_SERVICE_NAME env var, then to 'sglang-diffusion'.",
|
||||||
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--log-requests",
|
"--log-requests",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ start/end bookkeeping.
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
|
||||||
@@ -37,10 +38,17 @@ def init_diffusion_tracing(server_args, thread_label: str):
|
|||||||
trace_set_thread_info,
|
trace_set_thread_info,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Priority: --otlp-service-name > OTEL_SERVICE_NAME > "sglang-diffusion"
|
||||||
|
service_name = (
|
||||||
|
server_args.otlp_service_name
|
||||||
|
or os.getenv("OTEL_SERVICE_NAME")
|
||||||
|
or "sglang-diffusion"
|
||||||
|
)
|
||||||
|
|
||||||
# srt owns TraceReqContext and filters spans through its trace_modules list
|
# srt owns TraceReqContext and filters spans through its trace_modules list
|
||||||
process_tracing_init(
|
process_tracing_init(
|
||||||
server_args.otlp_traces_endpoint,
|
server_args.otlp_traces_endpoint,
|
||||||
"sglang-diffusion",
|
service_name,
|
||||||
trace_modules=DIFFUSION_TRACE_MODULE,
|
trace_modules=DIFFUSION_TRACE_MODULE,
|
||||||
)
|
)
|
||||||
trace_set_thread_info(thread_label)
|
trace_set_thread_info(thread_label)
|
||||||
|
|||||||
@@ -177,6 +177,11 @@ class Observability(msgspec.Struct):
|
|||||||
str,
|
str,
|
||||||
"Config opentelemetry collector endpoint if --enable-trace is set. format: <ip>:<port>",
|
"Config opentelemetry collector endpoint if --enable-trace is set. format: <ip>:<port>",
|
||||||
] = "localhost:4317"
|
] = "localhost:4317"
|
||||||
|
otlp_service_name: A[
|
||||||
|
Optional[str],
|
||||||
|
"Service name for OTLP traces (displayed as 'service.name' in trace backends). "
|
||||||
|
"If unset, falls back to the OTEL_SERVICE_NAME env var, then to 'sglang'.",
|
||||||
|
] = None
|
||||||
# RequestMetricsExporter configuration
|
# RequestMetricsExporter configuration
|
||||||
export_metrics_to_file: A[
|
export_metrics_to_file: A[
|
||||||
bool,
|
bool,
|
||||||
|
|||||||
@@ -1775,7 +1775,7 @@ def launch_local_runtime(server_args: ServerArgs) -> EncoderRuntime:
|
|||||||
if get_observability().enable_trace:
|
if get_observability().enable_trace:
|
||||||
process_tracing_init(
|
process_tracing_init(
|
||||||
get_observability().otlp_traces_endpoint,
|
get_observability().otlp_traces_endpoint,
|
||||||
"sglang",
|
get_observability().otlp_service_name,
|
||||||
trace_modules=get_observability().trace_modules,
|
trace_modules=get_observability().trace_modules,
|
||||||
)
|
)
|
||||||
trace_set_thread_info("Encoder")
|
trace_set_thread_info("Encoder")
|
||||||
|
|||||||
@@ -329,7 +329,7 @@ class Engine(EngineScoreMixin, EngineBase):
|
|||||||
if get_observability().enable_trace:
|
if get_observability().enable_trace:
|
||||||
process_tracing_init(
|
process_tracing_init(
|
||||||
get_observability().otlp_traces_endpoint,
|
get_observability().otlp_traces_endpoint,
|
||||||
"sglang",
|
get_observability().otlp_service_name,
|
||||||
trace_modules=get_observability().trace_modules,
|
trace_modules=get_observability().trace_modules,
|
||||||
)
|
)
|
||||||
thread_label = "Tokenizer"
|
thread_label = "Tokenizer"
|
||||||
|
|||||||
@@ -293,7 +293,7 @@ async def lifespan(fast_api_app: FastAPI):
|
|||||||
if get_observability().enable_trace:
|
if get_observability().enable_trace:
|
||||||
process_tracing_init(
|
process_tracing_init(
|
||||||
get_observability().otlp_traces_endpoint,
|
get_observability().otlp_traces_endpoint,
|
||||||
"sglang",
|
get_observability().otlp_service_name,
|
||||||
trace_modules=get_observability().trace_modules,
|
trace_modules=get_observability().trace_modules,
|
||||||
)
|
)
|
||||||
if get_disagg().disaggregation_mode == "prefill":
|
if get_disagg().disaggregation_mode == "prefill":
|
||||||
|
|||||||
@@ -839,7 +839,7 @@ def run_data_parallel_controller_process(
|
|||||||
if get_observability().enable_trace:
|
if get_observability().enable_trace:
|
||||||
process_tracing_init(
|
process_tracing_init(
|
||||||
get_observability().otlp_traces_endpoint,
|
get_observability().otlp_traces_endpoint,
|
||||||
"sglang",
|
get_observability().otlp_service_name,
|
||||||
trace_modules=get_observability().trace_modules,
|
trace_modules=get_observability().trace_modules,
|
||||||
)
|
)
|
||||||
thread_label = "DP Controller"
|
thread_label = "DP Controller"
|
||||||
|
|||||||
@@ -5852,7 +5852,7 @@ def run_scheduler_process(
|
|||||||
if get_observability().enable_trace:
|
if get_observability().enable_trace:
|
||||||
process_tracing_init(
|
process_tracing_init(
|
||||||
get_observability().otlp_traces_endpoint,
|
get_observability().otlp_traces_endpoint,
|
||||||
"sglang",
|
get_observability().otlp_service_name,
|
||||||
trace_modules=get_observability().trace_modules,
|
trace_modules=get_observability().trace_modules,
|
||||||
)
|
)
|
||||||
thread_label = "Scheduler"
|
thread_label = "Scheduler"
|
||||||
|
|||||||
@@ -227,9 +227,12 @@ def process_tracing_init(
|
|||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
# Priority: explicit server_name > OTEL_SERVICE_NAME > "sglang"
|
||||||
|
service_name = server_name or os.getenv("OTEL_SERVICE_NAME", "sglang")
|
||||||
|
|
||||||
resource = Resource.create(
|
resource = Resource.create(
|
||||||
attributes={
|
attributes={
|
||||||
SERVICE_NAME: server_name,
|
SERVICE_NAME: service_name,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
tracer_provider = TracerProvider(
|
tracer_provider = TracerProvider(
|
||||||
@@ -259,7 +262,7 @@ def process_tracing_init(
|
|||||||
if envs.SGLANG_TRACE_ASYNC.get():
|
if envs.SGLANG_TRACE_ASYNC.get():
|
||||||
from sglang.srt.observability.trace_async import start_trace_exporter
|
from sglang.srt.observability.trace_async import start_trace_exporter
|
||||||
|
|
||||||
start_trace_exporter(otlp_endpoint, server_name, trace_modules=trace_modules)
|
start_trace_exporter(otlp_endpoint, service_name, trace_modules=trace_modules)
|
||||||
|
|
||||||
|
|
||||||
def get_global_tracing_enabled():
|
def get_global_tracing_enabled():
|
||||||
|
|||||||
@@ -175,6 +175,48 @@ class TestProcessTracingInit(unittest.TestCase):
|
|||||||
finally:
|
finally:
|
||||||
mod.opentelemetry_imported = orig
|
mod.opentelemetry_imported = orig
|
||||||
|
|
||||||
|
@unittest.skipIf(not _has_otel, "OpenTelemetry not installed")
|
||||||
|
def test_service_name_priority_explicit(self):
|
||||||
|
"""Service name priority: explicit parameter > env var > default."""
|
||||||
|
with patch.dict(os.environ, {"OTEL_SERVICE_NAME": "from-env"}):
|
||||||
|
with patch.object(mod, "TracerProvider"):
|
||||||
|
with patch.object(mod, "Resource") as mock_resource:
|
||||||
|
process_tracing_init("localhost:4317", "explicit-name")
|
||||||
|
# Verify Resource.create was called with the explicit name
|
||||||
|
mock_resource.create.assert_called_once()
|
||||||
|
call_kwargs = mock_resource.create.call_args[1]
|
||||||
|
self.assertEqual(
|
||||||
|
call_kwargs["attributes"][mod.SERVICE_NAME], "explicit-name"
|
||||||
|
)
|
||||||
|
|
||||||
|
@unittest.skipIf(not _has_otel, "OpenTelemetry not installed")
|
||||||
|
def test_service_name_priority_env_var(self):
|
||||||
|
"""Service name falls back to OTEL_SERVICE_NAME when explicit is None."""
|
||||||
|
with patch.dict(os.environ, {"OTEL_SERVICE_NAME": "from-env"}):
|
||||||
|
with patch.object(mod, "TracerProvider"):
|
||||||
|
with patch.object(mod, "Resource") as mock_resource:
|
||||||
|
process_tracing_init("localhost:4317", None)
|
||||||
|
# Verify Resource.create was called with env var value
|
||||||
|
mock_resource.create.assert_called_once()
|
||||||
|
call_kwargs = mock_resource.create.call_args[1]
|
||||||
|
self.assertEqual(
|
||||||
|
call_kwargs["attributes"][mod.SERVICE_NAME], "from-env"
|
||||||
|
)
|
||||||
|
|
||||||
|
@unittest.skipIf(not _has_otel, "OpenTelemetry not installed")
|
||||||
|
def test_service_name_priority_default(self):
|
||||||
|
"""Service name falls back to 'sglang' when both explicit and env are unset."""
|
||||||
|
with patch.dict(os.environ, {}, clear=True):
|
||||||
|
with patch.object(mod, "TracerProvider"):
|
||||||
|
with patch.object(mod, "Resource") as mock_resource:
|
||||||
|
process_tracing_init("localhost:4317", None)
|
||||||
|
# Verify Resource.create was called with default value
|
||||||
|
mock_resource.create.assert_called_once()
|
||||||
|
call_kwargs = mock_resource.create.call_args[1]
|
||||||
|
self.assertEqual(
|
||||||
|
call_kwargs["attributes"][mod.SERVICE_NAME], "sglang"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestTraceReqContextDisabled(unittest.TestCase):
|
class TestTraceReqContextDisabled(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|||||||
Reference in New Issue
Block a user