func doLogs(context.Context) *rkentry.LogsResponse {
	res := &rkentry.LogsResponse{
		Entries: make(map[string][]*rkentry.LogsResponse_Entry),
	}
	doLogsHelper(rkentry.GlobalAppCtx.ListEventLoggerEntriesRaw(), res)
	doLogsHelper(rkentry.GlobalAppCtx.ListZapLoggerEntriesRaw(), res)
	return res
}
Helper function of /logs
package rkgrpc
import (
	"context"
	"encoding/json"
	"fmt"
	gwruntime "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
	"github.com/rookie-ninja/rk-common/common"
	"github.com/rookie-ninja/rk-entry/entry"
	api "github.com/rookie-ninja/rk-grpc/boot/api/third_party/gen/v1"
	"github.com/rookie-ninja/rk-grpc/interceptor"
	"github.com/rookie-ninja/rk-grpc/interceptor/context"
	"github.com/rookie-ninja/rk-grpc/interceptor/metrics/prom"
	"github.com/rookie-ninja/rk-query"
	"go.uber.org/zap"
	"google.golang.org/genproto/googleapis/rpc/code"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/protobuf/types/known/structpb"
	"net/http"
	"path"
	"runtime"
)
const (
	CommonServiceEntryType = "GrpcCommonServiceEntry"
	CommonServiceEntryNameDefault = "GrpcCommonServiceDefault"
	CommonServiceEntryDescription = "Internal RK entry which implements commonly used API with grpc framework."
	CommonServiceGwMappingFilePath = "api/v1/gw_mapping.yaml"
)
type BootConfigCommonService struct {
	Enabled bool `yaml:"enabled"`
}
type CommonServiceEntry struct {
	EntryName         string                    `json:"entryName" yaml:"entryName"`
	EntryType         string                    `json:"entryType" yaml:"entryType"`
	EntryDescription  string                    `json:"entryDescription" yaml:"entryDescription"`
	EventLoggerEntry  *rkentry.EventLoggerEntry `json:"eventLoggerEntry" yaml:"eventLoggerEntry"`
	ZapLoggerEntry    *rkentry.ZapLoggerEntry   `json:"zapLoggerEntry" yaml:"zapLoggerEntry"`
	GrpcRegF          GrpcRegFunc               `json:"regFuncGrpc" yaml:"regFuncGrpc"`
	GwRegF            GwRegFunc                 `json:"regFuncGw" yaml:"regFuncGw"`
	GwMappingFilePath string                    `json:"gwMappingFilePath" yaml:"gwMappingFilePath"`
	GwMapping         map[string]string         `json:"gwMapping" yaml:"gwMapping"`
}
type CommonServiceEntryOption func(*CommonServiceEntry)
func WithNameCommonService(name string) CommonServiceEntryOption {
	return func(entry *CommonServiceEntry) {
		entry.EntryName = name
	}
}
func WithEventLoggerEntryCommonService(eventLoggerEntry *rkentry.EventLoggerEntry) CommonServiceEntryOption {
	return func(entry *CommonServiceEntry) {
		entry.EventLoggerEntry = eventLoggerEntry
	}
}
func WithZapLoggerEntryCommonService(zapLoggerEntry *rkentry.ZapLoggerEntry) CommonServiceEntryOption {
	return func(entry *CommonServiceEntry) {
		entry.ZapLoggerEntry = zapLoggerEntry
	}
}
func NewCommonServiceEntry(opts ...CommonServiceEntryOption) *CommonServiceEntry {
	entry := &CommonServiceEntry{
		EntryName:         CommonServiceEntryNameDefault,
		EntryType:         CommonServiceEntryType,
		EntryDescription:  CommonServiceEntryDescription,
		ZapLoggerEntry:    rkentry.GlobalAppCtx.GetZapLoggerEntryDefault(),
		EventLoggerEntry:  rkentry.GlobalAppCtx.GetEventLoggerEntryDefault(),
		GrpcRegF:          registerRkCommonService,
		GwRegF:            api.RegisterRkCommonServiceHandlerFromEndpoint,
		GwMappingFilePath: CommonServiceGwMappingFilePath,
		GwMapping:         make(map[string]string),
	}
	for i := range opts {
		opts[i](entry)
	}
	return entry
}
func (entry *CommonServiceEntry) Bootstrap(ctx context.Context) {
	event := entry.EventLoggerEntry.GetEventHelper().Start(
		"bootstrap",
		rkquery.WithEntryName(entry.EntryName),
		rkquery.WithEntryType(entry.EntryType))
	logger := entry.ZapLoggerEntry.GetLogger()
	if raw := ctx.Value(bootstrapEventIdKey); raw != nil {
		event.SetEventId(raw.(string))
		logger = logger.With(zap.String("eventId", event.GetEventId()))
	}
	entry.logBasicInfo(event)
	defer entry.EventLoggerEntry.GetEventHelper().Finish(event)
	logger.Info("Bootstrapping CommonServiceEntry.", event.ListPayloads()...)
}
func (entry *CommonServiceEntry) Interrupt(ctx context.Context) {
	event := entry.EventLoggerEntry.GetEventHelper().Start(
		"interrupt",
		rkquery.WithEntryName(entry.EntryName),
		rkquery.WithEntryType(entry.EntryType))
	logger := entry.ZapLoggerEntry.GetLogger()
	if raw := ctx.Value(bootstrapEventIdKey); raw != nil {
		event.SetEventId(raw.(string))
		logger = logger.With(zap.String("eventId", event.GetEventId()))
	}
	entry.logBasicInfo(event)
	defer entry.EventLoggerEntry.GetEventHelper().Finish(event)
	logger.Info("Interrupting CommonServiceEntry.", event.ListPayloads()...)
}
func (entry *CommonServiceEntry) GetName() string {
	return entry.EntryName
}
func (entry *CommonServiceEntry) GetType() string {
	return entry.EntryType
}
func (entry *CommonServiceEntry) String() string {
	bytes, _ := json.Marshal(entry)
	return string(bytes)
}
func (entry *CommonServiceEntry) MarshalJSON() ([]byte, error) {
	m := map[string]interface{}{
		"entryName":        entry.EntryName,
		"entryType":        entry.EntryType,
		"entryDescription": entry.EntryDescription,
		"zapLoggerEntry":   entry.ZapLoggerEntry.GetName(),
		"eventLoggerEntry": entry.EventLoggerEntry.GetName(),
	}
	return json.Marshal(&m)
}
func (entry *CommonServiceEntry) UnmarshalJSON([]byte) error {
	return nil
}
func (entry *CommonServiceEntry) GetDescription() string {
	return entry.EntryDescription
}
func (entry *CommonServiceEntry) logBasicInfo(event rkquery.Event) {
	event.AddPayloads(
		zap.String("entryName", entry.EntryName),
		zap.String("entryType", entry.EntryType),
	)
}
func doHealthy(context.Context) *rkentry.HealthyResponse {
	return &rkentry.HealthyResponse{
		Healthy: true,
	}
}
func (entry *CommonServiceEntry) Healthy(ctx context.Context, request *api.HealthyRequest) (*structpb.Struct, error) {
	event := rkgrpcctx.GetEvent(ctx)
	event.AddPair("healthy", "true")
	return structpb.NewStruct(rkcommon.ConvertStructToMap(doHealthy(ctx)))
}
func doGc(context.Context) *rkentry.GcResponse {
	before := rkentry.NewMemInfo()
	runtime.GC()
	after := rkentry.NewMemInfo()
	return &rkentry.GcResponse{
		MemStatBeforeGc: before,
		MemStatAfterGc:  after,
	}
}
func (entry *CommonServiceEntry) Gc(ctx context.Context, request *api.GcRequest) (*structpb.Struct, error) {
	return structpb.NewStruct(rkcommon.ConvertStructToMap(doGc(ctx)))
}
func doInfo(context.Context) *rkentry.ProcessInfo {
	return rkentry.NewProcessInfo()
}
func (entry *CommonServiceEntry) Info(ctx context.Context, request *api.InfoRequest) (*structpb.Struct, error) {
	return structpb.NewStruct(rkcommon.ConvertStructToMap(doInfo(ctx)))
}
func doConfigs(context.Context) *rkentry.ConfigsResponse {
	res := &rkentry.ConfigsResponse{
		Entries: make([]*rkentry.ConfigsResponse_ConfigEntry, 0),
	}
	for _, v := range rkentry.GlobalAppCtx.ListConfigEntries() {
		configEntry := &rkentry.ConfigsResponse_ConfigEntry{
			EntryName:        v.GetName(),
			EntryType:        v.GetType(),
			EntryDescription: v.GetDescription(),
			EntryMeta:        v.GetViperAsMap(),
			Path:             v.Path,
		}
		res.Entries = append(res.Entries, configEntry)
	}
	return res
}
func (entry *CommonServiceEntry) Configs(ctx context.Context, request *api.ConfigsRequest) (*structpb.Struct, error) {
	return structpb.NewStruct(rkcommon.ConvertStructToMap(doConfigs(ctx)))
}
func getSwUrl(ctx context.Context, entry *GrpcEntry) string {
	if entry.IsSwEnabled() {
		scheme := "http"
		if entry.IsTlsEnabled() {
			scheme = "https"
		}
		remoteIp, _, _ := rkgrpcinter.GetRemoteAddressSet(ctx)
		return fmt.Sprintf("%s://%s:%d%s",
			scheme,
			remoteIp,
			entry.SwEntry.Port,
			entry.SwEntry.Path)
	}
	return ""
}
func getGwMapping(ctx context.Context, entry *GrpcEntry, grpcMethod string) *rkentry.ApisResponse_Rest {
	res := &rkentry.ApisResponse_Rest{}
	var value *gwRule
	var ok bool
	if value, ok = entry.GwHttpToGrpcMapping[grpcMethod]; !ok {
		return res
	}
	res.Port = entry.Port
	res.Method = value.Method
	res.Pattern = value.Pattern
	res.SwUrl = getSwUrl(ctx, entry)
	return res
}
func doApis(ctx context.Context) *rkentry.ApisResponse {
	res := &rkentry.ApisResponse{
		Entries: make([]*rkentry.ApisResponse_Entry, 0),
	}
	grpcEntry := getEntry(ctx)
	if grpcEntry == nil {
		return res
	}
	for serviceName, serviceInfo := range grpcEntry.Server.GetServiceInfo() {
		for i := range serviceInfo.Methods {
			method := serviceInfo.Methods[i]
			apiType := "Unary"
			if method.IsServerStream {
				apiType = "Stream"
			}
			entry := &rkentry.ApisResponse_Entry{
				EntryName: grpcEntry.GetName(),
				Grpc: &rkentry.ApisResponse_Grpc{
					Service: serviceName,
					Method:  method.Name,
					Port:    grpcEntry.Port,
					Type:    apiType,
					Gw:      getGwMapping(ctx, grpcEntry, serviceName+"."+method.Name),
				},
			}
			res.Entries = append(res.Entries, entry)
		}
	}
	return res
}
func (entry *CommonServiceEntry) Apis(ctx context.Context, request *api.ApisRequest) (*structpb.Struct, error) {
	return structpb.NewStruct(rkcommon.ConvertStructToMap(doApis(ctx)))
}
func doSys(context.Context) *rkentry.SysResponse {
	return &rkentry.SysResponse{
		CpuInfo:   rkentry.NewCpuInfo(),
		MemInfo:   rkentry.NewMemInfo(),
		NetInfo:   rkentry.NewNetInfo(),
		OsInfo:    rkentry.NewOsInfo(),
		GoEnvInfo: rkentry.NewGoEnvInfo(),
	}
}
func (entry *CommonServiceEntry) Sys(ctx context.Context, request *api.SysRequest) (*structpb.Struct, error) {
	return structpb.NewStruct(rkcommon.ConvertStructToMap(doSys(ctx)))
}
func doReq(ctx context.Context) *rkentry.ReqResponse {
	vector := rkgrpcmetrics.GetMetricsSet(ctx).GetSummary(rkgrpcmetrics.ElapsedNano)
	reqMetrics := rkentry.NewPromMetricsInfo(vector)
	type innerGrpcInfo struct {
		grpcService string
		grpcMethod  string
	}
	apis := make([]*innerGrpcInfo, 0)
	grpcEntry := GetGrpcEntry(rkgrpcctx.GetEntryName(ctx))
	if grpcEntry != nil {
		infos := grpcEntry.Server.GetServiceInfo()
		for serviceName, serviceInfo := range infos {
			for j := range serviceInfo.Methods {
				apis = append(apis, &innerGrpcInfo{
					grpcService: serviceName,
					grpcMethod:  serviceInfo.Methods[j].Name,
				})
			}
		}
	}
	for i := range apis {
		api := apis[i]
		contains := false
		for j := range reqMetrics {
			if reqMetrics[j].GrpcMethod == api.grpcMethod && reqMetrics[j].GrpcService == api.grpcService {
				contains = true
			}
		}
		if !contains {
			reqMetrics = append(reqMetrics, &rkentry.ReqMetricsRK{
				GrpcService: apis[i].grpcService,
				GrpcMethod:  apis[i].grpcMethod,
				ResCode:     make([]*rkentry.ResCodeRK, 0),
			})
		}
	}
	return &rkentry.ReqResponse{
		Metrics: reqMetrics,
	}
}
func (entry *CommonServiceEntry) Req(ctx context.Context, request *api.ReqRequest) (*structpb.Struct, error) {
	return structpb.NewStruct(rkcommon.ConvertStructToMap(doReq(ctx)))
}
func doEntriesHelper(m map[string]rkentry.Entry, res *rkentry.EntriesResponse) {
	for i := range m {
		entry := m[i]
		element := &rkentry.EntriesResponse_Entry{
			EntryName:        entry.GetName(),
			EntryType:        entry.GetType(),
			EntryDescription: entry.GetDescription(),
			EntryMeta:        entry,
		}
		if entries, ok := res.Entries[entry.GetType()]; ok {
			entries = append(entries, element)
		} else {
			res.Entries[entry.GetType()] = []*rkentry.EntriesResponse_Entry{element}
		}
	}
}
func doEntries(ctx context.Context) *rkentry.EntriesResponse {
	res := &rkentry.EntriesResponse{
		Entries: make(map[string][]*rkentry.EntriesResponse_Entry),
	}
	if ctx == nil {
		return res
	}
	doEntriesHelper(rkentry.GlobalAppCtx.ListEntries(), res)
	doEntriesHelper(rkentry.GlobalAppCtx.ListEventLoggerEntriesRaw(), res)
	doEntriesHelper(rkentry.GlobalAppCtx.ListZapLoggerEntriesRaw(), res)
	doEntriesHelper(rkentry.GlobalAppCtx.ListConfigEntriesRaw(), res)
	doEntriesHelper(rkentry.GlobalAppCtx.ListCertEntriesRaw(), res)
	doEntriesHelper(rkentry.GlobalAppCtx.ListCredEntriesRaw(), res)
	appInfoEntry := rkentry.GlobalAppCtx.GetAppInfoEntry()
	res.Entries[appInfoEntry.GetType()] = []*rkentry.EntriesResponse_Entry{
		{
			EntryName:        appInfoEntry.GetName(),
			EntryType:        appInfoEntry.GetType(),
			EntryDescription: appInfoEntry.GetDescription(),
			EntryMeta:        appInfoEntry,
		},
	}
	return res
}
func (entry *CommonServiceEntry) Entries(ctx context.Context, request *api.EntriesRequest) (*structpb.Struct, error) {
	return structpb.NewStruct(rkcommon.ConvertStructToMap(doEntries(ctx)))
}
func doCerts(context.Context) *rkentry.CertsResponse {
	res := &rkentry.CertsResponse{
		Entries: make([]*rkentry.CertsResponse_Entry, 0),
	}
	entries := rkentry.GlobalAppCtx.ListCertEntries()
	for i := range entries {
		entry := entries[i]
		certEntry := &rkentry.CertsResponse_Entry{
			EntryName:        entry.GetName(),
			EntryType:        entry.GetType(),
			EntryDescription: entry.GetDescription(),
		}
		if entry.Retriever != nil {
			certEntry.Endpoint = entry.Retriever.GetEndpoint()
			certEntry.Locale = entry.Retriever.GetLocale()
			certEntry.Provider = entry.Retriever.GetProvider()
			certEntry.ServerCertPath = entry.ServerCertPath
			certEntry.ServerKeyPath = entry.ServerKeyPath
			certEntry.ClientCertPath = entry.ClientCertPath
			certEntry.ClientKeyPath = entry.ClientKeyPath
		}
		if entry.Store != nil {
			certEntry.ServerCert = entry.Store.SeverCertString()
			certEntry.ClientCert = entry.Store.ClientCertString()
		}
		res.Entries = append(res.Entries, certEntry)
	}
	return res
}
func (entry *CommonServiceEntry) Certs(ctx context.Context, request *api.CertsRequest) (*structpb.Struct, error) {
	res, err := structpb.NewStruct(rkcommon.ConvertStructToMap(doCerts(ctx)))
	return res, err
}
func doLogsHelper(m map[string]rkentry.Entry, res *rkentry.LogsResponse) {
	entries := make([]*rkentry.LogsResponse_Entry, 0)
	for i := range m {
		entry := m[i]
		element := &rkentry.LogsResponse_Entry{
			EntryName:        entry.GetName(),
			EntryType:        entry.GetType(),
			EntryDescription: entry.GetDescription(),
			EntryMeta:        entry,
		}
		if val, ok := entry.(*rkentry.ZapLoggerEntry); ok {
			if val.LoggerConfig != nil {
				element.OutputPaths = val.LoggerConfig.OutputPaths
				element.ErrorOutputPaths = val.LoggerConfig.ErrorOutputPaths
			}
		}
		if val, ok := entry.(*rkentry.EventLoggerEntry); ok {
			if val.LoggerConfig != nil {
				element.OutputPaths = val.LoggerConfig.OutputPaths
				element.ErrorOutputPaths = val.LoggerConfig.ErrorOutputPaths
			}
		}
		entries = append(entries, element)
	}
	var entryType string
	if len(entries) > 0 {
		entryType = entries[0].EntryType
	}
	res.Entries[entryType] = entries
}