package o11yapiserver import ( "net/http" "github.com/hanzoai/o11y/pkg/http/handler" "github.com/hanzoai/o11y/pkg/http/routing" "github.com/hanzoai/o11y/pkg/types" "github.com/hanzoai/o11y/pkg/types/metricsexplorertypes" ) // ALL of these routes are ALSO declared as typed ops at the module's mount seam // (metrics.go in the repo root), which is what carries them into the composed // document, the SDK, the CLI and the agent surface. That is a second DISPATCH, // never a second implementation: the ops answer by handing the call to this // router, so the handlers below stay the one place the work is performed — and // the gates declared here (ViewAccess on the reads, EditAccess on the metadata // write) stay the one place access is decided. Both halves are needed — the ops // serve the composed binary, this router serves the standalone process, which // has no native router to register an op on — so deleting either drops one of // the two deployments. func (provider *provider) addMetricsExplorerRoutes(router routing.Router) { router.Get("/v1/o11y/metrics", handler.New( provider.authzMiddleware.ViewAccess(provider.metricsExplorerHandler.ListMetrics), handler.OpenAPIDef{ ID: "ListMetrics", Tags: []string{"metrics"}, Summary: "List metric names", Description: "This endpoint returns a list of distinct metric names within the specified time range", Request: nil, RequestQuery: new(metricsexplorertypes.ListMetricsParams), RequestContentType: "", Response: new(metricsexplorertypes.ListMetricsResponse), ResponseContentType: "application/json", SuccessStatusCode: http.StatusOK, ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusUnauthorized, http.StatusInternalServerError}, Deprecated: false, SecuritySchemes: newSecuritySchemes(types.RoleViewer), })) router.Post("/v1/o11y/metrics/stats", handler.New( provider.authzMiddleware.ViewAccess(provider.metricsExplorerHandler.GetStats), handler.OpenAPIDef{ ID: "GetMetricsStats", Tags: []string{"metrics"}, Summary: "Get metrics statistics", Description: "This endpoint provides list of metrics with their number of samples and timeseries for the given time range", Request: new(metricsexplorertypes.StatsRequest), RequestContentType: "application/json", Response: new(metricsexplorertypes.StatsResponse), ResponseContentType: "application/json", SuccessStatusCode: http.StatusOK, ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusUnauthorized, http.StatusInternalServerError}, Deprecated: false, SecuritySchemes: newSecuritySchemes(types.RoleViewer), })) router.Post("/v1/o11y/metrics/treemap", handler.New( provider.authzMiddleware.ViewAccess(provider.metricsExplorerHandler.GetTreemap), handler.OpenAPIDef{ ID: "GetMetricsTreemap", Tags: []string{"metrics"}, Summary: "Get metrics treemap", Description: "This endpoint returns a treemap visualization showing the proportional distribution of metrics by sample count or time series count", Request: new(metricsexplorertypes.TreemapRequest), RequestContentType: "application/json", Response: new(metricsexplorertypes.TreemapResponse), ResponseContentType: "application/json", SuccessStatusCode: http.StatusOK, ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusUnauthorized, http.StatusInternalServerError}, Deprecated: false, SecuritySchemes: newSecuritySchemes(types.RoleViewer), })) router.Get("/v1/o11y/metrics/attributes", handler.New( provider.authzMiddleware.ViewAccess(provider.metricsExplorerHandler.GetMetricAttributes), handler.OpenAPIDef{ ID: "GetMetricAttributes", Tags: []string{"metrics"}, Summary: "Get metric attributes", Description: "This endpoint returns attribute keys and their unique values for a specified metric", Request: nil, RequestQuery: new(metricsexplorertypes.MetricAttributesRequest), RequestContentType: "", Response: new(metricsexplorertypes.MetricAttributesResponse), ResponseContentType: "application/json", SuccessStatusCode: http.StatusOK, ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusUnauthorized, http.StatusNotFound, http.StatusInternalServerError}, Deprecated: false, SecuritySchemes: newSecuritySchemes(types.RoleViewer), })) router.Get("/v1/o11y/metrics/metadata", handler.New( provider.authzMiddleware.ViewAccess(provider.metricsExplorerHandler.GetMetricMetadata), handler.OpenAPIDef{ ID: "GetMetricMetadata", Tags: []string{"metrics"}, Summary: "Get metric metadata", Description: "This endpoint returns metadata information like metric description, unit, type, temporality, monotonicity for a specified metric", Request: nil, RequestQuery: new(metricsexplorertypes.MetricNameQuery), RequestContentType: "", Response: new(metricsexplorertypes.MetricMetadata), ResponseContentType: "application/json", SuccessStatusCode: http.StatusOK, ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusUnauthorized, http.StatusNotFound, http.StatusInternalServerError}, Deprecated: false, SecuritySchemes: newSecuritySchemes(types.RoleViewer), })) router.Post("/v1/o11y/metrics/metadata", handler.New( provider.authzMiddleware.EditAccess(provider.metricsExplorerHandler.UpdateMetricMetadata), handler.OpenAPIDef{ ID: "UpdateMetricMetadata", Tags: []string{"metrics"}, Summary: "Update metric metadata", Description: "This endpoint helps to update metadata information like metric description, unit, type, temporality, monotonicity for a specified metric", Request: new(metricsexplorertypes.UpdateMetricMetadataRequest), RequestContentType: "application/json", Response: nil, ResponseContentType: "application/json", SuccessStatusCode: http.StatusOK, ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusUnauthorized, http.StatusInternalServerError}, Deprecated: false, SecuritySchemes: newSecuritySchemes(types.RoleEditor), })) router.Get("/v1/o11y/metrics/highlights", handler.New( provider.authzMiddleware.ViewAccess(provider.metricsExplorerHandler.GetMetricHighlights), handler.OpenAPIDef{ ID: "GetMetricHighlights", Tags: []string{"metrics"}, Summary: "Get metric highlights", Description: "This endpoint returns highlights like number of datapoints, totaltimeseries, active time series, last received time for a specified metric", Request: nil, RequestQuery: new(metricsexplorertypes.MetricNameQuery), RequestContentType: "", Response: new(metricsexplorertypes.MetricHighlightsResponse), ResponseContentType: "application/json", SuccessStatusCode: http.StatusOK, ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusUnauthorized, http.StatusNotFound, http.StatusInternalServerError}, Deprecated: false, SecuritySchemes: newSecuritySchemes(types.RoleViewer), })) router.Get("/v1/o11y/metrics/alerts", handler.New( provider.authzMiddleware.ViewAccess(provider.metricsExplorerHandler.GetMetricAlerts), handler.OpenAPIDef{ ID: "GetMetricAlerts", Tags: []string{"metrics"}, Summary: "Get metric alerts", Description: "This endpoint returns associated alerts for a specified metric", Request: nil, RequestQuery: new(metricsexplorertypes.MetricNameQuery), RequestContentType: "", Response: new(metricsexplorertypes.MetricAlertsResponse), ResponseContentType: "application/json", SuccessStatusCode: http.StatusOK, ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusUnauthorized, http.StatusNotFound, http.StatusInternalServerError}, Deprecated: false, SecuritySchemes: newSecuritySchemes(types.RoleViewer), })) // GetMetricDashboardsV2 is the one handler for /v1/o11y/metrics/dashboards. router.Get("/v1/o11y/metrics/dashboards", handler.New( provider.authzMiddleware.ViewAccess(provider.metricsExplorerHandler.GetMetricDashboardsV2), handler.OpenAPIDef{ ID: "GetMetricDashboardsV2", Tags: []string{"metrics"}, Summary: "Get metric dashboards (v2)", Description: "This endpoint returns associated v2 dashboards for a specified metric", Request: nil, RequestQuery: new(metricsexplorertypes.MetricNameQuery), RequestContentType: "", Response: new(metricsexplorertypes.MetricDashboardPanelsResponse), ResponseContentType: "application/json", SuccessStatusCode: http.StatusOK, ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusUnauthorized, http.StatusNotFound, http.StatusInternalServerError}, Deprecated: false, SecuritySchemes: newSecuritySchemes(types.RoleViewer), })) router.Post("/v1/o11y/metrics/inspect", handler.New( provider.authzMiddleware.ViewAccess(provider.metricsExplorerHandler.InspectMetrics), handler.OpenAPIDef{ ID: "InspectMetrics", Tags: []string{"metrics"}, Summary: "Inspect raw metric data points", Description: "Returns raw time series data points for a metric within a time range (max 30 minutes). Each series includes labels and timestamp/value pairs.", Request: new(metricsexplorertypes.InspectMetricsRequest), RequestContentType: "application/json", Response: new(metricsexplorertypes.InspectMetricsResponse), ResponseContentType: "application/json", SuccessStatusCode: http.StatusOK, ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusUnauthorized, http.StatusInternalServerError}, Deprecated: false, SecuritySchemes: newSecuritySchemes(types.RoleViewer), })) router.Get("/v1/o11y/metrics/onboarding", handler.New( provider.authzMiddleware.ViewAccess(provider.metricsExplorerHandler.GetOnboardingStatus), handler.OpenAPIDef{ ID: "GetMetricsOnboardingStatus", Tags: []string{"metrics"}, Summary: "Check if non-O11y metrics have been received", Description: "Lightweight endpoint that checks if any non-O11y metrics have been ingested, used for onboarding status detection", Request: nil, RequestContentType: "", Response: new(metricsexplorertypes.MetricsOnboardingResponse), ResponseContentType: "application/json", SuccessStatusCode: http.StatusOK, ErrorStatusCodes: []int{http.StatusUnauthorized, http.StatusInternalServerError}, Deprecated: false, SecuritySchemes: newSecuritySchemes(types.RoleViewer), })) }