CPU replicas start on half the machine's CPUs, not all of them: two busy llama.cpp servers each spinning on all 8 vCPUs fell to 0.8 tok/s apiece, where at 4 threads they keep 5.5. llamacpp.threads sets it per node. Inference requests can be traced over OTLP/HTTP (tracing.endpoint), with admission, schedule and upstream spans and traceparent sent to the engine. Security: onboarding no longer puts the cluster root in the system trust store and removes it where it was; the mirror's mutual-TLS API can be limited to named certificates (--api-client); init.log no longer keeps the administrator's password; a warning when auth is off on a public listen; the recorded actor is sanitised and sudo-aware; Ray's dashboard is off, and the remaining engine gaps are documented. reconciler.go and agent.go are split by topic, the status mapping of each failure is tested, and the plan's checklist is brought up to date. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
52 lines
1.6 KiB
Go
52 lines
1.6 KiB
Go
package router
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
|
|
"go.opentelemetry.io/otel"
|
|
"go.opentelemetry.io/otel/attribute"
|
|
"go.opentelemetry.io/otel/codes"
|
|
"go.opentelemetry.io/otel/propagation"
|
|
"go.opentelemetry.io/otel/trace"
|
|
)
|
|
|
|
// tracer is looked up per use rather than kept, so a provider installed after
|
|
// the router was built — as tests do — is the one spans go to.
|
|
func tracer() trace.Tracer { return otel.Tracer("gitea.mynodes.xyz/ilker/llmgw/internal/router") }
|
|
|
|
// startInference opens the span for one inference request, continuing the
|
|
// caller's trace when it sent a traceparent.
|
|
func startInference(req *http.Request, path, requestID string) (context.Context, trace.Span) {
|
|
ctx := otel.GetTextMapPropagator().Extract(req.Context(), propagation.HeaderCarrier(req.Header))
|
|
return tracer().Start(ctx, "inference "+path,
|
|
trace.WithSpanKind(trace.SpanKindServer),
|
|
trace.WithAttributes(
|
|
attribute.String("llmgw.request_id", requestID),
|
|
attribute.String("http.route", path),
|
|
))
|
|
}
|
|
|
|
// endSpan closes a span, marking it failed when err is set.
|
|
func endSpan(span trace.Span, err error) {
|
|
if err != nil {
|
|
span.RecordError(err)
|
|
span.SetStatus(codes.Error, err.Error())
|
|
}
|
|
span.End()
|
|
}
|
|
|
|
// withTraceparent is h with the current span's context in it, for the engine.
|
|
// A copy: the request's header is sent on every attempt, each its own span.
|
|
func withTraceparent(ctx context.Context, h http.Header) http.Header {
|
|
if !trace.SpanContextFromContext(ctx).IsValid() {
|
|
return h
|
|
}
|
|
out := h.Clone()
|
|
if out == nil {
|
|
out = http.Header{}
|
|
}
|
|
otel.GetTextMapPropagator().Inject(ctx, propagation.HeaderCarrier(out))
|
|
return out
|
|
}
|