Skip to content

Commit 4099d11

Browse files
GT-30 API for setting operator log level (#1087)
1 parent 38e3ce8 commit 4099d11

File tree

14 files changed

+408
-33
lines changed

14 files changed

+408
-33
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
- (Bugfix) Add Panic Handler
6969
- (Bugfix) Unify yaml packages
7070
- (Feature) Add new GRPC and HTTP API
71+
- (Feature) Add new API endpoints to allow getting and setting operator logging level
7172

7273
## [1.2.13](https://github.com/arangodb/kube-arangodb/tree/1.2.13) (2022-06-07)
7374
- (Bugfix) Fix arangosync members state inspection

docs/design/api.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ The HTTP API is running at endpoint specified by operator command line options `
1616

1717
The HTTP API exposes endpoints used to get operator health and readiness status, operator version, and prometheus-compatible metrics.
1818

19-
For now only `/metrics` endpoint require authorization.
19+
For now only `/metrics` and `/log/level` endpoints require authorization.
2020

2121

2222
## gRPC

pkg/api/api.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ func NewServer(cli typedCore.CoreV1Interface, cfg ServerConfig) (*Server, error)
9494
),
9595
grpcAddress: cfg.GRPCAddress,
9696
}
97-
handler, err := buildHTTPHandler(cfg, auth)
97+
handler, err := buildHTTPHandler(s, cfg, auth)
9898
if err != nil {
9999
return nil, err
100100
}

pkg/api/grpc.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@ package api
2222

2323
import (
2424
"context"
25+
"fmt"
2526

2627
pb "github.com/arangodb/kube-arangodb/pkg/api/server"
28+
"github.com/arangodb/kube-arangodb/pkg/logging"
2729
"github.com/arangodb/kube-arangodb/pkg/version"
2830
)
2931

@@ -37,3 +39,46 @@ func (s *Server) GetVersion(ctx context.Context, _ *pb.Empty) (*pb.Version, erro
3739
BuildDate: v.BuildDate,
3840
}, nil
3941
}
42+
43+
var loglevelMap = map[pb.LogLevel]logging.Level{
44+
pb.LogLevel_TRACE: logging.Trace,
45+
pb.LogLevel_DEBUG: logging.Debug,
46+
pb.LogLevel_INFO: logging.Info,
47+
pb.LogLevel_WARN: logging.Warn,
48+
pb.LogLevel_ERROR: logging.Error,
49+
pb.LogLevel_FATAL: logging.Fatal,
50+
}
51+
52+
func logLevelToGRPC(l logging.Level) pb.LogLevel {
53+
for grpcVal, localVal := range loglevelMap {
54+
if l == localVal {
55+
return grpcVal
56+
}
57+
}
58+
return pb.LogLevel_DEBUG
59+
}
60+
61+
func (s *Server) GetLogLevel(ctx context.Context, _ *pb.Empty) (*pb.LogLevelConfig, error) {
62+
l := s.getLogLevelsByTopics()
63+
64+
topics := make(map[string]pb.LogLevel, len(l))
65+
for topic, level := range l {
66+
topics[topic] = logLevelToGRPC(level)
67+
}
68+
return &pb.LogLevelConfig{
69+
Topics: topics,
70+
}, nil
71+
}
72+
73+
func (s *Server) SetLogLevel(ctx context.Context, cfg *pb.LogLevelConfig) (*pb.Empty, error) {
74+
l := make(map[string]logging.Level, len(cfg.Topics))
75+
for topic, grpcLevel := range cfg.Topics {
76+
level, ok := loglevelMap[grpcLevel]
77+
if !ok {
78+
return &pb.Empty{}, fmt.Errorf("unknown log level %s for topic %s", grpcLevel, topic)
79+
}
80+
l[topic] = level
81+
}
82+
s.setLogLevelsByTopics(l)
83+
return &pb.Empty{}, nil
84+
}

pkg/api/http.go

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,14 @@ import (
2626
"github.com/gin-gonic/gin"
2727
prometheus "github.com/prometheus/client_golang/prometheus/promhttp"
2828

29+
"github.com/arangodb/kube-arangodb/pkg/logging"
2930
"github.com/arangodb/kube-arangodb/pkg/util/errors"
3031
operatorHTTP "github.com/arangodb/kube-arangodb/pkg/util/http"
3132
"github.com/arangodb/kube-arangodb/pkg/util/probe"
3233
"github.com/arangodb/kube-arangodb/pkg/version"
3334
)
3435

35-
func buildHTTPHandler(cfg ServerConfig, auth *authorization) (http.Handler, error) {
36+
func buildHTTPHandler(s *Server, cfg ServerConfig, auth *authorization) (http.Handler, error) {
3637
gin.SetMode(gin.ReleaseMode)
3738
r := gin.New()
3839
r.Use(gin.Recovery())
@@ -61,6 +62,8 @@ func buildHTTPHandler(cfg ServerConfig, auth *authorization) (http.Handler, erro
6162
r.GET("/ready", gin.WrapF(handleGetReady(readyProbes...)))
6263

6364
r.GET("/metrics", auth.ensureHTTPAuth, gin.WrapH(prometheus.Handler()))
65+
r.GET("/log/level", auth.ensureHTTPAuth, s.handleGetLogLevel)
66+
r.POST("/log/level", auth.ensureHTTPAuth, s.handlePostLogLevel)
6467

6568
return r, nil
6669
}
@@ -77,3 +80,43 @@ func handleGetReady(probes ...*probe.ReadyProbe) func(w http.ResponseWriter, r *
7780
w.WriteHeader(http.StatusOK)
7881
}
7982
}
83+
84+
func (s *Server) handleGetLogLevel(c *gin.Context) {
85+
logLevels := s.getLogLevelsByTopics()
86+
topics := make(map[string]string, len(logLevels))
87+
for topic, level := range logLevels {
88+
topics[topic] = level.String()
89+
}
90+
c.JSON(http.StatusOK, gin.H{
91+
"topics": topics,
92+
})
93+
}
94+
95+
func (s *Server) handlePostLogLevel(c *gin.Context) {
96+
var req = struct {
97+
Topics map[string]string `json:"topics"`
98+
}{}
99+
100+
err := c.BindJSON(&req)
101+
if err != nil {
102+
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
103+
"msg": err.Error(),
104+
})
105+
return
106+
}
107+
108+
logLevels := make(map[string]logging.Level, len(req.Topics))
109+
for topic, levelStr := range req.Topics {
110+
l, err := logging.ParseLogLevel(levelStr)
111+
if err != nil {
112+
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
113+
"msg": err.Error(),
114+
})
115+
return
116+
}
117+
logLevels[topic] = l
118+
}
119+
120+
s.setLogLevelsByTopics(logLevels)
121+
c.JSON(http.StatusOK, gin.H{})
122+
}

pkg/api/logging.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2016-2022 ArangoDB GmbH, Cologne, Germany
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
// Copyright holder is ArangoDB GmbH, Cologne, Germany
19+
//
20+
21+
package api
22+
23+
import (
24+
"github.com/arangodb/kube-arangodb/pkg/logging"
25+
)
26+
27+
func (s *Server) getLogLevelsByTopics() map[string]logging.Level {
28+
return logging.Global().LogLevels()
29+
}
30+
31+
func (s *Server) setLogLevelsByTopics(logLevels map[string]logging.Level) {
32+
logging.Global().ApplyLogLevels(logLevels)
33+
}

0 commit comments

Comments
 (0)