Loki: Implement custom /config handler (#4785)

* Implement custom /config handler.

* Make `customConfigEndpointHandlerFn` public.
pull/4842/head
Dylan Guedes 4 years ago committed by GitHub
parent 11bf736c90
commit 347e3e37cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      cmd/loki/main.go
  2. 21
      pkg/loki/loki.go
  3. 80
      pkg/loki/loki_test.go

@ -93,6 +93,6 @@ func main() {
level.Info(util_log.Logger).Log("msg", "Starting Loki", "version", version.Info())
err = t.Run()
err = t.Run(loki.RunOpts{})
util_log.CheckFatal("running loki", err)
}

@ -280,8 +280,23 @@ func newDefaultConfig() *Config {
return defaultConfig
}
// RunOpts configures custom behavior for running Loki.
type RunOpts struct {
// CustomConfigEndpointHandlerFn is the handlerFunc to be used by the /config endpoint.
// If empty, default handlerFunc will be used.
CustomConfigEndpointHandlerFn func(http.ResponseWriter, *http.Request)
}
func (t *Loki) bindConfigEndpoint(opts RunOpts) {
configEndpointHandlerFn := configHandler(t.Cfg, newDefaultConfig())
if opts.CustomConfigEndpointHandlerFn != nil {
configEndpointHandlerFn = opts.CustomConfigEndpointHandlerFn
}
t.Server.HTTP.Path("/config").Methods("GET").HandlerFunc(configEndpointHandlerFn)
}
// Run starts Loki running, and blocks until a Loki stops.
func (t *Loki) Run() error {
func (t *Loki) Run(opts RunOpts) error {
serviceMap, err := t.ModuleManager.InitModuleServices(t.Cfg.Target...)
if err != nil {
return err
@ -306,8 +321,8 @@ func (t *Loki) Run() error {
grpc_health_v1.RegisterHealthServer(t.Server.GRPC, grpcutil.NewHealthCheck(sm))
// This adds a way to see the config and the changes compared to the defaults
t.Server.HTTP.Path("/config").Methods("GET").HandlerFunc(configHandler(t.Cfg, newDefaultConfig()))
// Config endpoint adds a way to see the config and the changes compared to the defaults.
t.bindConfigEndpoint(opts)
// Each component serves its version.
t.Server.HTTP.Path("/loki/api/v1/status/buildinfo").Methods("GET").HandlerFunc(versionHandler())

@ -3,7 +3,10 @@ package loki
import (
"bytes"
"flag"
"fmt"
"io"
"io/ioutil"
"net/http"
"strings"
"testing"
"time"
@ -86,3 +89,80 @@ func TestLoki_isModuleEnabled(t1 *testing.T) {
})
}
}
func TestLoki_CustomRunOptsBehavior(t *testing.T) {
yamlConfig := `target: querier
server:
http_listen_port: 3100
common:
path_prefix: /tmp/loki
ring:
kvstore:
store: inmemory
schema_config:
configs:
- from: 2020-10-24
store: boltdb-shipper
row_shards: 10
object_store: filesystem
schema: v11
index:
prefix: index_
period: 24h`
cfgWrapper, _, err := configWrapperFromYAML(t, yamlConfig, nil)
require.NoError(t, err)
loki, err := New(cfgWrapper.Config)
require.NoError(t, err)
lokiHealthCheck := func() error {
// wait for Loki HTTP server to be ready.
// retries at most 10 times (1 second in total) to avoid infinite loops when no timeout is set.
for i := 0; i < 10; i++ {
// waits until request to /ready doesn't error.
resp, err := http.DefaultClient.Get("http://localhost:3100/ready")
if err != nil {
time.Sleep(time.Millisecond * 200)
continue
}
// waits until /ready returns OK.
if resp.StatusCode != http.StatusOK {
time.Sleep(time.Millisecond * 200)
continue
}
// Loki is healthy.
return nil
}
return fmt.Errorf("loki HTTP not healthy")
}
customHandlerInvoked := false
customHandler := func(w http.ResponseWriter, _ *http.Request) {
customHandlerInvoked = true
_, err := w.Write([]byte("abc"))
require.NoError(t, err)
}
// Run Loki querier in a different go routine and with custom /config handler.
go func() {
err := loki.Run(RunOpts{CustomConfigEndpointHandlerFn: customHandler})
require.NoError(t, err)
}()
err = lokiHealthCheck()
require.NoError(t, err)
resp, err := http.DefaultClient.Get("http://localhost:3100/config")
require.NoError(t, err)
defer resp.Body.Close()
bBytes, err := ioutil.ReadAll(resp.Body)
require.NoError(t, err)
require.Equal(t, string(bBytes), "abc")
assert.True(t, customHandlerInvoked)
}

Loading…
Cancel
Save