Skip to content

feat: Add endpoint returning tenant configured limits #17101

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 16, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions pkg/loki/config_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"net/http"
"reflect"

"github.com/gorilla/mux"
"gopkg.in/yaml.v2"
)

Expand Down Expand Up @@ -113,6 +114,29 @@ func configHandler(actualCfg interface{}, defaultCfg interface{}) http.HandlerFu
}
}

func (t *Loki) tenantLimitsHandler() func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
if t.TenantLimits == nil {
http.Error(w, "Tenant configs not enabled", http.StatusNotFound)
return
}

user := mux.Vars(r)["tenant"]
if user == "" {
http.Error(w, "Tenant ID not provided", http.StatusBadRequest)
return
}

limit := t.TenantLimits.TenantLimits(user)
if limit == nil {
http.Error(w, "Tenant limits not found", http.StatusNotFound)
return
}

writeYAMLResponse(w, limit)
}
}

// writeYAMLResponse writes some YAML as a HTTP response.
func writeYAMLResponse(w http.ResponseWriter, v interface{}) {
// There is not standardised content-type for YAML, text/plain ensures the
Expand Down
7 changes: 3 additions & 4 deletions pkg/loki/loki.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@ import (
rt "runtime"
"time"

"go.uber.org/atomic"

"google.golang.org/grpc/health/grpc_health_v1"

"github.com/fatih/color"
"github.com/felixge/fgprof"
"github.com/go-kit/log/level"
Expand All @@ -30,6 +26,8 @@ import (
"github.com/grafana/dskit/signals"
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
"go.uber.org/atomic"
"google.golang.org/grpc/health/grpc_health_v1"

"github.com/grafana/loki/v3/pkg/analytics"
blockbuilder "github.com/grafana/loki/v3/pkg/blockbuilder/builder"
Expand Down Expand Up @@ -505,6 +503,7 @@ func (t *Loki) bindConfigEndpoint(opts RunOpts) {
configEndpointHandlerFn = opts.CustomConfigEndpointHandlerFn
}
t.Server.HTTP.Path("/config").Methods("GET").HandlerFunc(configEndpointHandlerFn)
t.Server.HTTP.Path("/config/tenant/{tenant}/limits").Methods("GET").HandlerFunc(t.tenantLimitsHandler())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if we have a root prefix for paths like this? given that this is now going to be something relied upon by other services I think the path should have a version in it, if that's not already provided by an additional prefix somewhere else

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't add any prefix to that route. My concern with adding it under /loki/api/v1 is that I think we risk to somehow accidentally exposte the endpoint and make it public. I see this more like an operator endpoint similar to the /config or /ring ones.

I agree adding versioning here makes sense, what about /config/tenant/v1/{tenant}/limits?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm also wary about how this changes our multi-tenant paradigm, might it be better to not have a tenant path param and instead use headers the way we do multi-tenant in the rest of our API's?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, good idea 👍 I will get the tenant from the header

}

// ListTargets prints a list of available user visible targets and their
Expand Down