Skip to content

Commit

Permalink
Feature: Add podyaml and nodeyaml panel in dashboard and correspondin…
Browse files Browse the repository at this point in the history
…g API
  • Loading branch information
wuchang0201 authored Apr 10, 2024
1 parent fee0d7d commit 86b0988
Show file tree
Hide file tree
Showing 11 changed files with 340 additions and 10 deletions.
8 changes: 1 addition & 7 deletions build/docker/Dockerfile.grafana
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,16 @@
FROM node as node
# 将代码拷贝到镜像中的工作目录
COPY ./grafana_plugin/yaml_panel /app/yaml_panel
COPY ./grafana_plugin/custom_log_panel /app/custom_log_panel
# 在镜像中创建工作目录
WORKDIR /app/yaml_panel
# 安装依赖并编译
RUN npm install \
&& npm run build
# 在镜像中创建工作目录
WORKDIR /app/custom_log_panel

# 安装依赖并编译
RUN npm install \
&& npm run build
# Use the official Grafana image as the base image.
FROM grafana/grafana:latest

COPY --from=node /app/yaml_panel/dist /var/lib/grafana/plugins/antgroup-yaml-panel
COPY --from=node /app/custom_log_panel/dist /var/lib/grafana/plugins/antgroup-customlog-panel

# Define the list of plugins to install, separated by spaces.
ARG PLUGINS=""
Expand Down
90 changes: 90 additions & 0 deletions internal/grafanadi/handler/rawdata_handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package handler

import (
"net/http"
"time"

"github.com/alipay/container-observability-service/internal/grafanadi/service"
"github.com/alipay/container-observability-service/pkg/dal/storage-client/data_access"
"github.com/alipay/container-observability-service/pkg/dal/storage-client/model"
"github.com/alipay/container-observability-service/pkg/metrics"
"github.com/alipay/container-observability-service/pkg/utils"
"k8s.io/klog/v2"
)

type RawHandler struct {
request *http.Request
writer http.ResponseWriter
requestParams *RawdataParams
storage data_access.StorageInterface
}

type RawdataParams struct {
plfId string
}

func (handler *RawHandler) queryPodLifePhaseByID(plfId string) (int, interface{}, error) {
lifePhase := make([]*model.LifePhase, 0)
if len(plfId) == 0 {
return http.StatusOK, nil, nil

}

begin := time.Now()
defer func() {
cost := utils.TimeSinceInMilliSeconds(begin)
metrics.QueryMethodDurationMilliSeconds.WithLabelValues("PodLifePhaseByID").Observe(cost)
}()

err := handler.storage.QueryPodLifePhaseByID(&lifePhase, handler.requestParams.plfId)
if err != nil {
klog.Errorf("query lifephase failed: %s", err.Error())
return http.StatusOK, nil, nil

}
if len(lifePhase) > 0 {
return http.StatusOK, service.ConvertPodphase2Frame(lifePhase), nil
}

return http.StatusOK, nil, nil
}

func (handler *RawHandler) RequestParams() interface{} {
return handler.requestParams
}

func (handler *RawHandler) ParseRequest() error {
params := RawdataParams{}
if handler.request.Method == http.MethodGet {

params.plfId = handler.request.URL.Query().Get("plfid")
}

handler.requestParams = &params
return nil
}

func (handler *RawHandler) ValidRequest() error {
return nil
}

func (handler *RawHandler) Process() (int, interface{}, error) {
defer utils.IgnorePanic("RawdataleHandler.Process ")

var result interface{}
var err error
var httpStatus int
if handler.requestParams != nil {
httpStatus, result, err = handler.queryPodLifePhaseByID(handler.requestParams.plfId)

}
return httpStatus, result, err
}

func RawdataFactory(w http.ResponseWriter, r *http.Request, storage data_access.StorageInterface) Handler {
return &RawHandler{
request: r,
writer: w,
storage: storage,
}
}
104 changes: 104 additions & 0 deletions internal/grafanadi/handler/yaml_handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package handler

import (
"net/http"
"time"

"github.com/alipay/container-observability-service/internal/grafanadi/service"
"github.com/alipay/container-observability-service/pkg/dal/storage-client/data_access"
"github.com/alipay/container-observability-service/pkg/dal/storage-client/model"
"github.com/alipay/container-observability-service/pkg/metrics"
"github.com/alipay/container-observability-service/pkg/utils"

"k8s.io/klog/v2"
)

type YamlHandler struct {
request *http.Request
writer http.ResponseWriter
requestParams *YamlParams
storage data_access.StorageInterface
}

type YamlParams struct {
Resource string
Uid string
Name string
}

func (handler *YamlHandler) GetYamls(params *YamlParams) (int, interface{}, error) {
podYamls := make([]*model.PodYaml, 0)
nodeYamls := make([]*model.NodeYaml, 0)
var err error
if params == nil {
return http.StatusOK, nil, nil
}

begin := time.Now()
defer func() {
cost := utils.TimeSinceInMilliSeconds(begin)
metrics.QueryMethodDurationMilliSeconds.WithLabelValues("GetYamls").Observe(cost)
}()
if handler.requestParams.Resource == "pod" && handler.requestParams.Uid != "" {
err = handler.storage.QueryPodYamlsWithPodUID(&podYamls, handler.requestParams.Uid)
if err == nil {
return http.StatusOK, service.ConvertPodYaml2Frame(podYamls), nil
}
} else if handler.requestParams.Resource == "node" && handler.requestParams.Name != "" {
err = handler.storage.QueryNodeYamlsWithNodeName(&nodeYamls, handler.requestParams.Name)
if err != nil {
klog.Errorf("get nodeyaml failed: %s", err.Error())
} else {

// return http.StatusOK, service.TransformYaml2Html(nodeYamls[0]), nil
return http.StatusOK, service.ConvertNodeYaml2Frame(nodeYamls), nil

}
}

return http.StatusOK, nil, nil
}

func (handler *YamlHandler) RequestParams() interface{} {
return handler.requestParams
}

func (handler *YamlHandler) ParseRequest() error {
params := YamlParams{}
if handler.request.Method == http.MethodGet {
resource := handler.request.URL.Query().Get("resource")
uid := handler.request.URL.Query().Get("uid")
name := handler.request.URL.Query().Get("name")
params.Resource = resource
params.Uid = uid
params.Name = name
}

handler.requestParams = &params
return nil
}

func (handler *YamlHandler) ValidRequest() error {
return nil
}

func (handler *YamlHandler) Process() (int, interface{}, error) {
defer utils.IgnorePanic("ContainerlifecycleHandler.Process ")

var result interface{}
var err error
var httpStatus int
if handler.requestParams != nil {
httpStatus, result, err = handler.GetYamls(handler.requestParams)

}
return httpStatus, result, err
}

func YamlFactory(w http.ResponseWriter, r *http.Request, storage data_access.StorageInterface) Handler {
return &YamlHandler{
request: r,
writer: w,
storage: storage,
}
}
40 changes: 40 additions & 0 deletions internal/grafanadi/model/model.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
package model

import (
"time"

v1 "k8s.io/api/core/v1"
)

// Take this as Example: https://sriramajeyam.com/grafana-infinity-datasource/wiki/json
type BizInfoTable struct {
ClusterName string `json:"ClusterName,omitempty"`
Expand All @@ -25,6 +31,40 @@ type PodInfoTable struct {
NodeIP string `json:"NodeIP,omitempty"`
NodeYaml string `json:"NodeYaml,omitempty"`
}
type PodYamlTable struct {
AuditID string `json:"AuditID,omitempty"`
ClusterName string `json:"ClusterName,omitempty"`
HostIP string `json:"HostIP,omitempty"`
IsBeginDelete string `json:"IsBeginDelete,omitempty"`
IsDeleted string `json:"IsDeleted,omitempty"`
Pod *v1.Pod `json:"pod,omitempty"`
PodIP string `json:"PodIP,omitempty"`
PodName string `json:"PodName,omitempty"`
PodUid string `json:"PodUid,omitempty"`
StageTimestamp time.Time `json:"stageTimestamp,omitempty"`
}
type PhaseTable struct {
EndTime time.Time `json:"endTime,omitempty"`
ClusterName string `json:"clusterName,omitempty"`
DataSourceId string `json:"dataSourceId,omitempty"`
HasErr bool `json:"hasErr"`
Namespace string `json:"namespace,omitempty" `
OperationName string `json:"operationName,omitempty" `
PodUID string `json:"podUid,omitempty"`
PodName string `json:"podName,omitempty" `
StartTime time.Time `json:"startTime,omitempty" `
ExtraInfo interface{} `json:"extraInfo,omitempty"`
TraceStage string `json:"traceStage"`
}
type NodeYamlTable struct {
AuditID string `json:"AuditID,omitempty"`
NodeName string `json:"NodeName,omitempty"`
NodeIp string `json:"NodeIp,omitempty"`
UID string `json:"UID,omitempty"`
ClusterName string `json:"ClusterName,omitempty"`
Node *v1.Node `json:"Node,omitempty"`
StageTimeStamp time.Time `json:"StageTimeStamp,omitempty"`
}
type PodListTable struct {
DeliveryTime string `json:"交付时间,omitempty"`
Namespace string `json:"namespace,omitempty"`
Expand Down
2 changes: 2 additions & 0 deletions internal/grafanadi/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,11 @@ func (s *Server) StartServer(stopCh chan struct{}) {
r.Path("/podtypedistribute").HandlerFunc(handlerWrapper(handler.DebuggingPodsFactory, s.Storage))
r.Path("/podlist").HandlerFunc(handlerWrapper(handler.PodlistFactory, s.Storage))
r.Path("/podnumber").HandlerFunc(handlerWrapper(handler.PodlistFactory, s.Storage))
r.Path("/showyamls").HandlerFunc(handlerWrapper(handler.YamlFactory, s.Storage))
r.Path("/podyamlgraphnodes").HandlerFunc(handlerWrapper(handler.NodeGraphParamsFactory, s.Storage))
r.Path("/podyamlgraphedges").HandlerFunc(handlerWrapper(handler.NodeGraphParamsFactory, s.Storage))
r.Path("/elasticaggregations").HandlerFunc(corsWrapper(interutils.ServeSLOGrafanaDI, s.Storage))
r.Path("/rawdata").HandlerFunc(handlerWrapper(handler.RawdataFactory, s.Storage))

err := http.ListenAndServe(s.Config.ListenAddr, r)
if err != nil {
Expand Down
57 changes: 57 additions & 0 deletions internal/grafanadi/service/bizinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,60 @@ func ConvertBizInfo2Frame(podInfos []*storagemodel.PodInfo) []model.BizInfoTable

return []model.BizInfoTable{bit}
}

func ConvertPodYaml2Frame(podYamls []*storagemodel.PodYaml) []model.PodYamlTable {
if len(podYamls) < 1 {
return nil
}
bit := model.PodYamlTable{
AuditID: podYamls[0].AuditID,
ClusterName: podYamls[0].ClusterName,
HostIP: podYamls[0].HostIP,
IsBeginDelete: podYamls[0].IsBeginDelete,
IsDeleted: podYamls[0].IsDeleted,
Pod: podYamls[0].Pod,
PodIP: podYamls[0].PodIP,
PodName: podYamls[0].PodName,
PodUid: podYamls[0].PodUid,
StageTimestamp: podYamls[0].StageTimestamp,
}

return []model.PodYamlTable{bit}
}

func ConvertNodeYaml2Frame(nodeYamls []*storagemodel.NodeYaml) []model.NodeYamlTable {
if len(nodeYamls) < 1 {
return nil
}
bit := model.NodeYamlTable{
AuditID: nodeYamls[0].AuditID,
ClusterName: nodeYamls[0].ClusterName,
NodeName: nodeYamls[0].NodeName,
NodeIp: nodeYamls[0].NodeIp,
UID: nodeYamls[0].UID,
Node: nodeYamls[0].Node,
StageTimeStamp: nodeYamls[0].StageTimeStamp,
}

return []model.NodeYamlTable{bit}
}
func ConvertPodphase2Frame(lifePhase []*storagemodel.LifePhase) []model.PhaseTable {
if len(lifePhase) < 1 {
return nil
}
bit := model.PhaseTable{
EndTime: lifePhase[0].EndTime,
ClusterName: lifePhase[0].ClusterName,
DataSourceId: lifePhase[0].DataSourceId,
HasErr: lifePhase[0].HasErr,
Namespace: lifePhase[0].Namespace,
OperationName: lifePhase[0].OperationName,
PodUID: lifePhase[0].PodUID,
PodName: lifePhase[0].PodName,
StartTime: lifePhase[0].StartTime,
ExtraInfo: lifePhase[0].ExtraInfo,
TraceStage: lifePhase[0].TraceStage,
}

return []model.PhaseTable{bit}
}
6 changes: 4 additions & 2 deletions internal/grafanadi/service/podphase.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/alipay/container-observability-service/internal/grafanadi/model"
storagemodel "github.com/alipay/container-observability-service/pkg/dal/storage-client/model"
"github.com/alipay/container-observability-service/pkg/utils"
)

const (
Expand Down Expand Up @@ -132,9 +133,10 @@ func ConvertPodPhase2Frame(podPhases []*storagemodel.LifePhase) model.DataFrame
typeAry = append(typeAry, t)

uaAry = append(uaAry, convertNil(userAgent))
plfUrl := fmt.Sprintf("http://lunettes.lunettes.svc:8080/api/v1/rawdata?plfid=%s", phase.PlfID)
hashCodeStr := fmt.Sprintf("%d", utils.StringHashcode(phase.OperationName))
plfId := phase.ClusterName + "_" + phase.Namespace + "_" + phase.PodUID + "_" + phase.DataSourceId + "_" + hashCodeStr
plfUrl := fmt.Sprintf("http://localhost:9097/d/rawdatalinks/rawdata?orgId=1&var-plfid=%s", plfId)
plfAry = append(plfAry, convertNil(plfUrl))

reasonAry = append(reasonAry, convertNil(phaseReason))
messageAry = append(messageAry, convertNil(phaseMessage))
traceStageAry = append(traceStageAry, convertNil(currentTraceStage))
Expand Down
Loading

0 comments on commit 86b0988

Please sign in to comment.