[WIP] logging refactor (#1794)
* refactor logging Signed-off-by: huanggze <loganhuang@yunify.com> * refactor logging Signed-off-by: huanggze <loganhuang@yunify.com>
This commit is contained in:
@@ -1 +1,156 @@
|
||||
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, err)
|
||||
}
|
||||
if noHit {
|
||||
handleNoHit(typ, resp)
|
||||
return
|
||||
}
|
||||
|
||||
switch typ {
|
||||
case TypeStat:
|
||||
res, err := h.lo.GetCurrentStats(sf)
|
||||
if err != nil {
|
||||
api.HandleInternalError(resp, err)
|
||||
}
|
||||
resp.WriteAsJson(res)
|
||||
case TypeHist:
|
||||
interval := req.QueryParameter("interval")
|
||||
res, err := h.lo.CountLogsByInterval(sf, interval)
|
||||
if err != nil {
|
||||
api.HandleInternalError(resp, 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, 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, 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))
|
||||
}
|
||||
}
|
||||
|
||||
56
pkg/kapis/logging/v1alpha2/helper.go
Normal file
56
pkg/kapis/logging/v1alpha2/helper.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package v1alpha2
|
||||
|
||||
import (
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/klog"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/utils/stringutils"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (h handler) intersect(nsFilter []string, nsSearch []string, wsFilter []string, wsSearch []string) map[string]time.Time {
|
||||
nsList, err := h.k.Kubernetes().CoreV1().Namespaces().List(v1.ListOptions{})
|
||||
if err != nil {
|
||||
klog.Errorf("failed to list namespace, error: %s", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
inner := make(map[string]time.Time)
|
||||
|
||||
// if no search condition is set on both namespace and workspace,
|
||||
// then return all namespaces
|
||||
if nsSearch == nil && nsFilter == nil && wsSearch == nil && wsFilter == nil {
|
||||
for _, ns := range nsList.Items {
|
||||
inner[ns.Name] = ns.CreationTimestamp.Time
|
||||
}
|
||||
} else {
|
||||
for _, ns := range nsList.Items {
|
||||
if stringutils.StringIn(ns.Name, nsFilter) ||
|
||||
stringutils.StringIn(ns.Annotations[constants.WorkspaceLabelKey], wsFilter) ||
|
||||
containsIn(ns.Name, nsSearch) ||
|
||||
containsIn(ns.Annotations[constants.WorkspaceLabelKey], wsSearch) {
|
||||
inner[ns.Name] = ns.CreationTimestamp.Time
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return inner
|
||||
}
|
||||
|
||||
func containsIn(str string, subStrs []string) bool {
|
||||
for _, sub := range subStrs {
|
||||
if strings.Contains(str, sub) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (h handler) withCreationTime(name string) map[string]time.Time {
|
||||
ns, err := h.k.Kubernetes().CoreV1().Namespaces().Get(name, v1.GetOptions{})
|
||||
if err == nil {
|
||||
return map[string]time.Time{name: ns.CreationTimestamp.Time}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -22,10 +22,10 @@ import (
|
||||
"github.com/emicklei/go-restful-openapi"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"kubesphere.io/kubesphere/pkg/api/logging/v1alpha2"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/logging"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models/log"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/logging"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
@@ -36,15 +36,13 @@ const (
|
||||
|
||||
var GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha2"}
|
||||
|
||||
var (
|
||||
WebServiceBuilder = runtime.NewContainerBuilder(addWebService)
|
||||
AddToContainer = WebServiceBuilder.AddToContainer
|
||||
)
|
||||
|
||||
func addWebService(c *restful.Container) error {
|
||||
func AddToContainer(c *restful.Container, k8sClient k8s.Client, loggingClient logging.Interface) error {
|
||||
ws := runtime.NewWebService(GroupVersion)
|
||||
|
||||
ws.Route(ws.GET("/cluster").To(logging.LoggingQueryCluster).
|
||||
h := newHandler(k8sClient, loggingClient)
|
||||
|
||||
ws.Route(ws.GET("/cluster").
|
||||
To(h.handleClusterQuery).
|
||||
Doc("Query logs against the cluster.").
|
||||
Param(ws.QueryParameter("operation", "Operation type. This can be one of four types: query (for querying logs), statistics (for retrieving statistical data), histogram (for displaying log count by time interval) and export (for exporting logs). Defaults to query.").DefaultValue("query").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("workspaces", "A comma-separated list of workspaces. This field restricts the query to specified workspaces. For example, the following filter matches the workspace my-ws and demo-ws: `my-ws,demo-ws`").DataType("string").Required(false)).
|
||||
@@ -65,102 +63,13 @@ func addWebService(c *restful.Container) error {
|
||||
Param(ws.QueryParameter("from", "The offset from the result set. This field returns query results from the specified offset. It requires **operation** is set to query. Defaults to 0 (i.e. from the beginning of the result set).").DataType("integer").DefaultValue("0").Required(false)).
|
||||
Param(ws.QueryParameter("size", "Size of result to return. It requires **operation** is set to query. Defaults to 10 (i.e. 10 log records).").DataType("integer").DefaultValue("10").Required(false)).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.LogQueryTag}).
|
||||
Writes(v1alpha2.QueryResult{}).
|
||||
Returns(http.StatusOK, RespOK, v1alpha2.QueryResult{})).
|
||||
Writes(v1alpha2.APIResponse{}).
|
||||
Returns(http.StatusOK, RespOK, v1alpha2.APIResponse{})).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON, "text/plain")
|
||||
|
||||
ws.Route(ws.GET("/workspaces/{workspace}").To(logging.LoggingQueryWorkspace).
|
||||
Doc("Query logs against the specific workspace.").
|
||||
Param(ws.PathParameter("workspace", "The name of the workspace.").DataType("string").Required(true)).
|
||||
Param(ws.QueryParameter("operation", "Query type. This can be one of three types: query (for querying logs), statistics (for retrieving statistical data), and histogram (for displaying log count by time interval). Defaults to query.").DefaultValue("query").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("namespaces", "A comma-separated list of namespaces. This field restricts the query to specified namespaces. For example, the following filter matches the namespace my-ns and demo-ns: `my-ns,demo-ns`").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("namespace_query", "A comma-separated list of keywords. Differing from **namespaces**, this field performs fuzzy matching on namespaces. For example, the following value limits the query to namespaces whose name contains the word my(My,MY,...) *OR* demo(Demo,DemO,...): `my,demo`.").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("workloads", "A comma-separated list of workloads. This field restricts the query to specified workloads. For example, the following filter matches the workload my-wl and demo-wl: `my-wl,demo-wl`").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("workload_query", "A comma-separated list of keywords. Differing from **workloads**, this field performs fuzzy matching on workloads. For example, the following value limits the query to workloads whose name contains the word my(My,MY,...) *OR* demo(Demo,DemO,...): `my,demo`.").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("pods", "A comma-separated list of pods. This field restricts the query to specified pods. For example, the following filter matches the pod my-po and demo-po: `my-po,demo-po`").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("pod_query", "A comma-separated list of keywords. Differing from **pods**, this field performs fuzzy matching on pods. For example, the following value limits the query to pods whose name contains the word my(My,MY,...) *OR* demo(Demo,DemO,...): `my,demo`.").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("containers", "A comma-separated list of containers. This field restricts the query to specified containers. For example, the following filter matches the container my-cont and demo-cont: `my-cont,demo-cont`").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("container_query", "A comma-separated list of keywords. Differing from **containers**, this field performs fuzzy matching on containers. For example, the following value limits the query to containers whose name contains the word my(My,MY,...) *OR* demo(Demo,DemO,...): `my,demo`.").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("log_query", "A comma-separated list of keywords. The query returns logs which contain at least one keyword. Case-insensitive matching. For example, if the field is set to `err,INFO`, the query returns any log containing err(ERR,Err,...) *OR* INFO(info,InFo,...).").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("interval", "Time interval. It requires **operation** is set to histogram. The format is [0-9]+[smhdwMqy]. Defaults to 15m (i.e. 15 min).").DefaultValue("15m").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("start_time", "Start time of query. Default to 0. The format is a string representing milliseconds since the epoch, eg. 1559664000000.").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("end_time", "End time of query. Default to now. The format is a string representing milliseconds since the epoch, eg. 1559664000000.").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("sort", "Sort order. One of acs, desc. This field sorts logs by timestamp.").DataType("string").DefaultValue("desc").Required(false)).
|
||||
Param(ws.QueryParameter("from", "The offset from the result set. This field returns query results from the specified offset. It requires **operation** is set to query. Defaults to 0 (i.e. from the beginning of the result set).").DataType("integer").DefaultValue("0").Required(false)).
|
||||
Param(ws.QueryParameter("size", "Size of result to return. It requires **operation** is set to query. Defaults to 10 (i.e. 10 log records).").DataType("integer").DefaultValue("10").Required(false)).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.LogQueryTag}).
|
||||
Writes(v1alpha2.QueryResult{}).
|
||||
Returns(http.StatusOK, RespOK, v1alpha2.QueryResult{})).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
|
||||
ws.Route(ws.GET("/namespaces/{namespace}").To(logging.LoggingQueryNamespace).
|
||||
Doc("Query logs against the specific namespace.").
|
||||
Param(ws.PathParameter("namespace", "The name of the namespace.").DataType("string").Required(true)).
|
||||
Param(ws.QueryParameter("operation", "Query type. This can be one of three types: query (for querying logs), statistics (for retrieving statistical data), and histogram (for displaying log count by time interval). Defaults to query.").DefaultValue("query").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("workloads", "A comma-separated list of workloads. This field restricts the query to specified workloads. For example, the following filter matches the workload my-wl and demo-wl: `my-wl,demo-wl`").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("workload_query", "A comma-separated list of keywords. Differing from **workloads**, this field performs fuzzy matching on workloads. For example, the following value limits the query to workloads whose name contains the word my(My,MY,...) *OR* demo(Demo,DemO,...): `my,demo`.").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("pods", "A comma-separated list of pods. This field restricts the query to specified pods. For example, the following filter matches the pod my-po and demo-po: `my-po,demo-po`").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("pod_query", "A comma-separated list of keywords. Differing from **pods**, this field performs fuzzy matching on pods. For example, the following value limits the query to pods whose name contains the word my(My,MY,...) *OR* demo(Demo,DemO,...): `my,demo`.").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("containers", "A comma-separated list of containers. This field restricts the query to specified containers. For example, the following filter matches the container my-cont and demo-cont: `my-cont,demo-cont`").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("container_query", "A comma-separated list of keywords. Differing from **containers**, this field performs fuzzy matching on containers. For example, the following value limits the query to containers whose name contains the word my(My,MY,...) *OR* demo(Demo,DemO,...): `my,demo`.").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("log_query", "A comma-separated list of keywords. The query returns logs which contain at least one keyword. Case-insensitive matching. For example, if the field is set to `err,INFO`, the query returns any log containing err(ERR,Err,...) *OR* INFO(info,InFo,...).").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("interval", "Time interval. It requires **operation** is set to histogram. The format is [0-9]+[smhdwMqy]. Defaults to 15m (i.e. 15 min).").DefaultValue("15m").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("start_time", "Start time of query. Default to 0. The format is a string representing milliseconds since the epoch, eg. 1559664000000.").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("end_time", "End time of query. Default to now. The format is a string representing milliseconds since the epoch, eg. 1559664000000.").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("sort", "Sort order. One of acs, desc. This field sorts logs by timestamp.").DataType("string").DefaultValue("desc").Required(false)).
|
||||
Param(ws.QueryParameter("from", "The offset from the result set. This field returns query results from the specified offset. It requires **operation** is set to query. Defaults to 0 (i.e. from the beginning of the result set).").DataType("integer").DefaultValue("0").Required(false)).
|
||||
Param(ws.QueryParameter("size", "Size of result to return. It requires **operation** is set to query. Defaults to 10 (i.e. 10 log records).").DataType("integer").DefaultValue("10").Required(false)).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.LogQueryTag}).
|
||||
Writes(v1alpha2.QueryResult{}).
|
||||
Returns(http.StatusOK, RespOK, v1alpha2.QueryResult{})).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
|
||||
ws.Route(ws.GET("/namespaces/{namespace}/workloads/{workload}").To(logging.LoggingQueryWorkload).
|
||||
Doc("Query logs against the specific workload.").
|
||||
Param(ws.PathParameter("namespace", "The name of the namespace.").DataType("string").Required(true)).
|
||||
Param(ws.PathParameter("workload", "The name of the workload.").DataType("string").Required(true)).
|
||||
Param(ws.QueryParameter("operation", "Query type. This can be one of three types: query (for querying logs), statistics (for retrieving statistical data), and histogram (for displaying log count by time interval). Defaults to query.").DefaultValue("query").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("pods", "A comma-separated list of pods. This field restricts the query to specified pods. For example, the following filter matches the pod my-po and demo-po: `my-po,demo-po`").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("pod_query", "A comma-separated list of keywords. Differing from **pods**, this field performs fuzzy matching on pods. For example, the following value limits the query to pods whose name contains the word my(My,MY,...) *OR* demo(Demo,DemO,...): `my,demo`.").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("containers", "A comma-separated list of containers. This field restricts the query to specified containers. For example, the following filter matches the container my-cont and demo-cont: `my-cont,demo-cont`").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("container_query", "A comma-separated list of keywords. Differing from **containers**, this field performs fuzzy matching on containers. For example, the following value limits the query to containers whose name contains the word my(My,MY,...) *OR* demo(Demo,DemO,...): `my,demo`.").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("log_query", "A comma-separated list of keywords. The query returns logs which contain at least one keyword. Case-insensitive matching. For example, if the field is set to `err,INFO`, the query returns any log containing err(ERR,Err,...) *OR* INFO(info,InFo,...).").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("interval", "Time interval. It requires **operation** is set to histogram. The format is [0-9]+[smhdwMqy]. Defaults to 15m (i.e. 15 min).").DefaultValue("15m").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("start_time", "Start time of query. Default to 0. The format is a string representing milliseconds since the epoch, eg. 1559664000000.").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("end_time", "End time of query. Default to now. The format is a string representing milliseconds since the epoch, eg. 1559664000000.").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("sort", "Sort order. One of acs, desc. This field sorts logs by timestamp.").DataType("string").DefaultValue("desc").Required(false)).
|
||||
Param(ws.QueryParameter("from", "The offset from the result set. This field returns query results from the specified offset. It requires **operation** is set to query. Defaults to 0 (i.e. from the beginning of the result set).").DataType("integer").DefaultValue("0").Required(false)).
|
||||
Param(ws.QueryParameter("size", "Size of result to return. It requires **operation** is set to query. Defaults to 10 (i.e. 10 log records).").DataType("integer").DefaultValue("10").Required(false)).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.LogQueryTag}).
|
||||
Writes(v1alpha2.QueryResult{}).
|
||||
Returns(http.StatusOK, RespOK, v1alpha2.QueryResult{})).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
|
||||
ws.Route(ws.GET("/namespaces/{namespace}/pods/{pod}").To(logging.LoggingQueryPod).
|
||||
Doc("Query logs against the specific pod.").
|
||||
Param(ws.PathParameter("namespace", "The name of the namespace.").DataType("string").Required(true)).
|
||||
Param(ws.PathParameter("pod", "Pod name.").DataType("string").Required(true)).
|
||||
Param(ws.QueryParameter("operation", "Query type. This can be one of three types: query (for querying logs), statistics (for retrieving statistical data), and histogram (for displaying log count by time interval). Defaults to query.").DefaultValue("query").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("containers", "A comma-separated list of containers. This field restricts the query to specified containers. For example, the following filter matches the container my-cont and demo-cont: `my-cont,demo-cont`").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("container_query", "A comma-separated list of keywords. Differing from **containers**, this field performs fuzzy matching on containers. For example, the following value limits the query to containers whose name contains the word my(My,MY,...) *OR* demo(Demo,DemO,...): `my,demo`.").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("log_query", "A comma-separated list of keywords. The query returns logs which contain at least one keyword. Case-insensitive matching. For example, if the field is set to `err,INFO`, the query returns any log containing err(ERR,Err,...) *OR* INFO(info,InFo,...).").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("interval", "Time interval. It requires **operation** is set to histogram. The format is [0-9]+[smhdwMqy]. Defaults to 15m (i.e. 15 min).").DefaultValue("15m").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("start_time", "Start time of query. Default to 0. The format is a string representing milliseconds since the epoch, eg. 1559664000000.").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("end_time", "End time of query. Default to now. The format is a string representing milliseconds since the epoch, eg. 1559664000000.").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("sort", "Sort order. One of acs, desc. This field sorts logs by timestamp.").DataType("string").DefaultValue("desc").Required(false)).
|
||||
Param(ws.QueryParameter("from", "The offset from the result set. This field returns query results from the specified offset. It requires **operation** is set to query. Defaults to 0 (i.e. from the beginning of the result set).").DataType("integer").DefaultValue("0").Required(false)).
|
||||
Param(ws.QueryParameter("size", "Size of result to return. It requires **operation** is set to query. Defaults to 10 (i.e. 10 log records).").DataType("integer").DefaultValue("10").Required(false)).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.LogQueryTag}).
|
||||
Writes(v1alpha2.QueryResult{}).
|
||||
Returns(http.StatusOK, RespOK, v1alpha2.QueryResult{})).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
|
||||
ws.Route(ws.GET("/namespaces/{namespace}/pods/{pod}/containers/{container}").To(logging.LoggingQueryContainer).
|
||||
ws.Route(ws.GET("/namespaces/{namespace}/pods/{pod}/containers/{container}").
|
||||
To(h.handleContainerQuery).
|
||||
Doc("Query logs against the specific container.").
|
||||
Param(ws.PathParameter("namespace", "The name of the namespace.").DataType("string").Required(true)).
|
||||
Param(ws.PathParameter("pod", "Pod name.").DataType("string").Required(true)).
|
||||
@@ -174,47 +83,11 @@ func addWebService(c *restful.Container) error {
|
||||
Param(ws.QueryParameter("from", "The offset from the result set. This field returns query results from the specified offset. It requires **operation** is set to query. Defaults to 0 (i.e. from the beginning of the result set).").DataType("integer").DefaultValue("0").Required(false)).
|
||||
Param(ws.QueryParameter("size", "Size of result to return. It requires **operation** is set to query. Defaults to 10 (i.e. 10 log records).").DataType("integer").DefaultValue("10").Required(false)).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.LogQueryTag}).
|
||||
Writes(v1alpha2.QueryResult{}).
|
||||
Returns(http.StatusOK, RespOK, v1alpha2.QueryResult{})).
|
||||
Writes(v1alpha2.APIResponse{}).
|
||||
Returns(http.StatusOK, RespOK, v1alpha2.APIResponse{})).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON, restful.MIME_OCTET)
|
||||
|
||||
ws.Route(ws.GET("/fluentbit/outputs").To(logging.LoggingQueryFluentbitOutputs).
|
||||
Doc("List all Fluent bit output plugins.").
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.FluentBitSetting}).
|
||||
Writes(log.FluentbitOutputsResult{}).
|
||||
Returns(http.StatusOK, RespOK, log.FluentbitOutputsResult{})).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
|
||||
ws.Route(ws.POST("/fluentbit/outputs").To(logging.LoggingInsertFluentbitOutput).
|
||||
Doc("Add a new Fluent bit output plugin.").
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.FluentBitSetting}).
|
||||
Reads(fluentbitclient.OutputPlugin{}).
|
||||
Writes(log.FluentbitOutputsResult{}).
|
||||
Returns(http.StatusOK, RespOK, log.FluentbitOutputsResult{})).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
|
||||
ws.Route(ws.PUT("/fluentbit/outputs/{output}").To(logging.LoggingUpdateFluentbitOutput).
|
||||
Doc("Update the specific Fluent bit output plugin.").
|
||||
Param(ws.PathParameter("output", "ID of the output.").DataType("string").Required(true)).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.FluentBitSetting}).
|
||||
Reads(fluentbitclient.OutputPlugin{}).
|
||||
Writes(log.FluentbitOutputsResult{}).
|
||||
Returns(http.StatusOK, RespOK, log.FluentbitOutputsResult{})).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
|
||||
ws.Route(ws.DELETE("/fluentbit/outputs/{output}").To(logging.LoggingDeleteFluentbitOutput).
|
||||
Doc("Delete the specific Fluent bit output plugin.").
|
||||
Param(ws.PathParameter("output", "ID of the output.").DataType("string").Required(true)).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.FluentBitSetting}).
|
||||
Writes(log.FluentbitOutputsResult{}).
|
||||
Returns(http.StatusOK, RespOK, log.FluentbitOutputsResult{})).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
|
||||
c.Add(ws)
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user