init
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
package loger
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/sirupsen/logrus"
|
||||
"io"
|
||||
"os"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ANSI 转义码定义颜色
|
||||
const (
|
||||
reset = "\033[0m"
|
||||
red = "\033[31m"
|
||||
green = "\033[32m"
|
||||
yellow = "\033[33m"
|
||||
blue = "\033[34m"
|
||||
magenta = "\033[35m"
|
||||
cyan = "\033[36m"
|
||||
white = "\033[97m"
|
||||
gray = "\033[90m"
|
||||
brightYellow = "\033[93m"
|
||||
)
|
||||
|
||||
// 自定义日志格式化器
|
||||
type customFormatter struct{}
|
||||
|
||||
// Format 实现 logrus.Formatter 接口
|
||||
func (f *customFormatter) Format(entry *logrus.Entry) ([]byte, error) {
|
||||
// 根据日志级别选择颜色
|
||||
var levelColor string
|
||||
switch entry.Level {
|
||||
case logrus.DebugLevel:
|
||||
levelColor = cyan
|
||||
case logrus.InfoLevel:
|
||||
levelColor = green
|
||||
case logrus.WarnLevel:
|
||||
levelColor = yellow
|
||||
case logrus.ErrorLevel:
|
||||
levelColor = red
|
||||
case logrus.FatalLevel, logrus.PanicLevel:
|
||||
levelColor = magenta
|
||||
default:
|
||||
levelColor = white
|
||||
}
|
||||
|
||||
// 获取时间,格式为 yyyy/mm/dd hh:mm:ss.ms
|
||||
timestamp := fmt.Sprintf("%s%s%s", levelColor, entry.Time.Format("01-02 15:04:05"), reset)
|
||||
|
||||
// 获取文件名和行号
|
||||
_, file, line, ok := runtime.Caller(6) // 使用更高的层级
|
||||
if !ok {
|
||||
file = "unknown"
|
||||
line = 0
|
||||
}
|
||||
if entry.Caller != nil {
|
||||
// 获取调用者的文件名并只保留文件名部分
|
||||
file = file[strings.LastIndex(file, "/")+1:] // 仅保留文件名
|
||||
}
|
||||
|
||||
// 获取日志标题
|
||||
title, ok := entry.Data["title"].(string)
|
||||
if !ok {
|
||||
title = "unknown"
|
||||
}
|
||||
|
||||
// 格式化日志级别,并为其添加颜色
|
||||
level := fmt.Sprintf("%s[%s]%s", levelColor, strings.ToUpper(entry.Level.String()), reset)
|
||||
title = fmt.Sprintf("%s「%s」%s", levelColor, title, reset)
|
||||
|
||||
// 格式化输出内容
|
||||
logMessage := fmt.Sprintf("%s %s:%d: %s >> %s %s\n",
|
||||
timestamp,
|
||||
file,
|
||||
line,
|
||||
level,
|
||||
title,
|
||||
entry.Message,
|
||||
)
|
||||
|
||||
return []byte(logMessage), nil
|
||||
}
|
||||
|
||||
func getLog() *logrus.Logger {
|
||||
logLevel := os.Getenv("LOG_LEVEL")
|
||||
logSave := os.Getenv("LOG_SAVE")
|
||||
logSaveDir := os.Getenv("LOG_SAVE_PATH")
|
||||
log := logrus.New()
|
||||
switch logLevel {
|
||||
case "debug":
|
||||
log.SetLevel(logrus.DebugLevel)
|
||||
case "info":
|
||||
log.SetLevel(logrus.InfoLevel)
|
||||
case "warn":
|
||||
log.SetLevel(logrus.WarnLevel)
|
||||
case "error":
|
||||
log.SetLevel(logrus.ErrorLevel)
|
||||
case "fatal":
|
||||
log.SetLevel(logrus.FatalLevel)
|
||||
}
|
||||
// 自定义日志格式
|
||||
log.SetFormatter(&customFormatter{})
|
||||
// 启用调用信息的追踪,这样可以获取到文件名和行号
|
||||
log.SetReportCaller(true)
|
||||
|
||||
if logSave == "true" {
|
||||
logFileName := time.Now().Format("20060102") + ".log"
|
||||
logSavePath := logSaveDir + "/" + logFileName
|
||||
// 判断日志文件是否已存在
|
||||
_, err := os.Stat(logSaveDir)
|
||||
if os.IsNotExist(err) {
|
||||
// 路径不存在,创建目录
|
||||
if err := os.MkdirAll(logSaveDir, 0755); err != nil {
|
||||
log.Error("日志文件目录创建失败")
|
||||
return log
|
||||
}
|
||||
}
|
||||
logFile, _ := os.OpenFile(logSavePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
|
||||
multiWriter := io.MultiWriter(os.Stdout, logFile)
|
||||
log.SetOutput(multiWriter)
|
||||
}
|
||||
return log
|
||||
}
|
||||
|
||||
func toString(v interface{}) string {
|
||||
// 使用反射检查类型
|
||||
rv := reflect.ValueOf(v)
|
||||
|
||||
// 处理结构体和结构体指针
|
||||
if rv.Kind() == reflect.Struct || (rv.Kind() == reflect.Ptr && rv.Elem().Kind() == reflect.Struct) {
|
||||
jsonData, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return fmt.Sprintf("Error marshalling to JSON: %v", err)
|
||||
}
|
||||
return string(jsonData)
|
||||
}
|
||||
|
||||
// 对于其他类型,使用 fmt.Sprintf
|
||||
return fmt.Sprintf("%v", v)
|
||||
}
|
||||
|
||||
// isPrintable 检查字符串是否只包含可打印字符
|
||||
func isPrintable(s string) bool {
|
||||
for _, r := range s {
|
||||
if r < 32 || r > 126 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// joinToString 将多个参数转换为字符串,并拼接在一起。
|
||||
func joinToString(parts ...interface{}) string {
|
||||
var strParts []string
|
||||
for _, part := range parts {
|
||||
strParts = append(strParts, toString(part))
|
||||
}
|
||||
return strings.Join(strParts, "")
|
||||
}
|
||||
|
||||
func Debug(title string, content ...interface{}) {
|
||||
getLog().WithFields(logrus.Fields{
|
||||
"title": title,
|
||||
}).Debug(joinToString(content))
|
||||
}
|
||||
|
||||
func Info(title string, content ...interface{}) {
|
||||
getLog().WithFields(logrus.Fields{
|
||||
"title": title,
|
||||
}).Info(joinToString(content))
|
||||
}
|
||||
|
||||
func Warn(title string, content ...interface{}) {
|
||||
getLog().WithFields(logrus.Fields{
|
||||
"title": title,
|
||||
}).Warn(joinToString(content))
|
||||
}
|
||||
|
||||
func Error(title string, content ...interface{}) {
|
||||
getLog().WithFields(logrus.Fields{
|
||||
"title": title,
|
||||
}).Error(joinToString(content))
|
||||
}
|
||||
|
||||
func Fatal(title string, content ...interface{}) {
|
||||
getLog().WithFields(logrus.Fields{
|
||||
"title": title,
|
||||
}).Fatal(joinToString(content))
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package nacos
|
||||
|
||||
import (
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/constant"
|
||||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
cc *constant.ClientConfig
|
||||
sc []constant.ServerConfig
|
||||
)
|
||||
|
||||
func GetIP(domain string) string {
|
||||
// 确保域名不为空
|
||||
if domain == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
// 使用 net.LookupIP 查找域名的 IP 地址
|
||||
ips, err := net.LookupIP(domain)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
// 检查是否找到了 IP
|
||||
if len(ips) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
// 返回第一个 IPv4 地址(如果有)
|
||||
for _, ip := range ips {
|
||||
if ipv4 := ip.To4(); ipv4 != nil {
|
||||
return ipv4.String()
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有 IPv4,返回第一个 IP(可能是 IPv6)
|
||||
return ips[0].String()
|
||||
}
|
||||
|
||||
func InitNacosRegistryConfig() {
|
||||
if cc != nil && sc != nil {
|
||||
return
|
||||
}
|
||||
nacosHosts := strings.Split(os.Getenv("NACOS_HOSTS"), ",")
|
||||
nacosPort, _ := strconv.Atoi(os.Getenv("NACOS_PORT"))
|
||||
for _, host := range nacosHosts {
|
||||
serverConfig := constant.NewServerConfig(GetIP(host), uint64(nacosPort))
|
||||
sc = append(sc, *serverConfig)
|
||||
}
|
||||
|
||||
LogDir := os.Getenv("LOG_SAVE_PATH")
|
||||
cc = &constant.ClientConfig{
|
||||
NamespaceId: os.Getenv("NACOS_NAMESPACE"),
|
||||
TimeoutMs: 5000,
|
||||
NotLoadCacheAtStart: true,
|
||||
LogDir: LogDir,
|
||||
//CacheDir: "/tmp/nacos/cache",
|
||||
LogLevel: "debug",
|
||||
Username: os.Getenv("NACOS_USER"),
|
||||
Password: os.Getenv("NACOS_PASSWORD"),
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package nacos
|
||||
|
||||
import (
|
||||
"apiServer_service/utils/loger"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/clients"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/clients/config_client"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/vo"
|
||||
)
|
||||
|
||||
// NewNacosConfigClient 创建一个 Nacos 配置服务
|
||||
func NewNacosConfigClient() (*config_client.IConfigClient, error) {
|
||||
InitNacosRegistryConfig()
|
||||
cli, err := clients.NewConfigClient(
|
||||
vo.NacosClientParam{
|
||||
ClientConfig: cc,
|
||||
ServerConfigs: sc,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &cli, nil
|
||||
}
|
||||
|
||||
// AddConfig 新增配置
|
||||
func AddConfig(dataId, group, content string) error {
|
||||
client, err := NewNacosConfigClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = (*client).PublishConfig(vo.ConfigParam{
|
||||
DataId: dataId,
|
||||
Group: group,
|
||||
Content: content,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetConfig 获取配置
|
||||
func GetConfig(dataId, group string) string {
|
||||
client, err := NewNacosConfigClient()
|
||||
if err != nil {
|
||||
loger.Error("获取配置客户端失败", err)
|
||||
return ""
|
||||
}
|
||||
content, err := (*client).GetConfig(vo.ConfigParam{
|
||||
DataId: dataId,
|
||||
Group: group,
|
||||
})
|
||||
if err != nil {
|
||||
loger.Error("获取配置失败", err)
|
||||
return ""
|
||||
}
|
||||
return content
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package nacos
|
||||
|
||||
import (
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/clients"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/clients/naming_client"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/model"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/vo"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var (
|
||||
cli naming_client.INamingClient
|
||||
groupName string
|
||||
)
|
||||
|
||||
// NewNacosRegistry 创建一个nacos注册中心
|
||||
func NewNacosRegistry() (*naming_client.INamingClient, error) {
|
||||
InitNacosRegistryConfig()
|
||||
if cli != nil {
|
||||
return &cli, nil
|
||||
}
|
||||
groupName = os.Getenv("NACOS_GROUP_NAME")
|
||||
var err error
|
||||
cli, err = clients.NewNamingClient(
|
||||
vo.NacosClientParam{
|
||||
ClientConfig: cc,
|
||||
ServerConfigs: sc,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &cli, nil
|
||||
}
|
||||
|
||||
// RegisterService 注册当前服务到nacos中
|
||||
func RegisterService() error {
|
||||
client, err := NewNacosRegistry()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
serviceName := os.Getenv("NACOS_SERVICE_NAME")
|
||||
host := os.Getenv("NACOS_SERVICE_HOST")
|
||||
port, err := strconv.Atoi(os.Getenv("NACOS_SERVICE_PORT"))
|
||||
if err != nil {
|
||||
port = 8848
|
||||
}
|
||||
weight, err := strconv.Atoi(os.Getenv("NACOS_SERVICE_WEIGHT"))
|
||||
if err != nil {
|
||||
weight = 10
|
||||
}
|
||||
_, err = (*client).RegisterInstance(vo.RegisterInstanceParam{
|
||||
Ip: host,
|
||||
Port: uint64(port),
|
||||
ServiceName: serviceName,
|
||||
Weight: float64(weight),
|
||||
Enable: true,
|
||||
Healthy: true,
|
||||
Ephemeral: false,
|
||||
GroupName: groupName,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DiscoverServiceList 发现服务列表
|
||||
func DiscoverServiceList(serviceName string) ([]model.Instance, error) {
|
||||
client, err := NewNacosRegistry()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
instances, err := (*client).SelectInstances(vo.SelectInstancesParam{
|
||||
ServiceName: serviceName,
|
||||
HealthyOnly: false,
|
||||
GroupName: groupName,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return instances, nil
|
||||
}
|
||||
|
||||
// DiscoverService 发现一个服务
|
||||
func DiscoverService(serviceName string) (model.Instance, error) {
|
||||
client, err := NewNacosRegistry()
|
||||
if err != nil {
|
||||
return model.Instance{}, err
|
||||
}
|
||||
instances, err := (*client).SelectOneHealthyInstance(vo.SelectOneHealthInstanceParam{
|
||||
ServiceName: serviceName,
|
||||
GroupName: groupName,
|
||||
})
|
||||
if err != nil {
|
||||
return model.Instance{}, err
|
||||
}
|
||||
return *instances, nil
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package server_cli
|
||||
|
||||
import (
|
||||
"apiServer_service/proto"
|
||||
"apiServer_service/utils/loger"
|
||||
"apiServer_service/utils/nacos"
|
||||
"context"
|
||||
"errors"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// 获取 apiServer 的地址
|
||||
func getApiServer() string {
|
||||
service, err := nacos.DiscoverService("apiServer")
|
||||
if err != nil {
|
||||
loger.Error("getApiServer error", err)
|
||||
return ""
|
||||
}
|
||||
return service.Ip + ":" + strconv.Itoa(int(service.Port))
|
||||
}
|
||||
|
||||
// 获取 grpc 客户端
|
||||
func getGrpcClient() (*proto.ServerVisitServiceClient, error) {
|
||||
serverUri := getApiServer()
|
||||
if serverUri == "" {
|
||||
loger.Error("获取服务器地址失败")
|
||||
return nil, errors.New("getApiServer error")
|
||||
}
|
||||
conn, err := grpc.NewClient(getApiServer(), grpc.WithInsecure())
|
||||
if err != nil {
|
||||
loger.Error("getGrpcClient error", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c := proto.NewServerVisitServiceClient(conn)
|
||||
return &c, nil
|
||||
}
|
||||
|
||||
// getContext 创建带有 token 的上下文
|
||||
func getContext() context.Context { // 创建带有 token 的上下文
|
||||
token := os.Getenv("GRPC_TOKEN")
|
||||
md := metadata.Pairs("authorization", "Bearer "+token) // 设置 authorization 头
|
||||
ctx := metadata.NewOutgoingContext(context.Background(), md)
|
||||
return ctx
|
||||
}
|
||||
|
||||
// ReportVisit 演示方法 向服务器上报访问记录
|
||||
func ReportVisit(token, note, VisitIp, OS string, point, UserId int) error {
|
||||
client, err := getGrpcClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
recode, err := (*client).AddServerVisitRecode(getContext(), &proto.ServerVisitRequest{
|
||||
Note: note,
|
||||
VisitIp: VisitIp,
|
||||
UserAgent: OS,
|
||||
ServerOs: OS,
|
||||
Point: int64(point),
|
||||
Token: token,
|
||||
})
|
||||
if err != nil {
|
||||
loger.Error("ReportVisit error", err)
|
||||
return err
|
||||
}
|
||||
loger.Debug("ReportVisit", recode)
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user