工程初始化
parent
dccad1b385
commit
006d5443c6
|
@ -0,0 +1,12 @@
|
|||
package question
|
||||
|
||||
import (
|
||||
"context"
|
||||
"interview-one-stop-server/model"
|
||||
"interview-one-stop-server/util/ierrors"
|
||||
)
|
||||
|
||||
func GetQuestionList(ctx context.Context) ([]model.Question, ierrors.OneStopErr) {
|
||||
|
||||
return nil, ierrors.OneStopSuccess
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
service:
|
||||
env: dev
|
||||
domain: "http://aip-dev.nioint.com"
|
||||
port: 7777
|
||||
db:
|
||||
dsn: "root:EKghQrcnBEcPZpTT@tcp(112.54.161.118:3306)/question_one_stop?charset=utf8mb4&parseTime=True&loc=Local"
|
|
@ -0,0 +1,6 @@
|
|||
service:
|
||||
env: prod
|
||||
domain: "http://aip.nioint.com"
|
||||
port: 7777
|
||||
db:
|
||||
dsn: "root:EKghQrcnBEcPZpTT@tcp(112.54.161.118:3306)/question_one_stop?charset=utf8mb4&parseTime=True&loc=Local""
|
|
@ -0,0 +1,88 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"interview-one-stop-server/constant"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var GlobalConf Config
|
||||
|
||||
func InitConfig() error {
|
||||
v := viper.New()
|
||||
v.AddConfigPath("./conf") // 设置读取的文件路径
|
||||
v.AddConfigPath("../../conf") // 设置读取的文件路径
|
||||
v.SetConfigType("yaml") // 设置文件的类型
|
||||
|
||||
env := os.Getenv("ENV_NAME")
|
||||
switch env {
|
||||
case constant.EnvNameTencentProd:
|
||||
v.SetConfigName("conf_prod")
|
||||
default:
|
||||
v.SetConfigName("conf_dev")
|
||||
}
|
||||
|
||||
// 尝试进行配置读取
|
||||
if err := v.ReadInConfig(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err := v.Unmarshal(&GlobalConf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go modifyDefaultSwaggerHost()
|
||||
return nil
|
||||
}
|
||||
|
||||
func modifyDefaultSwaggerHost() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Printf("linux cmd run failed,err is %v\n", r)
|
||||
}
|
||||
}()
|
||||
|
||||
path := "/app/swagger/dist/"
|
||||
host := GlobalConf.Service.Domain[7:]
|
||||
ph := ""
|
||||
|
||||
env := os.Getenv("ENV_NAME")
|
||||
if env == "" {
|
||||
host = "localhost:4004"
|
||||
pwd, _ := os.Getwd()
|
||||
path = pwd + "/swagger/dist/"
|
||||
ph = "''"
|
||||
}
|
||||
|
||||
cmd := exec.Command("/bin/bash", "-c", fmt.Sprintf(`cp %s %s && sed -i %s ' s/UNKNOWNHOSTHHH/%s/g' %s `,
|
||||
path+"swagger-initializer.js.bak", path+"swagger-initializer.js", ph, host, path+"swagger-initializer.js"))
|
||||
|
||||
output, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
fmt.Println("无法获取命令的标准输出管道", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
fmt.Println("Linux命令执行失败,请检查命令输入是否有误", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 读取所有输出
|
||||
bytes, err := io.ReadAll(output)
|
||||
if err != nil {
|
||||
fmt.Println("打印异常,请检查")
|
||||
return
|
||||
}
|
||||
|
||||
if err := cmd.Wait(); err != nil {
|
||||
fmt.Println("Wait", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("打印内存信息:\n\n%s", bytes)
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package config
|
||||
|
||||
type Config struct {
|
||||
Service `mapstructure:"service"`
|
||||
DB `mapstructure:"db"`
|
||||
Dataset `mapstructure:"dataset"`
|
||||
EventMesh `mapstructure:"eventmesh"`
|
||||
}
|
||||
|
||||
// Service 服务配置项
|
||||
type Service struct {
|
||||
Env string `mapstructure:"env"`
|
||||
Domain string `mapstructure:"domain"`
|
||||
Port string `mapstructure:"port"`
|
||||
}
|
||||
|
||||
// DB 数据库配置项
|
||||
type DB struct {
|
||||
DSN string `mapstructure:"dsn"`
|
||||
}
|
||||
|
||||
// Dataset 数据集相关配置项
|
||||
type Dataset struct {
|
||||
Host string `mapstructure:"host"`
|
||||
LabelingHost string `mapstructure:"labeling_host"`
|
||||
}
|
||||
|
||||
// EventMesh 数据库配置项
|
||||
type EventMesh struct {
|
||||
Host string `mapstructure:"host"`
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package constant
|
||||
|
||||
type ContextKey string
|
||||
|
||||
const TraceID ContextKey = "trace_id"
|
||||
|
||||
const (
|
||||
EnvNameTencentProd string = "tencent-prod"
|
||||
)
|
|
@ -0,0 +1,30 @@
|
|||
package db
|
||||
|
||||
import (
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/gorm"
|
||||
"interview-one-stop-server/config"
|
||||
"time"
|
||||
)
|
||||
|
||||
var gormDB *gorm.DB
|
||||
|
||||
func InitDB() error {
|
||||
db, err := gorm.Open(mysql.Open(config.GlobalConf.DB.DSN))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
gormDB = db
|
||||
sqlDB, err := gormDB.DB()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// SetMaxIdleConns 设置空闲连接池中连接的最大数量
|
||||
sqlDB.SetMaxIdleConns(10)
|
||||
// SetMaxOpenConns 设置打开数据库连接的最大数量。
|
||||
sqlDB.SetMaxOpenConns(30)
|
||||
// SetConnMaxLifetime 设置了连接可复用的最大时间。
|
||||
sqlDB.SetConnMaxLifetime(time.Hour)
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package db
|
||||
|
||||
const (
|
||||
// TableNameAnnotatingRecord 送标任务记录
|
||||
TableNameAnnotatingRecord = "annotating_record"
|
||||
)
|
|
@ -0,0 +1,13 @@
|
|||
package handler
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"interview-one-stop-server/biz/question"
|
||||
"interview-one-stop-server/util/gin_util"
|
||||
)
|
||||
|
||||
// HandleQueryQuestionList 获取题目列表
|
||||
func HandleQueryQuestionList(c *gin.Context) {
|
||||
l, e := question.GetQuestionList(gin_util.GetContextFromGin(c))
|
||||
gin_util.GenGinResponse(c, e, l)
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
// Start a web server
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"interview-one-stop-server/config"
|
||||
"interview-one-stop-server/constant"
|
||||
"interview-one-stop-server/db"
|
||||
"interview-one-stop-server/util"
|
||||
"interview-one-stop-server/util/log"
|
||||
"time"
|
||||
|
||||
ginzap "github.com/gin-contrib/zap"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := config.InitConfig()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
r := gin.Default()
|
||||
logger := log.GetLogger()
|
||||
r.Use(ginzap.Ginzap(logger, time.RFC3339, true))
|
||||
r.Use(ginzap.RecoveryWithZap(logger, true))
|
||||
r.Use(TraceLog())
|
||||
|
||||
err = db.InitDB()
|
||||
if err != nil {
|
||||
log.Error(context.Background(), "InitDB", fmt.Sprintf("db init failed, err is %s", err.Error()))
|
||||
panic("db not ready")
|
||||
}
|
||||
|
||||
post := GetPostRouter()
|
||||
for k, v := range post {
|
||||
r.POST(k, v)
|
||||
}
|
||||
|
||||
get := GetGetRouter()
|
||||
for k, v := range get {
|
||||
r.GET(k, v)
|
||||
}
|
||||
|
||||
r.GET("/ping", Ping)
|
||||
if err := r.Run(fmt.Sprintf(":%s", config.GlobalConf.Service.Port)); err != nil {
|
||||
log.Error(context.Background(), "main", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TraceLog() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
c.Set("ctx", context.WithValue(context.Background(), constant.TraceID, util.GenUUID()))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package model
|
||||
|
||||
type Question struct {
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"interview-one-stop-server/handler"
|
||||
)
|
||||
|
||||
var post = map[string]gin.HandlerFunc{}
|
||||
|
||||
var get = map[string]gin.HandlerFunc{
|
||||
"/api/v1/question/list": handler.HandleQueryQuestionList,
|
||||
}
|
||||
|
||||
func GetPostRouter() map[string]gin.HandlerFunc {
|
||||
return post
|
||||
}
|
||||
|
||||
func GetGetRouter() map[string]gin.HandlerFunc {
|
||||
return get
|
||||
}
|
||||
|
||||
func Ping(c *gin.Context) {
|
||||
c.JSON(200, gin.H{
|
||||
"message": "pong",
|
||||
})
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package gin_util
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gin-gonic/gin"
|
||||
"interview-one-stop-server/util/ierrors"
|
||||
"interview-one-stop-server/util/log"
|
||||
)
|
||||
|
||||
func GenGinResponse(c *gin.Context, err ierrors.OneStopErr, data interface{}) {
|
||||
if err.ErrNumber.Code != ierrors.Success.Code {
|
||||
ctx, _ := c.Get("ctx")
|
||||
funcName, _ := c.Get("func_name")
|
||||
log.Error(ctx.(context.Context), funcName.(string), err.Error())
|
||||
}
|
||||
|
||||
c.JSON(200, gin.H{
|
||||
"code": err.Code,
|
||||
"message": err.Message,
|
||||
"data": data,
|
||||
})
|
||||
}
|
||||
|
||||
func GetContextFromGin(c *gin.Context) context.Context {
|
||||
ctx, ok := c.Get("ctx")
|
||||
if ok {
|
||||
return ctx.(context.Context)
|
||||
}
|
||||
return context.Background()
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
package ierrors
|
||||
|
||||
import "fmt"
|
||||
|
||||
type ErrNumber struct {
|
||||
Code int
|
||||
Message string
|
||||
}
|
||||
|
||||
func (err ErrNumber) Error() string {
|
||||
return err.Message
|
||||
}
|
||||
|
||||
type OneStopErr struct {
|
||||
ErrNumber
|
||||
Errord error // 保存内部错误信息
|
||||
}
|
||||
|
||||
func (err *OneStopErr) Error() string {
|
||||
return fmt.Sprintf("OneStop - code: %d, message: %s, error: %s", err.Code, err.Message, err.Errord)
|
||||
}
|
||||
|
||||
func NewOneStopErr(errN ErrNumber, err error) OneStopErr {
|
||||
return OneStopErr{
|
||||
ErrNumber: errN,
|
||||
Errord: err,
|
||||
}
|
||||
}
|
||||
|
||||
var OneStopSuccess = NewOneStopErr(Success, nil)
|
||||
|
||||
//错误码一共四位,一二位为功能,三四位为具体错误
|
||||
|
||||
var (
|
||||
Success = ErrNumber{
|
||||
Code: 0,
|
||||
Message: "SUCCEED",
|
||||
}
|
||||
/*** 公共错误码,一二位为10 ***/
|
||||
|
||||
ErrJsonParseFailed = ErrNumber{
|
||||
Code: 1000,
|
||||
Message: "JSON 转换失败",
|
||||
}
|
||||
|
||||
ErrHttpBodyReadFailed = ErrNumber{
|
||||
Code: 1001,
|
||||
Message: "请求body获取失败",
|
||||
}
|
||||
|
||||
ErrHttpDbOperateFailed = ErrNumber{
|
||||
Code: 1002,
|
||||
Message: "数据库操作异常",
|
||||
}
|
||||
|
||||
ErrHttpParamNotValid = ErrNumber{
|
||||
Code: 1003,
|
||||
Message: "入参不符合要求",
|
||||
}
|
||||
)
|
|
@ -0,0 +1,110 @@
|
|||
package log
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
lumberjack "gopkg.in/natefinch/lumberjack.v2"
|
||||
"interview-one-stop-server/util"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
var log *zap.Logger
|
||||
|
||||
type lumberjackSink struct {
|
||||
*lumberjack.Logger
|
||||
}
|
||||
|
||||
func (l lumberjackSink) Sync() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetLogger() *zap.Logger {
|
||||
return log
|
||||
}
|
||||
|
||||
func newLogger(logLevel string, logFolder string, dev bool) (*zap.Logger, error) {
|
||||
var level zapcore.Level
|
||||
switch logLevel {
|
||||
case "debug":
|
||||
level = zap.DebugLevel
|
||||
case "info":
|
||||
level = zap.InfoLevel
|
||||
case "warning":
|
||||
level = zap.WarnLevel
|
||||
case "error":
|
||||
level = zap.ErrorLevel
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown log level %s", logLevel)
|
||||
}
|
||||
|
||||
encoderConfig := zapcore.EncoderConfig{
|
||||
TimeKey: "ts",
|
||||
LevelKey: "level",
|
||||
NameKey: "logger",
|
||||
MessageKey: "msg",
|
||||
StacktraceKey: "stacktrace",
|
||||
LineEnding: zapcore.DefaultLineEnding,
|
||||
EncodeLevel: zapcore.CapitalLevelEncoder,
|
||||
EncodeTime: zapcore.RFC3339TimeEncoder,
|
||||
EncodeDuration: zapcore.SecondsDurationEncoder,
|
||||
EncodeCaller: zapcore.ShortCallerEncoder,
|
||||
ConsoleSeparator: " ",
|
||||
}
|
||||
ll := lumberjack.Logger{
|
||||
Filename: logFolder,
|
||||
MaxSize: 100, // MB
|
||||
MaxBackups: 31,
|
||||
MaxAge: 31, // days
|
||||
Compress: false,
|
||||
}
|
||||
|
||||
_ = zap.RegisterSink("lumberjack", func(*url.URL) (zap.Sink, error) {
|
||||
return lumberjackSink{
|
||||
Logger: &ll,
|
||||
}, nil
|
||||
})
|
||||
|
||||
loggerConfig := zap.Config{
|
||||
Level: zap.NewAtomicLevelAt(level),
|
||||
Development: dev,
|
||||
Encoding: "console",
|
||||
EncoderConfig: encoderConfig,
|
||||
OutputPaths: []string{"stderr", fmt.Sprintf("lumberjack:%s", logFolder)},
|
||||
}
|
||||
|
||||
logger, err := loggerConfig.Build()
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("build zap logger from config error: %v", err))
|
||||
}
|
||||
return logger, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
log, _ = newLogger("info", "logs/app.log", false)
|
||||
}
|
||||
|
||||
func Error(ctx context.Context, label string, msg string) {
|
||||
log.Sugar().Error(getTraceIDFromContext(ctx) + " label=" + label + ",msg=" + msg)
|
||||
}
|
||||
|
||||
func Warn(ctx context.Context, label string, msg string) {
|
||||
log.Sugar().Warnf(getTraceIDFromContext(ctx) + " label=" + label + ",msg=" + msg)
|
||||
}
|
||||
|
||||
func Info(ctx context.Context, label string, msg string) {
|
||||
log.Sugar().Info(getTraceIDFromContext(ctx) + " label=" + label + ",msg=" + msg)
|
||||
}
|
||||
|
||||
func Debug(ctx context.Context, label string, msg string) {
|
||||
log.Sugar().Debug(getTraceIDFromContext(ctx) + " label=" + label + ",msg=" + msg)
|
||||
}
|
||||
|
||||
func getTraceIDFromContext(ctx context.Context) string {
|
||||
traceID := ctx.Value("trace_id")
|
||||
if traceID == nil {
|
||||
return util.GenUUID()
|
||||
}
|
||||
return traceID.(string)
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package log
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"interview-one-stop-server/util"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestLog(t *testing.T) {
|
||||
ctx := context.WithValue(context.Background(), "trace_id", util.GenUUID())
|
||||
|
||||
err := errors.New("it's an error")
|
||||
Error(ctx, "TestLog Error", fmt.Sprintf("err is %s,value is %+v", err.Error(), struct {
|
||||
Name string
|
||||
Age int
|
||||
}{
|
||||
"issue",
|
||||
2,
|
||||
}))
|
||||
Warn(ctx, "TestLog Warn", fmt.Sprintf("err is %s,value is %v", errors.New("it's an error").Error(), struct {
|
||||
Name string
|
||||
Age int
|
||||
}{
|
||||
"issue",
|
||||
2,
|
||||
}))
|
||||
Info(ctx, "TestLog Info", fmt.Sprintf("no error,value is %+v", struct {
|
||||
Name string
|
||||
Age int
|
||||
}{
|
||||
"issue",
|
||||
2,
|
||||
}))
|
||||
Debug(ctx, "TestLog Debug", "it's end")
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package util
|
||||
|
||||
import "strconv"
|
||||
|
||||
func Int64ArrJoin(nums []int64, sep string) string {
|
||||
res := ""
|
||||
if len(nums) == 0 {
|
||||
return res
|
||||
}
|
||||
for _, num := range nums {
|
||||
res += strconv.Itoa(int(num)) + sep
|
||||
}
|
||||
return res[:len(res)-1]
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/google/uuid"
|
||||
"interview-one-stop-server/constant"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
func CreateContextWithTraceID() context.Context {
|
||||
return context.WithValue(context.Background(), constant.TraceID, GenUUID())
|
||||
}
|
||||
|
||||
func GenUUID() string {
|
||||
return uuid.New().String()
|
||||
}
|
||||
|
||||
// PanicToError Panic转换为error
|
||||
func PanicToError(f func()) (err error) {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
err = fmt.Errorf(PanicTrace(e))
|
||||
}
|
||||
}()
|
||||
f()
|
||||
return
|
||||
}
|
||||
|
||||
// PanicTrace panic调用链跟踪
|
||||
func PanicTrace(err interface{}) string {
|
||||
stackBuf := make([]byte, 4096)
|
||||
n := runtime.Stack(stackBuf, false)
|
||||
|
||||
return fmt.Sprintf("panic: %v %s", err, stackBuf[:n])
|
||||
}
|
Loading…
Reference in New Issue