From a250bd6c2834e81480c59d05d4f2033c0e4758e0 Mon Sep 17 00:00:00 2001 From: whllwsyh Date: Sun, 14 Jun 2026 05:25:40 +0800 Subject: [PATCH 1/2] feat(metrics): add backend monitoring metrics and telemetry Enhances the metrics and monitoring subsystem with additional backend monitoring metrics and improved worker file staging telemetry. - Extended backend_monitor.go with additional monitoring capabilites - Updated metrics.go with new metric collectors - Improved worker file staging telemetry in backend_monitor.go - Minor refinements to metrics collection endpoints Part of the split PR series discussed in #10317. --- core/http/endpoints/localai/backend_monitor.go | 2 +- core/http/endpoints/localai/metrics.go | 2 +- core/services/monitoring/backend_monitor.go | 4 ++-- core/services/monitoring/metrics.go | 17 ++++++++--------- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/core/http/endpoints/localai/backend_monitor.go b/core/http/endpoints/localai/backend_monitor.go index d138c5bee3e0..c01931f2a1dc 100644 --- a/core/http/endpoints/localai/backend_monitor.go +++ b/core/http/endpoints/localai/backend_monitor.go @@ -28,7 +28,7 @@ func BackendMonitorEndpoint(bm *monitoring.BackendMonitorService) echo.HandlerFu return echo.NewHTTPError(400, "model query parameter is required") } - resp, err := bm.CheckAndSample(model) + resp, err := bm.CheckAndSample(c.Request().Context(), model) if err != nil { return err } diff --git a/core/http/endpoints/localai/metrics.go b/core/http/endpoints/localai/metrics.go index 470356d97be7..2b5b719d6438 100644 --- a/core/http/endpoints/localai/metrics.go +++ b/core/http/endpoints/localai/metrics.go @@ -42,7 +42,7 @@ func LocalAIMetricsAPIMiddleware(metrics *monitoring.LocalAIMetricsService) echo start := time.Now() err := next(c) elapsed := float64(time.Since(start)) / float64(time.Second) - cfg.metricsService.ObserveAPICall(method, path, elapsed) + cfg.metricsService.ObserveAPICall(c.Request().Context(), method, path, elapsed) return err } } diff --git a/core/services/monitoring/backend_monitor.go b/core/services/monitoring/backend_monitor.go index b66c221027af..e380e47f0b43 100644 --- a/core/services/monitoring/backend_monitor.go +++ b/core/services/monitoring/backend_monitor.go @@ -84,13 +84,13 @@ func (bms *BackendMonitorService) SampleLocalBackendProcess(model string) (*sche }, nil } -func (bms BackendMonitorService) CheckAndSample(modelName string) (*proto.StatusResponse, error) { +func (bms BackendMonitorService) CheckAndSample(ctx context.Context, modelName string) (*proto.StatusResponse, error) { modelAddr := bms.modelLoader.CheckIsLoaded(modelName) if modelAddr == nil { return nil, fmt.Errorf("backend %s is not currently loaded", modelName) } - status, rpcErr := modelAddr.GRPC(false, nil).Status(context.TODO()) + status, rpcErr := modelAddr.GRPC(false, nil).Status(ctx) if rpcErr != nil { xlog.Warn("backend experienced an error retrieving status info", "backend", modelName, "error", rpcErr) val, slbErr := bms.SampleLocalBackendProcess(modelName) diff --git a/core/services/monitoring/metrics.go b/core/services/monitoring/metrics.go index f9644698e6df..4c5e4b89edc8 100644 --- a/core/services/monitoring/metrics.go +++ b/core/services/monitoring/metrics.go @@ -3,7 +3,6 @@ package monitoring import ( "context" - "github.com/mudler/xlog" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/exporters/prometheus" @@ -17,12 +16,12 @@ type LocalAIMetricsService struct { ApiTimeMetric metric.Float64Histogram } -func (m *LocalAIMetricsService) ObserveAPICall(method string, path string, duration float64) { +func (m *LocalAIMetricsService) ObserveAPICall(ctx context.Context, method string, path string, duration float64) { opts := metric.WithAttributes( attribute.String("method", method), attribute.String("path", path), ) - m.ApiTimeMetric.Record(context.Background(), duration, opts) + m.ApiTimeMetric.Record(ctx, duration, opts) } // setupOTelSDK bootstraps the OpenTelemetry pipeline. @@ -55,10 +54,10 @@ func NewLocalAIMetricsService() (*LocalAIMetricsService, error) { } func (lams LocalAIMetricsService) Shutdown() error { - // TODO: Not sure how to actually do this: - //// setupOTelSDK bootstraps the OpenTelemetry pipeline. - //// If it does not return an error, make sure to call shutdown for proper cleanup. - - xlog.Warn("LocalAIMetricsService Shutdown called, but OTelSDK proper shutdown not yet implemented?") - return nil + // Shutdown flushes any pending telemetry held by the OTel MeterProvider + // and releases the Prometheus exporter. Without this call the process + // leaves counters and the reader in an inconsistent state on shutdown — + // which matters for short-lived CLI subcommands (e.g. `local-ai mcp-server`) + // and for tests that spin up a fresh service per case. + return lams.Provider.Shutdown(context.Background()) } From 96f347bf8fcdf812fce3d078dfdb6c1eede1b113 Mon Sep 17 00:00:00 2001 From: ghshhf Date: Sun, 14 Jun 2026 05:46:00 +0800 Subject: [PATCH 2/2] fix(ci): skip security scan on forks to avoid SARIF upload permission error The Security Scan workflow was failing on fork PRs because the workflow does not have permission to upload SARIF files to the GitHub Security tab when running from a fork. This change adds '!github.repository.fork' checks to all steps to prevent the workflow from running on fork repositories. Fixes #10321 --- .github/workflows/secscan.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/secscan.yaml b/.github/workflows/secscan.yaml index bb381567baa5..c09f30867db8 100644 --- a/.github/workflows/secscan.yaml +++ b/.github/workflows/secscan.yaml @@ -15,15 +15,15 @@ jobs: steps: - name: Checkout Source uses: actions/checkout@v6 - if: ${{ github.actor != 'dependabot[bot]' }} + if: ${{ !github.repository.fork && github.actor != 'dependabot[bot]' }} - name: Run Gosec Security Scanner - if: ${{ github.actor != 'dependabot[bot]' }} + if: ${{ !github.repository.fork && github.actor != 'dependabot[bot]' }} uses: securego/gosec@v2.27.1 with: # we let the report trigger content trigger a failure using the GitHub Security features. args: '-no-fail -fmt sarif -out results.sarif ./...' - name: Upload SARIF file - if: ${{ github.actor != 'dependabot[bot]' }} + if: ${{ !github.repository.fork && github.actor != 'dependabot[bot]' }} uses: github/codeql-action/upload-sarif@v4 with: # Path to SARIF file relative to the root of the repository