157 lines
4.3 KiB
Go
157 lines
4.3 KiB
Go
package v1alpha2
|
|
|
|
import (
|
|
"github.com/emicklei/go-restful"
|
|
"kubesphere.io/kubesphere/pkg/api"
|
|
"kubesphere.io/kubesphere/pkg/models/logging"
|
|
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
|
|
loggingclient "kubesphere.io/kubesphere/pkg/simple/client/logging"
|
|
util "kubesphere.io/kubesphere/pkg/utils/stringutils"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
LevelCluster = iota
|
|
LevelContainer
|
|
|
|
// query type, default to `query`
|
|
TypeStat = "statistics"
|
|
TypeHist = "histogram"
|
|
TypeExport = "export"
|
|
|
|
Ascending = "asc"
|
|
Descending = "desc"
|
|
)
|
|
|
|
type handler struct {
|
|
k k8s.Client
|
|
lo logging.LoggingOperator
|
|
}
|
|
|
|
func newHandler(k k8s.Client, l loggingclient.Interface) *handler {
|
|
return &handler{k, logging.NewLoggingOperator(l)}
|
|
}
|
|
|
|
func (h handler) handleClusterQuery(req *restful.Request, resp *restful.Response) {
|
|
h.get(req, LevelCluster, resp)
|
|
}
|
|
|
|
func (h handler) handleContainerQuery(req *restful.Request, resp *restful.Response) {
|
|
h.get(req, LevelContainer, resp)
|
|
}
|
|
|
|
func (h handler) get(req *restful.Request, lvl int, resp *restful.Response) {
|
|
typ := req.QueryParameter("type")
|
|
|
|
noHit, sf, err := h.newSearchFilter(req, lvl)
|
|
if err != nil {
|
|
api.HandleBadRequest(resp, nil, err)
|
|
}
|
|
if noHit {
|
|
handleNoHit(typ, resp)
|
|
return
|
|
}
|
|
|
|
switch typ {
|
|
case TypeStat:
|
|
res, err := h.lo.GetCurrentStats(sf)
|
|
if err != nil {
|
|
api.HandleInternalError(resp, nil, err)
|
|
}
|
|
resp.WriteAsJson(res)
|
|
case TypeHist:
|
|
interval := req.QueryParameter("interval")
|
|
res, err := h.lo.CountLogsByInterval(sf, interval)
|
|
if err != nil {
|
|
api.HandleInternalError(resp, nil, err)
|
|
}
|
|
resp.WriteAsJson(res)
|
|
case TypeExport:
|
|
resp.Header().Set(restful.HEADER_ContentType, "text/plain")
|
|
resp.Header().Set("Content-Disposition", "attachment")
|
|
err := h.lo.ExportLogs(sf, resp.ResponseWriter)
|
|
if err != nil {
|
|
api.HandleInternalError(resp, nil, err)
|
|
}
|
|
default:
|
|
from, _ := strconv.ParseInt(req.QueryParameter("from"), 10, 64)
|
|
size, err := strconv.ParseInt(req.QueryParameter("size"), 10, 64)
|
|
if err != nil {
|
|
size = 10
|
|
}
|
|
order := req.QueryParameter("sort")
|
|
if order != Ascending {
|
|
order = Descending
|
|
}
|
|
res, err := h.lo.SearchLogs(sf, from, size, order)
|
|
if err != nil {
|
|
api.HandleInternalError(resp, nil, err)
|
|
}
|
|
resp.WriteAsJson(res)
|
|
}
|
|
}
|
|
|
|
func (h handler) newSearchFilter(req *restful.Request, level int) (bool, loggingclient.SearchFilter, error) {
|
|
var sf loggingclient.SearchFilter
|
|
|
|
switch level {
|
|
case LevelCluster:
|
|
sf.NamespaceFilter = h.intersect(
|
|
util.Split(req.QueryParameter("namespaces"), ","),
|
|
util.Split(strings.ToLower(req.QueryParameter("namespace_query")), ","),
|
|
util.Split(req.QueryParameter("workspaces"), ","),
|
|
util.Split(strings.ToLower(req.QueryParameter("workspace_query")), ","))
|
|
sf.WorkloadFilter = util.Split(req.QueryParameter("workloads"), ",")
|
|
sf.WorkloadSearch = util.Split(req.QueryParameter("workload_query"), ",")
|
|
sf.PodFilter = util.Split(req.QueryParameter("pods"), ",")
|
|
sf.PodSearch = util.Split(req.QueryParameter("pod_query"), ",")
|
|
sf.ContainerFilter = util.Split(req.QueryParameter("containers"), ",")
|
|
sf.ContainerSearch = util.Split(req.QueryParameter("container_query"), ",")
|
|
case LevelContainer:
|
|
sf.NamespaceFilter = h.withCreationTime(req.PathParameter("namespace"))
|
|
sf.PodFilter = []string{req.PathParameter("pod")}
|
|
sf.ContainerFilter = []string{req.PathParameter("container")}
|
|
}
|
|
|
|
sf.LogSearch = util.Split(req.QueryParameter("log_query"), ",")
|
|
|
|
var err error
|
|
now := time.Now()
|
|
// If time is not given, set it to now.
|
|
if req.QueryParameter("start_time") == "" {
|
|
sf.Starttime = now
|
|
} else {
|
|
sf.Starttime, err = time.Parse(time.RFC3339, req.QueryParameter("start_time"))
|
|
if err != nil {
|
|
return false, sf, err
|
|
}
|
|
}
|
|
if req.QueryParameter("end_time") == "" {
|
|
sf.Endtime = now
|
|
} else {
|
|
sf.Endtime, err = time.Parse(time.RFC3339, req.QueryParameter("end_time"))
|
|
if err != nil {
|
|
return false, sf, err
|
|
}
|
|
}
|
|
|
|
return len(sf.NamespaceFilter) == 0, sf, nil
|
|
}
|
|
|
|
func handleNoHit(typ string, resp *restful.Response) {
|
|
switch typ {
|
|
case TypeStat:
|
|
resp.WriteAsJson(new(loggingclient.Statistics))
|
|
case TypeHist:
|
|
resp.WriteAsJson(new(loggingclient.Histogram))
|
|
case TypeExport:
|
|
resp.Header().Set(restful.HEADER_ContentType, "text/plain")
|
|
resp.Header().Set("Content-Disposition", "attachment")
|
|
resp.Write(nil)
|
|
default:
|
|
resp.WriteAsJson(new(loggingclient.Logs))
|
|
}
|
|
}
|