Commit cad2b7f3c47265a75ce78e22fa4192355f0d103e

Authored by zhangqijia
1 parent c92a54a3

reactor: 重构目录, 重构日志, 增加redis组件

Showing 47 changed files with 1321 additions and 759 deletions   Show diff stats
cmd/game.go
... ... @@ -3,9 +3,9 @@ package main
3 3 import (
4 4 "os"
5 5 "os/signal"
6   - "pro2d/components/net"
7 6 "pro2d/conf"
8   - "pro2d/utils"
  7 + "pro2d/src/components/logger"
  8 + "pro2d/src/components/net"
9 9 "syscall"
10 10 )
11 11  
... ... @@ -21,8 +21,9 @@ func main() {
21 21  
22 22 select {
23 23 case e := <- err:
24   - utils.Sugar.Errorf("game server error: %v", e)
  24 + logger.Error("game server error: %v", e)
25 25 case <-stopChan:
26 26 s.Stop()
  27 + logger.Debug("game stop...")
27 28 }
28 29 }
... ...
cmd/http.go
... ... @@ -3,8 +3,9 @@ package main
3 3 import (
4 4 "os"
5 5 "os/signal"
6   - "pro2d/actions"
7   - "pro2d/utils"
  6 + _ "pro2d/conf"
  7 + "pro2d/src/actions"
  8 + "pro2d/src/components/logger"
8 9 "syscall"
9 10 )
10 11  
... ... @@ -20,8 +21,8 @@ func main() {
20 21  
21 22 select {
22 23 case e := <- err:
23   - utils.Sugar.Errorf("game server error: %v", e)
  24 + logger.Error("game server error: %v", e)
24 25 case <-stopChan:
25   - utils.Sugar.Debugf("game stop")
  26 + logger.Debug("game stop")
26 27 }
27 28 }
28 29 \ No newline at end of file
... ...
components/db/redis.go deleted
... ... @@ -1,54 +0,0 @@
1   -package db
2   -//
3   -//import (
4   -// "fmt"
5   -// "github.com/garyburd/redigo/redis"
6   -// "pro2d/conf"
7   -// "pro2d/utils"
8   -// "time"
9   -//)
10   -//
11   -//type RedisPool struct {
12   -// RedisPool *redis.Pool
13   -//}
14   -//
15   -//func (rp *RedisPool)Connect(conf *conf.ServerConf) error {
16   -// rp.RedisPool = &redis.Pool{
17   -// //最大活跃连接数,0代表无限
18   -// MaxActive: 888,
19   -// MaxIdle: 20,
20   -// //闲置连接的超时时间
21   -// IdleTimeout: time.Second * 100,
22   -// //定义拨号获得连接的函数
23   -// Dial: func() (redis.Conn, error) {
24   -// option := []redis.DialOption{redis.DialDatabase(conf.RedisConf.DB)}
25   -// if conf.RedisConf.Auth != "" {
26   -// option = append(option, redis.DialPassword(conf.RedisConf.Auth))
27   -// }
28   -// return redis.Dial("tcp",conf.RedisConf.Address, option...)
29   -// },
30   -// }
31   -// return nil
32   -//}
33   -//
34   -//func (rp *RedisPool)Close() {
35   -// rp.RedisPool.Close()
36   -//}
37   -//
38   -//func (rp *RedisPool) Insert() error {
39   -// conn := rp.RedisPool.Get()
40   -// defer conn.Close()
41   -// reply, err := conn.Do("HKEYS", fmt.Sprintf("account:%s", "123123"))
42   -// if err != nil {
43   -// return err
44   -// }
45   -//
46   -// utils.Sugar.Debugf("%v", reply)
47   -// reply, err = conn.Do("HMSET", fmt.Sprintf("account:%s", "1231231"), "phone", "1231231", "passwd", "2131231")
48   -// if err != nil {
49   -// utils.Sugar.Errorf("%v", err)
50   -// return err
51   -// }
52   -// utils.Sugar.Debugf("%v", reply)
53   -// return nil
54   -//}
conf/RedisKeys.go deleted
... ... @@ -1,2 +0,0 @@
1   -package conf
2   -
conf/conf.go
1 1 package conf
2 2  
3 3 import (
  4 + "encoding/json"
4 5 "fmt"
5   - lumberjack "gopkg.in/natefinch/lumberjack.v2"
6 6 "gopkg.in/yaml.v3"
7 7 "io/ioutil"
8   - "pro2d/components/db"
9   - "pro2d/utils"
  8 + "pro2d/src/components/db"
  9 + "pro2d/src/components/logger"
  10 + "pro2d/src/utils"
  11 + "strings"
10 12 )
11 13  
12 14 type RedisConf struct {
... ... @@ -36,11 +38,41 @@ type TLS struct {
36 38 }
37 39  
38 40 type SConf struct {
39   - ID string `yaml:"id"`
40   - Name string `yaml:"name"`
41   - IP string `yaml:"ip"`
42   - Port int `yaml:"port"`
43   - DBName string `yaml:"dbname"`
  41 + ID string `yaml:"id"`
  42 + Name string `yaml:"name"`
  43 + IP string `yaml:"ip"`
  44 + Port int `yaml:"port"`
  45 + DBName string `yaml:"dbname"`
  46 +}
  47 +
  48 +type LogConsole struct {
  49 + Level string `yaml:"level" json:"level"`
  50 + Color bool `yaml:"color" json:"color"`
  51 +}
  52 +
  53 +type LogFile struct {
  54 + Level string `yaml:"level" json:"level"`
  55 + Daily bool `yaml:"daily" json:"daily"`
  56 + Maxlines int `yaml:"maxlines" json:"maxlines"`
  57 + Maxsize int `yaml:"maxsize" json:"maxsize"`
  58 + Maxdays int `yaml:"maxdays" json:"maxdays"`
  59 + Append bool `yaml:"append" json:"append"`
  60 + Permit string `yaml:"permit" json:"permit"`
  61 +}
  62 +
  63 +type LogConn struct {
  64 + Net string `yaml:"net" json:"net"`
  65 + Addr string `yaml:"addr" json:"addr"`
  66 + Level string `yaml:"level" json:"level"`
  67 + Reconnect bool `yaml:"reconnect" json:"reconnect"`
  68 + ReconnectOnMsg bool `yaml:"reconnectOnMsg" json:"reconnectOnMsg"`
  69 +}
  70 +
  71 +type LogConf struct {
  72 + TimeFormat string `yaml:"TimeFormat" json:"TimeFormat"`
  73 + LogConsole *LogConsole `yaml:"Console" json:"Console"`
  74 + LogFile *LogFile `yaml:"File" json:"File"`
  75 + LogConn *LogConn `yaml:"Conn" json:"Conn"`
44 76 }
45 77  
46 78 type ServerConf struct {
... ... @@ -53,7 +85,7 @@ type ServerConf struct {
53 85 AccountConf *SConf `yaml:"server_account"`
54 86 GameConf *SConf `yaml:"server_game"`
55 87 RedisConf *RedisConf `yaml:"redis"`
56   - LogConf *lumberjack.Logger `json:"logconf"`
  88 + LogConf *LogConf `yaml:"logconf" json:"logconf"`
57 89 Etcd *Etcd `yaml:"etcd"`
58 90 }
59 91  
... ... @@ -74,15 +106,24 @@ func init() {
74 106 return
75 107 }
76 108  
  109 + c, err := json.Marshal(&GlobalConf.LogConf)
  110 + if err != nil {
  111 + fmt.Errorf("log conf %v", err)
  112 + return
  113 + }
77 114 //初始化日志
78   - utils.InitLogger(GlobalConf.LogConf)
  115 + err = logger.SetLogger(string(c), strings.ToLower(GlobalConf.GameConf.Name))
  116 + if err != nil {
  117 + fmt.Errorf("log conf %v", err)
  118 + return
  119 + }
79 120  
80 121 //初始化雪花算法
81 122 SnowFlack = utils.NewSnowflake(GlobalConf.WorkerID, GlobalConf.DatacenterID)
82 123  
83 124 err = db.Connect(GlobalConf.MongoConf.User, GlobalConf.MongoConf.Password, GlobalConf.MongoConf.Host, GlobalConf.MongoConf.Port, GlobalConf.MongoConf.MaxNum, GlobalConf.MongoConf.TimeOut)
84 125 if err != nil {
85   - utils.Sugar.Errorf("connect db err: %v", err)
  126 + logger.Error("connect db err: %v", err)
86 127 }
87 128  
88 129 }
89 130 \ No newline at end of file
... ...
conf/conf.yaml
... ... @@ -16,11 +16,6 @@ etcd:
16 16 endpoints:
17 17 - "192.168.0.206:2379"
18 18  
19   -tls:
20   - status: true
21   - key: "keys/server.key"
22   - pem: "keys/server.pem"
23   -
24 19 server_account:
25 20 id: "1"
26 21 name: "account"
... ... @@ -36,8 +31,21 @@ server_game:
36 31 dbname: "game"
37 32  
38 33 logconf:
39   - filename: "./pro2d.log" # ⽇志⽂件路径
40   - maxsize: 1024 # 1M=1024KB=1024000byte
41   - maxbackups: 5 # 最多保留5个备份
42   - maxage: 30 # days
43   - compress: true # 是否压缩 disabled by default
44 34 \ No newline at end of file
  35 + TimeFormat: "2006-01-02 15:04:05"
  36 + Console:
  37 + level: "TRAC"
  38 + color: true
  39 + File:
  40 + level: "TRAC"
  41 + daily: true
  42 + maxlines: 1000000
  43 + maxsize: 1
  44 + maxdays: -1
  45 + append: true
  46 + permit: "0660"
  47 +# Conn:
  48 +# net: "tcp"
  49 +# addr: "127.0.0.1"
  50 +# level: "TRAC"
  51 +# reconnect: false
  52 +# reconnectOnMsg: false
45 53 \ No newline at end of file
... ...
... ... @@ -5,16 +5,15 @@ go 1.17
5 5 require (
6 6 github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394
7 7 github.com/dgrijalva/jwt-go v3.2.0+incompatible
  8 + github.com/garyburd/redigo v1.6.3
8 9 github.com/gin-gonic/gin v1.7.7
9 10 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
10 11 github.com/golang/protobuf v1.5.2
11 12 go.etcd.io/etcd/api/v3 v3.5.2
12 13 go.etcd.io/etcd/client/v3 v3.5.2
13 14 go.mongodb.org/mongo-driver v1.8.3
14   - go.uber.org/zap v1.17.0
15 15 google.golang.org/grpc v1.38.0
16 16 google.golang.org/protobuf v1.27.1
17   - gopkg.in/natefinch/lumberjack.v2 v2.0.0
18 17 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
19 18 )
20 19  
... ... @@ -44,12 +43,14 @@ require (
44 43 go.etcd.io/etcd/client/pkg/v3 v3.5.2 // indirect
45 44 go.uber.org/atomic v1.7.0 // indirect
46 45 go.uber.org/multierr v1.6.0 // indirect
  46 + go.uber.org/zap v1.17.0 // indirect
47 47 golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f // indirect
48 48 golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 // indirect
49 49 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
50 50 golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40 // indirect
51 51 golang.org/x/text v0.3.5 // indirect
52 52 google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c // indirect
  53 + gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
53 54 gopkg.in/yaml.v2 v2.4.0 // indirect
54 55 )
55 56  
... ...
... ... @@ -33,6 +33,8 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m
33 33 github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
34 34 github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
35 35 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
  36 +github.com/garyburd/redigo v1.6.3 h1:HCeeRluvAgMusMomi1+6Y5dmFOdYV/JzoRrrbFlkGIc=
  37 +github.com/garyburd/redigo v1.6.3/go.mod h1:rTb6epsqigu3kYKBnaF028A7Tf/Aw5s0cqA47doKKqw=
36 38 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
37 39 github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
38 40 github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
... ...
keys/ca.crt deleted
... ... @@ -1,21 +0,0 @@
1   ------BEGIN CERTIFICATE-----
2   -MIIDiDCCAnACCQDvizTzfA5snjANBgkqhkiG9w0BAQsFADCBhTELMAkGA1UEBhMC
3   -Q04xETAPBgNVBAgMCFpoZUppYW5nMREwDwYDVQQHDAhaaGVKaWFuZzEPMA0GA1UE
4   -CgwGR2xvYmFsMRcwFQYDVQQDDA5wcm8yZCBTZWN1cml0eTEWMBQGA1UECwwNSVQg
5   -RGVwYXJ0bWVudDEOMAwGA1UEAwwFcHJvMmQwHhcNMjIwMjIyMDYwNzIzWhcNMzIw
6   -MjIwMDYwNzIzWjCBhTELMAkGA1UEBhMCQ04xETAPBgNVBAgMCFpoZUppYW5nMREw
7   -DwYDVQQHDAhaaGVKaWFuZzEPMA0GA1UECgwGR2xvYmFsMRcwFQYDVQQDDA5wcm8y
8   -ZCBTZWN1cml0eTEWMBQGA1UECwwNSVQgRGVwYXJ0bWVudDEOMAwGA1UEAwwFcHJv
9   -MmQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC+eik5acnrHwEz+Zwb
10   -j7R1eCb9VrJymCii7PtCeeqCZaRBuUYUwKSkEdv367HRH00CW2tYCMMsoBqBewxO
11   -tBwa+1rpCbUvqWdmipMTjE4vmA5Kb50HS3/VxTlnICPb0P0CO2kArrktEPg3W7c5
12   -Xwmbe8BvYtdEV/BkLUG0+NQbXfXgkKBEs6t1FOqtJAubURann3wAH9pLIDRUcj5B
13   -QzM9b+8qvTjLLj4/uaac4b7X6bfVyaeX8cWOXLHDYEXwIdlRXYz4l+gSVO/EKIgA
14   -5QfwLJTWuxnzcM/klOPsIamQtOYIwEkc1KiCNPZ2CAkzXFspKweR1IwsDM8N/hUU
15   -BWxZAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAFzY2wB6phXffFwAcGQZx9FYY9S5
16   -3L0Xm4mji50+e6UA+N9MjO/4SXNpjt6qMQ3zwSUalapmr8uh9DWLsjRv6HRvgoIm
17   -9tkx8UQkjOoFKcee2+Z780BjsR7SI1HS3VLKUOjm8avKazFGGxjsOtayxzGytAT2
18   -DK1ubsqSbiK7hFFJqU3cUPP7D3pJOAKaBnLq8MA63vSGTsz2sQUR2Y5DKMXpIhEQ
19   -zlSQvMzsQXv0yll3DhPv76yV6ZKQzCHCoqaPBNU+9QhrWFqIP2QXLR5smeFqOGQM
20   -ngBFwwv9ysSMmcpanMePiuuvXykZiPJpknxdAxry6+A8+/KQ/07hFAHarbI=
21   ------END CERTIFICATE-----
keys/ca.key deleted
... ... @@ -1,28 +0,0 @@
1   ------BEGIN PRIVATE KEY-----
2   -MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC+eik5acnrHwEz
3   -+Zwbj7R1eCb9VrJymCii7PtCeeqCZaRBuUYUwKSkEdv367HRH00CW2tYCMMsoBqB
4   -ewxOtBwa+1rpCbUvqWdmipMTjE4vmA5Kb50HS3/VxTlnICPb0P0CO2kArrktEPg3
5   -W7c5Xwmbe8BvYtdEV/BkLUG0+NQbXfXgkKBEs6t1FOqtJAubURann3wAH9pLIDRU
6   -cj5BQzM9b+8qvTjLLj4/uaac4b7X6bfVyaeX8cWOXLHDYEXwIdlRXYz4l+gSVO/E
7   -KIgA5QfwLJTWuxnzcM/klOPsIamQtOYIwEkc1KiCNPZ2CAkzXFspKweR1IwsDM8N
8   -/hUUBWxZAgMBAAECggEATl/Jkpwavyn0vsQYHacVo7gaoucHaet93PwRrpqniZv0
9   -6C4pzeQuWmwWzH4onll4wF2JX6HLXRNLlLdiqwelAN0n3PdnnALiTuj593MlwKOa
10   -Tbp7LEM+iGEsa2hoGMx3LnHvlJ5QB2ESIQUV8P9P3rAe0DYlSTO98BpHDQXNkKx0
11   -UPo85k5IgnjueeHdxn8lokQsKXN5R8bS9GduRaEyMR/SHrT3T6YmRKr666N/AQas
12   -7dDe9qGwTpUFympP3PEX/VHQsF9x3/ng6wbRsiijKsUUeGpbslulKi5kHw3j+5Eo
13   -YkeHjH/iMySd41m4oszM4QmCYr5t49AAQl2bYW3b4QKBgQDxFW297lVS8O+z/ANR
14   -yVKI7iejiLKdpc0wlZiFWkAKCve+SCGJ2GZ907NKzLq1O6/byhs7XCu229oLvIFm
15   -/e1sCxdHR/bEf3CTlgoQYXiya0jCgF2GUM/hZpvWZHL0ECZfhwPsks4NWhdKEPyD
16   -9XWpjfC0qlVh18xAF7Zyrw4sTQKBgQDKQyp/wJub0UZ9FmaLORpxr7rO5pROEFov
17   -SiwoJ8gYLo7eU0QT6ipVD/vOTE2+5FdYuk41euYZLOzR0N72kqddUlVAtq9bly92
18   -sjtvM8iPSGU5cN0D+Up9KT0ZU3zIXH1mVFHsNmm62uN4B3s9Rs+0JvLTI6OwqLAW
19   -LtyqK09WPQKBgEOFP+YpASaoqknbdEaMvxvwr5Nirrvueuh3jW8T1sm5Rqe5ZgNI
20   -Y3QsPZPegRBPNjK1iSj36JpfOtN8qTViOwO+m3dwVVG1a586L3llAzvdRlSLRSZg
21   -LciwR0clfPiUKVsp4lR4zVL5/3nUBhUjQyAIy/idmCo+GUt+GLBIDQ0lAoGABnmT
22   -+Lb/xEM00HhRHA/d6tnHTyxOfxlC6dSkCT0MyMlkxXVA7qpGZKa4VuhWbM/+g9ai
23   -/k9K4m9vvV/EY3xaY0BpfkLa5kG2wUP/ZxXvS7bzlp0oViI64jrZu9/SVM+xK/9z
24   -B+7N/69WLNeAeHu11nyQtXWkndkome0yHzh3t7kCgYBM/U2XmSx0LYHqe+699NXy
25   -4ey3B4IQHb55Fw8LNiaI96ylQG43kNQpZUELjaPBTpQ1a76uL0bRDhjEpZDwjyK0
26   -gJUWilI8DYTvMa/fdpuVtc5qJErwfNmhRIWiWWryE1OrD1dprQYZzeAy/0+5HDrb
27   -lhQhMGXOJbhiQdKPMcwGbw==
28   ------END PRIVATE KEY-----
keys/ca.srl deleted
... ... @@ -1 +0,0 @@
1   -D4E715D41B6F9424
keys/openssl.cnf deleted
... ... @@ -1,357 +0,0 @@
1   -#
2   -# OpenSSL example configuration file.
3   -# This is mostly being used for generation of certificate requests.
4   -#
5   -
6   -# Note that you can include other files from the main configuration
7   -# file using the .include directive.
8   -#.include filename
9   -
10   -# This definition stops the following lines choking if HOME isn't
11   -# defined.
12   -HOME = .
13   -RANDFILE = $ENV::HOME/.rnd
14   -
15   -# Extra OBJECT IDENTIFIER info:
16   -#oid_file = $ENV::HOME/.oid
17   -oid_section = new_oids
18   -
19   -# To use this configuration file with the "-extfile" option of the
20   -# "openssl x509" utility, name here the section containing the
21   -# X.509v3 extensions to use:
22   -# extensions =
23   -# (Alternatively, use a configuration file that has only
24   -# X.509v3 extensions in its main [= default] section.)
25   -
26   -[ new_oids ]
27   -
28   -# We can add new OIDs in here for use by 'ca', 'req' and 'ts'.
29   -# Add a simple OID like this:
30   -# testoid1=1.2.3.4
31   -# Or use config file substitution like this:
32   -# testoid2=${testoid1}.5.6
33   -
34   -# Policies used by the TSA examples.
35   -tsa_policy1 = 1.2.3.4.1
36   -tsa_policy2 = 1.2.3.4.5.6
37   -tsa_policy3 = 1.2.3.4.5.7
38   -
39   -####################################################################
40   -[ ca ]
41   -default_ca = CA_default # The default ca section
42   -
43   -####################################################################
44   -[ CA_default ]
45   -
46   -dir = ./demoCA # Where everything is kept
47   -certs = $dir/certs # Where the issued certs are kept
48   -crl_dir = $dir/crl # Where the issued crl are kept
49   -database = $dir/index.txt # database index file.
50   -#unique_subject = no # Set to 'no' to allow creation of
51   - # several certs with same subject.
52   -new_certs_dir = $dir/newcerts # default place for new certs.
53   -
54   -certificate = $dir/cacert.pem # The CA certificate
55   -serial = $dir/serial # The current serial number
56   -crlnumber = $dir/crlnumber # the current crl number
57   - # must be commented out to leave a V1 CRL
58   -crl = $dir/crl.pem # The current CRL
59   -private_key = $dir/private/cakey.pem# The private key
60   -RANDFILE = $dir/private/.rand # private random number file
61   -
62   -x509_extensions = usr_cert # The extensions to add to the cert
63   -
64   -# Comment out the following two lines for the "traditional"
65   -# (and highly broken) format.
66   -name_opt = ca_default # Subject Name options
67   -cert_opt = ca_default # Certificate field options
68   -
69   -# Extension copying option: use with caution.
70   -copy_extensions = copy
71   -
72   -# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
73   -# so this is commented out by default to leave a V1 CRL.
74   -# crlnumber must also be commented out to leave a V1 CRL.
75   -# crl_extensions = crl_ext
76   -
77   -default_days = 365 # how long to certify for
78   -default_crl_days= 30 # how long before next CRL
79   -default_md = default # use public key default MD
80   -preserve = no # keep passed DN ordering
81   -
82   -# A few difference way of specifying how similar the request should look
83   -# For type CA, the listed attributes must be the same, and the optional
84   -# and supplied fields are just that :-)
85   -policy = policy_match
86   -
87   -# For the CA policy
88   -[ policy_match ]
89   -countryName = match
90   -stateOrProvinceName = match
91   -organizationName = match
92   -organizationalUnitName = optional
93   -commonName = supplied
94   -emailAddress = optional
95   -
96   -# For the 'anything' policy
97   -# At this point in time, you must list all acceptable 'object'
98   -# types.
99   -[ policy_anything ]
100   -countryName = optional
101   -stateOrProvinceName = optional
102   -localityName = optional
103   -organizationName = optional
104   -organizationalUnitName = optional
105   -commonName = supplied
106   -emailAddress = optional
107   -
108   -####################################################################
109   -[ req ]
110   -default_bits = 2048
111   -default_keyfile = privkey.pem
112   -distinguished_name = req_distinguished_name
113   -attributes = req_attributes
114   -x509_extensions = v3_ca # The extensions to add to the self signed cert
115   -
116   -# Passwords for private keys if not present they will be prompted for
117   -# input_password = secret
118   -# output_password = secret
119   -
120   -# This sets a mask for permitted string types. There are several options.
121   -# default: PrintableString, T61String, BMPString.
122   -# pkix : PrintableString, BMPString (PKIX recommendation before 2004)
123   -# utf8only: only UTF8Strings (PKIX recommendation after 2004).
124   -# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
125   -# MASK:XXXX a literal mask value.
126   -# WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings.
127   -string_mask = utf8only
128   -
129   -req_extensions = v3_req # The extensions to add to a certificate request
130   -
131   -[ req_distinguished_name ]
132   -countryName = Country Name (2 letter code)
133   -countryName_default = AU
134   -countryName_min = 2
135   -countryName_max = 2
136   -
137   -stateOrProvinceName = State or Province Name (full name)
138   -stateOrProvinceName_default = Some-State
139   -
140   -localityName = Locality Name (eg, city)
141   -
142   -0.organizationName = Organization Name (eg, company)
143   -0.organizationName_default = Internet Widgits Pty Ltd
144   -
145   -# we can do this but it is not needed normally :-)
146   -#1.organizationName = Second Organization Name (eg, company)
147   -#1.organizationName_default = World Wide Web Pty Ltd
148   -
149   -organizationalUnitName = Organizational Unit Name (eg, section)
150   -#organizationalUnitName_default =
151   -
152   -commonName = Common Name (e.g. server FQDN or YOUR name)
153   -commonName_max = 64
154   -
155   -emailAddress = Email Address
156   -emailAddress_max = 64
157   -
158   -# SET-ex3 = SET extension number 3
159   -
160   -[ req_attributes ]
161   -challengePassword = A challenge password
162   -challengePassword_min = 4
163   -challengePassword_max = 20
164   -
165   -unstructuredName = An optional company name
166   -
167   -[ usr_cert ]
168   -
169   -# These extensions are added when 'ca' signs a request.
170   -
171   -# This goes against PKIX guidelines but some CAs do it and some software
172   -# requires this to avoid interpreting an end user certificate as a CA.
173   -
174   -basicConstraints=CA:FALSE
175   -
176   -# Here are some examples of the usage of nsCertType. If it is omitted
177   -# the certificate can be used for anything *except* object signing.
178   -
179   -# This is OK for an SSL server.
180   -# nsCertType = server
181   -
182   -# For an object signing certificate this would be used.
183   -# nsCertType = objsign
184   -
185   -# For normal client use this is typical
186   -# nsCertType = client, email
187   -
188   -# and for everything including object signing:
189   -# nsCertType = client, email, objsign
190   -
191   -# This is typical in keyUsage for a client certificate.
192   -# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
193   -
194   -# This will be displayed in Netscape's comment listbox.
195   -nsComment = "OpenSSL Generated Certificate"
196   -
197   -# PKIX recommendations harmless if included in all certificates.
198   -subjectKeyIdentifier=hash
199   -authorityKeyIdentifier=keyid,issuer
200   -
201   -# This stuff is for subjectAltName and issuerAltname.
202   -# Import the email address.
203   -# subjectAltName=email:copy
204   -# An alternative to produce certificates that aren't
205   -# deprecated according to PKIX.
206   -# subjectAltName=email:move
207   -
208   -# Copy subject details
209   -# issuerAltName=issuer:copy
210   -
211   -#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
212   -#nsBaseUrl
213   -#nsRevocationUrl
214   -#nsRenewalUrl
215   -#nsCaPolicyUrl
216   -#nsSslServerName
217   -
218   -# This is required for TSA certificates.
219   -# extendedKeyUsage = critical,timeStamping
220   -
221   -[ v3_req ]
222   -
223   -# Extensions to add to a certificate request
224   -
225   -basicConstraints = CA:FALSE
226   -keyUsage = nonRepudiation, digitalSignature, keyEncipherment
227   -subjectAltName = @alt_names
228   -
229   -[alt_names]
230   -DNS.1 = localhost
231   -DNS.1 = pro2d
232   -
233   -[ v3_ca ]
234   -
235   -
236   -# Extensions for a typical CA
237   -
238   -
239   -# PKIX recommendation.
240   -
241   -subjectKeyIdentifier=hash
242   -
243   -authorityKeyIdentifier=keyid:always,issuer
244   -
245   -basicConstraints = critical,CA:true
246   -
247   -# Key usage: this is typical for a CA certificate. However since it will
248   -# prevent it being used as an test self-signed certificate it is best
249   -# left out by default.
250   -# keyUsage = cRLSign, keyCertSign
251   -
252   -# Some might want this also
253   -# nsCertType = sslCA, emailCA
254   -
255   -# Include email address in subject alt name: another PKIX recommendation
256   -# subjectAltName=email:copy
257   -# Copy issuer details
258   -# issuerAltName=issuer:copy
259   -
260   -# DER hex encoding of an extension: beware experts only!
261   -# obj=DER:02:03
262   -# Where 'obj' is a standard or added object
263   -# You can even override a supported extension:
264   -# basicConstraints= critical, DER:30:03:01:01:FF
265   -
266   -[ crl_ext ]
267   -
268   -# CRL extensions.
269   -# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
270   -
271   -# issuerAltName=issuer:copy
272   -authorityKeyIdentifier=keyid:always
273   -
274   -[ proxy_cert_ext ]
275   -# These extensions should be added when creating a proxy certificate
276   -
277   -# This goes against PKIX guidelines but some CAs do it and some software
278   -# requires this to avoid interpreting an end user certificate as a CA.
279   -
280   -basicConstraints=CA:FALSE
281   -
282   -# Here are some examples of the usage of nsCertType. If it is omitted
283   -# the certificate can be used for anything *except* object signing.
284   -
285   -# This is OK for an SSL server.
286   -# nsCertType = server
287   -
288   -# For an object signing certificate this would be used.
289   -# nsCertType = objsign
290   -
291   -# For normal client use this is typical
292   -# nsCertType = client, email
293   -
294   -# and for everything including object signing:
295   -# nsCertType = client, email, objsign
296   -
297   -# This is typical in keyUsage for a client certificate.
298   -# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
299   -
300   -# This will be displayed in Netscape's comment listbox.
301   -nsComment = "OpenSSL Generated Certificate"
302   -
303   -# PKIX recommendations harmless if included in all certificates.
304   -subjectKeyIdentifier=hash
305   -authorityKeyIdentifier=keyid,issuer
306   -
307   -# This stuff is for subjectAltName and issuerAltname.
308   -# Import the email address.
309   -# subjectAltName=email:copy
310   -# An alternative to produce certificates that aren't
311   -# deprecated according to PKIX.
312   -# subjectAltName=email:move
313   -
314   -# Copy subject details
315   -# issuerAltName=issuer:copy
316   -
317   -#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
318   -#nsBaseUrl
319   -#nsRevocationUrl
320   -#nsRenewalUrl
321   -#nsCaPolicyUrl
322   -#nsSslServerName
323   -
324   -# This really needs to be in place for it to be a proxy certificate.
325   -proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
326   -
327   -####################################################################
328   -[ tsa ]
329   -
330   -default_tsa = tsa_config1 # the default TSA section
331   -
332   -[ tsa_config1 ]
333   -
334   -# These are used by the TSA reply generation only.
335   -dir = ./demoCA # TSA root directory
336   -serial = $dir/tsaserial # The current serial number (mandatory)
337   -crypto_device = builtin # OpenSSL engine to use for signing
338   -signer_cert = $dir/tsacert.pem # The TSA signing certificate
339   - # (optional)
340   -certs = $dir/cacert.pem # Certificate chain to include in reply
341   - # (optional)
342   -signer_key = $dir/private/tsakey.pem # The TSA private key (optional)
343   -signer_digest = sha256 # Signing digest to use. (Optional)
344   -default_policy = tsa_policy1 # Policy if request did not specify it
345   - # (optional)
346   -other_policies = tsa_policy2, tsa_policy3 # acceptable policies (optional)
347   -digests = sha1, sha256, sha384, sha512 # Acceptable message digests (mandatory)
348   -accuracy = secs:1, millisecs:500, microsecs:100 # (optional)
349   -clock_precision_digits = 0 # number of digits after dot. (optional)
350   -ordering = yes # Is ordering defined for timestamps?
351   - # (optional, default: no)
352   -tsa_name = yes # Must the TSA name be included in the reply?
353   - # (optional, default: no)
354   -ess_cert_id_chain = no # Must the ESS cert id chain be included?
355   - # (optional, default: no)
356   -ess_cert_id_alg = sha1 # algorithm to compute certificate
357   - # identifier (optional, default: sha1)
keys/server.csr deleted
... ... @@ -1,18 +0,0 @@
1   ------BEGIN CERTIFICATE REQUEST-----
2   -MIICzjCCAbYCAQAwTjELMAkGA1UEBhMCQ04xCzAJBgNVBAsMAklUMQ8wDQYDVQQK
3   -DAZHbG9iYWwxDjAMBgNVBAMMBXBybzJkMREwDwYDVQQHDAhaaGVKaWFuZzCCASIw
4   -DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANd6QZzSWnpQN74TzcN8WoUYwutx
5   -mSQB2x8h17VBlVJepFpog1ujWoZUl1xQ7lgPr2DhMHM1qNkroahdI/AZGj2juuC2
6   -1vg2WZ4Wa/8vsICGPvTTqEd7VSpY66ybk0kd7rWFp7naXLBGFVf7mi3RPDW9Y3mO
7   -cyTR7Iwtm1iBhMDS5uczUOzrZ63yd0FA62iizKqckfwXVsYFUJqdG0uUUt88whnt
8   -qAPRKrkuU+Y6I+jo+C6gf7i7RTLz6aI01QYLRMENmJI5NqFcJ4cNKWsLIWY3sDz0
9   -XoyueWl3tHrjiX4TmZM28OZAHl/rKd0lQpQEB0UiHe7At/8xZHLDol6ip4MCAwEA
10   -AaA7MDkGCSqGSIb3DQEJDjEsMCowCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwEAYD
11   -VR0RBAkwB4IFcHJvMmQwDQYJKoZIhvcNAQELBQADggEBAKytMdGU/yLmC5uUUdWd
12   -0dnqloVaCiyPCjWBsv44H2jiVq2UT5nQeiTWJ2hAt6RIsIUyymrY6Flg6ZpCfKaa
13   -yqYNDBzDwGAJAWTHicNyQT/Uxb5rn+6R4qfyBOkFGaPlF9dxCgKRTqaSX5WmWFE6
14   -FzsAiwYcc8fb+ioljnN3NJ7MZLz0n6RU52PCwYDbgC941t3yFa5R1wHgGoK1/93B
15   -2/+IUNWaS8XRGfRe3SUZ2rSTuCgr8J9jfsvsx3qga3KWTpyAxOe3vexKpnhO9Xw0
16   -wDVRApMMmlPVrLrKMNGSCXNaBT0JdTpFn9CJFheJs9jqv+q77T8qpqln9leMgtvF
17   -ql8=
18   ------END CERTIFICATE REQUEST-----
keys/server.key deleted
... ... @@ -1,28 +0,0 @@
1   ------BEGIN PRIVATE KEY-----
2   -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDXekGc0lp6UDe+
3   -E83DfFqFGMLrcZkkAdsfIde1QZVSXqRaaINbo1qGVJdcUO5YD69g4TBzNajZK6Go
4   -XSPwGRo9o7rgttb4NlmeFmv/L7CAhj7006hHe1UqWOusm5NJHe61hae52lywRhVX
5   -+5ot0Tw1vWN5jnMk0eyMLZtYgYTA0ubnM1Ds62et8ndBQOtoosyqnJH8F1bGBVCa
6   -nRtLlFLfPMIZ7agD0Sq5LlPmOiPo6PguoH+4u0Uy8+miNNUGC0TBDZiSOTahXCeH
7   -DSlrCyFmN7A89F6Mrnlpd7R644l+E5mTNvDmQB5f6yndJUKUBAdFIh3uwLf/MWRy
8   -w6JeoqeDAgMBAAECggEAecQ5zdBFlvc7+OsiDUV5tdsfU4PXgbSWykoKpwBPzMN0
9   -5y5GhQOUBXNKMb3+Yr9CYWIASirZpxfz+7vesjDNVmXvFkvcwVmdXSvYjdW6TXcP
10   -nrT5VKPKpeqoC9vC6L/EhMnp1aojVO3V4+ln4FpsRwYmb6vjP7xti22+as6OYZQC
11   -ygC0f0hCWO4t67BrH7lmA+l5KHmfQtl0t7iJ3yXLXz1EMtbVKwoOuNxBnfxTdPuE
12   -a2ke5G8S8nN5ZCe2FpaN+BxQQ4NpRnc0aK5O02EibA5Ix2ItLnXs+MluNC91veVS
13   -WRAbEbvFBwZx624u0NEe5oAIFhS2m4VeKVUmqfdxwQKBgQD/fuE13vXtSV30I4Sj
14   -lZJfr9r+T/gGA6wIna0RhfaXnKDS9SjzFgF6MS2QSRKYzjPCzfGQIxq368NLrEdu
15   -lCLNQF9Z06lVNeuJT84VPYm4P/wheIG7LhNmBHsnkTzYnupFrlB22TnmStDSfuGp
16   -dhlyAUGN91pg/mP/nO1ZrTPpowKBgQDX5ycPD8dOUz2ACoKCGEf37hbcfqBmKd7a
17   -JGYOWaBXPOGZ26KboWoClrStHow2VCnqEx9pewA6+4m0cv4JXiCXa1/uoY9XxHRI
18   -Tz3BSycqAOFTGhz9Z+Nq8Rc9PIFYBHzjyVgrsXiO86TKK33uE7GAqXZGB+MeDOf0
19   -FSb8a8vooQKBgDkR715oKkjRnZH+KQ+dRm/nSSSLWlyFj3TxO4pxgQ6GpwnYR0hd
20   -PwE7YPEc0XGehcNa2z2WCc7Rc/NATUhvAIMWgPYAqI9nFvC6Cc+Gym+Eo14am+fi
21   -t+SO1a+V6qB8htn/wOt7REqjpZePTfrbbX2guDLs8Jw/1rhvJjlkzfa/AoGBAJ+/
22   -RbQsPZDjoE6b+CKgKqf0v2+YNcBB3MVVRzn48N17i4VW8ILstM6Did3KC36rWXP7
23   -gDOAshPyR9p/dx2hSsYeyZV8bt5G2q8iCpR5sdmvWwks+iQ5eRiImGRT33Qrpei4
24   -8ocpwgUrm1OHSJ8ebSjAumVospBqhjmgaP8+F1rhAoGBAIaDv/yhFtEQaldOkK8X
25   -YQACUmt3YflHxWmdlmulVqAOCDH8nV3YYHGFIEatBx2w0OBvxoLtw5HTvEq1pFcF
26   -4cL8ulNQeozLTsGfNeLgIe7NOb6T54QZFVg1+dgePtBIsab59sZE3817j5zmkr0A
27   -DywcIXZFRNuOpQgL2I4JF7PX
28   ------END PRIVATE KEY-----
keys/server.pem deleted
... ... @@ -1,21 +0,0 @@
1   ------BEGIN CERTIFICATE-----
2   -MIIDgzCCAmugAwIBAgIJANTnFdQbb5QkMA0GCSqGSIb3DQEBBQUAMIGFMQswCQYD
3   -VQQGEwJDTjERMA8GA1UECAwIWmhlSmlhbmcxETAPBgNVBAcMCFpoZUppYW5nMQ8w
4   -DQYDVQQKDAZHbG9iYWwxFzAVBgNVBAMMDnBybzJkIFNlY3VyaXR5MRYwFAYDVQQL
5   -DA1JVCBEZXBhcnRtZW50MQ4wDAYDVQQDDAVwcm8yZDAeFw0yMjAyMjIwNjA3MjNa
6   -Fw0yMzAyMjIwNjA3MjNaME4xCzAJBgNVBAYTAkNOMQswCQYDVQQLDAJJVDEPMA0G
7   -A1UECgwGR2xvYmFsMQ4wDAYDVQQDDAVwcm8yZDERMA8GA1UEBwwIWmhlSmlhbmcw
8   -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDXekGc0lp6UDe+E83DfFqF
9   -GMLrcZkkAdsfIde1QZVSXqRaaINbo1qGVJdcUO5YD69g4TBzNajZK6GoXSPwGRo9
10   -o7rgttb4NlmeFmv/L7CAhj7006hHe1UqWOusm5NJHe61hae52lywRhVX+5ot0Tw1
11   -vWN5jnMk0eyMLZtYgYTA0ubnM1Ds62et8ndBQOtoosyqnJH8F1bGBVCanRtLlFLf
12   -PMIZ7agD0Sq5LlPmOiPo6PguoH+4u0Uy8+miNNUGC0TBDZiSOTahXCeHDSlrCyFm
13   -N7A89F6Mrnlpd7R644l+E5mTNvDmQB5f6yndJUKUBAdFIh3uwLf/MWRyw6JeoqeD
14   -AgMBAAGjLDAqMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgXgMBAGA1UdEQQJMAeCBXBy
15   -bzJkMA0GCSqGSIb3DQEBBQUAA4IBAQBmCfF8okV2lCH7KBA4gKjKh7dCKdLiTBWP
16   -q5qHNt2dYOmZAi3CFlgvAqgg30/Ql9pILN+0XJTL7TnJRhvvCZ/eObtCJbmZD/jP
17   -SzmowtCyydPtj/DGmxY+UQZk4KqtRuDGD5LQRU2VYzHJvrf9yEse2uIf+uUetx7b
18   -r2dklvP+H33rMB1k3hswHg2/EmhJxtfvQCLQX8+Ofur/wW8uYKFj3hTabzYfcew3
19   -Uw1/5a+rLHBLAA1SYoviwnoNgiVBxkWkfEH7tsheFapVULltz3vll013Q69RBXVw
20   -K7QloFM0LgoJKM+X65ymUGPGL3F4WvewSOiWyFLQdW43wRlUUNkq
21   ------END CERTIFICATE-----
actions/HttpAction.go renamed to src/actions/HttpAction.go
... ... @@ -4,12 +4,12 @@ import (
4 4 "fmt"
5 5 "github.com/gin-gonic/gin"
6 6 "net/http"
7   - "pro2d/components/db"
8   - "pro2d/components/etcd"
9 7 "pro2d/conf"
10   - "pro2d/models"
11 8 "pro2d/protos/pb"
12   - "pro2d/utils"
  9 + "pro2d/src/components/db"
  10 + "pro2d/src/components/etcd"
  11 + "pro2d/src/models"
  12 + "pro2d/src/utils"
13 13 "reflect"
14 14 "strings"
15 15 )
... ...
actions/RoleAction.go renamed to src/actions/RoleAction.go
... ... @@ -2,11 +2,11 @@ package actions
2 2  
3 3 import (
4 4 "github.com/golang/protobuf/proto"
5   - "pro2d/components/net"
6 5 "pro2d/conf"
7   - "pro2d/models"
8 6 "pro2d/protos/pb"
9   - "pro2d/utils"
  7 + "pro2d/src/components/logger"
  8 + "pro2d/src/components/net"
  9 + "pro2d/src/models"
10 10 )
11 11  
12 12 func HeartRpc(msg *net.MsgPkg) (int32, proto.Message) {
... ... @@ -16,7 +16,7 @@ func HeartRpc(msg *net.MsgPkg) (int32, proto.Message) {
16 16 func CreateRpc(msg *net.MsgPkg) (int32, proto.Message) {
17 17 req := pb.CreateReq{}
18 18 if err := proto.Unmarshal(msg.Body, &req); err != nil {
19   - utils.Sugar.Errorf("CreateRpc err: %v", err)
  19 + logger.Error("CreateRpc err: %v", err)
20 20 return 1, nil
21 21 }
22 22 role := models.RoleExistByUid(req.Uid)
... ... @@ -27,7 +27,7 @@ func CreateRpc(msg *net.MsgPkg) (int32, proto.Message) {
27 27 roleId := conf.SnowFlack.NextVal()
28 28 role = models.NewRole(roleId)
29 29 if _, err := role.Create(); err != nil {
30   - utils.Sugar.Errorf("CreateRpc role create err: %v", err)
  30 + logger.Error("CreateRpc role create err: %v", err)
31 31 return 3, nil
32 32 }
33 33 return 0, nil
... ... @@ -36,7 +36,7 @@ func CreateRpc(msg *net.MsgPkg) (int32, proto.Message) {
36 36 func LoginRpc(msg *net.MsgPkg) (int32, proto.Message) {
37 37 req := pb.LoginReq{}
38 38 if err := proto.Unmarshal(msg.Body, &req); err != nil {
39   - utils.Sugar.Errorf("loginRpc err: %v", err)
  39 + logger.Error("loginRpc err: %v", err)
40 40 return 1, nil
41 41 }
42 42  
... ...
actions/protocode.go renamed to src/actions/protocode.go
1 1 package actions
2 2  
3 3 import (
4   - "pro2d/components/net"
5 4 "pro2d/protos/pb"
  5 + "pro2d/src/components/net"
6 6 )
7 7  
8 8 func init() {
... ...
common/common.go renamed to src/common/common.go
components/db/mongo.go renamed to src/components/db/mongo.go
... ... @@ -8,7 +8,7 @@ import (
8 8 "go.mongodb.org/mongo-driver/mongo/options"
9 9 "go.mongodb.org/mongo-driver/mongo/readpref"
10 10 "go.mongodb.org/mongo-driver/x/bsonx"
11   - "pro2d/utils"
  11 + "pro2d/src/utils"
12 12 "sort"
13 13 "strconv"
14 14 "time"
... ... @@ -38,7 +38,7 @@ func Connect(user, password, host string,port int, MaxNum int, timeOut int) erro
38 38 o.SetMaxPoolSize(uint64(MaxNum))
39 39 // 发起链接
40 40 var err error
41   - MongoClient , err = mongo.Connect(ctx, o)
  41 + MongoClient, err = mongo.Connect(ctx, o)
42 42 if err != nil {
43 43 return err
44 44 }
... ... @@ -89,8 +89,8 @@ func GetBsonM(key string, value interface{}) interface{} {
89 89 func NewMongoColl(key string, schema interface{}) *MgoColl {
90 90 return &MgoColl{
91 91 collection: MongoDatabase.Collection(utils.GetCollName(schema)),
92   - pri: GetBsonM(utils.GetPriKey(schema), key),
93   - schema: schema,
  92 + pri: GetBsonM(utils.GetPriKey(schema), key),
  93 + schema: schema,
94 94 }
95 95 }
96 96  
... ...
src/components/db/redis.go 0 → 100644
... ... @@ -0,0 +1,43 @@
  1 +package db
  2 +
  3 +import (
  4 + "github.com/garyburd/redigo/redis"
  5 + "pro2d/conf"
  6 + "time"
  7 +)
  8 +var RedisPool *redis.Pool
  9 +
  10 +func ConnectRedis(conf *conf.ServerConf) error {
  11 + RedisPool = &redis.Pool{
  12 + //最大活跃连接数,0代表无限
  13 + MaxActive: 888,
  14 + MaxIdle: 20,
  15 + //闲置连接的超时时间
  16 + IdleTimeout: time.Second * 100,
  17 + //定义拨号获得连接的函数
  18 + Dial: func() (redis.Conn, error) {
  19 + option := []redis.DialOption{redis.DialDatabase(conf.RedisConf.DB)}
  20 + if conf.RedisConf.Auth != "" {
  21 + option = append(option, redis.DialPassword(conf.RedisConf.Auth))
  22 + }
  23 + return redis.Dial("tcp",conf.RedisConf.Address, option...)
  24 + },
  25 + }
  26 + return nil
  27 +}
  28 +
  29 +func CloseRedis() {
  30 + RedisPool.Close()
  31 +}
  32 +
  33 +func HKEYS(args ...interface{}) (reply interface{}, err error) {
  34 + conn := RedisPool.Get()
  35 + defer conn.Close()
  36 + return conn.Do("HKEYS", args)
  37 +}
  38 +
  39 +func HMSET(args ...interface{}) (reply interface{}, err error) {
  40 + conn := RedisPool.Get()
  41 + defer conn.Close()
  42 + return conn.Do("HMSET", args)
  43 +}
0 44 \ No newline at end of file
... ...
components/etcd/etcd.go renamed to src/components/etcd/etcd.go
... ... @@ -5,7 +5,7 @@ import (
5 5 "fmt"
6 6 clientv3 "go.etcd.io/etcd/client/v3"
7 7 "pro2d/conf"
8   - "pro2d/utils"
  8 + "pro2d/src/components/logger"
9 9 "time"
10 10 )
11 11  
... ... @@ -17,10 +17,9 @@ func NewEtcdClient(conf *conf.Etcd) *EtcdClient {
17 17 cli, err := clientv3.New(clientv3.Config{
18 18 Endpoints: conf.Endpoints,
19 19 DialTimeout: time.Duration(conf.DialTimeout) * time.Second,
20   - Logger: utils.Logger,
21 20 })
22 21 if err != nil {
23   - utils.Sugar.Errorf("etcd init err: %v", err)
  22 + logger.Error("etcd init err: %v", err)
24 23 return nil
25 24 }
26 25 return &EtcdClient{
... ... @@ -31,7 +30,7 @@ func NewEtcdClient(conf *conf.Etcd) *EtcdClient {
31 30 func (e *EtcdClient)PutWithPrefix(prefix, key, val string) {
32 31 _, err := e.etcd.Put(context.TODO(), fmt.Sprintf("/%s/%s/", prefix, key), val)
33 32 if err != nil {
34   - utils.Sugar.Errorf("PutWithPrefix err: %v", err)
  33 + logger.Error("PutWithPrefix err: %v", err)
35 34 return
36 35 }
37 36 }
... ... @@ -40,19 +39,19 @@ func (e *EtcdClient)PutWithLeasePrefix(prefix, key, val string, ttl int64) error
40 39 lease := clientv3.NewLease(e.etcd)
41 40 leaseResp, err := lease.Grant(context.TODO(), ttl)
42 41 if err != nil {
43   - utils.Sugar.Errorf("PutWithLeasePrefix 设置租约时间失败:%v\n", err)
  42 + logger.Error("PutWithLeasePrefix 设置租约时间失败:%v\n", err)
44 43 return err
45 44 }
46 45  
47 46 _, err = e.etcd.Put(context.TODO(), fmt.Sprintf("/%s/%s/", prefix, key), val, clientv3.WithLease(leaseResp.ID))
48 47 if err != nil {
49   - utils.Sugar.Errorf("PutWithLeasePrefix err: %v", err)
  48 + logger.Error("PutWithLeasePrefix err: %v", err)
50 49 return err
51 50 }
52 51  
53 52 keepRespChan, err := lease.KeepAlive(context.TODO(), leaseResp.ID)
54 53 if err != nil {
55   - utils.Sugar.Errorf("keepalive err: %v", err)
  54 + logger.Error("keepalive err: %v", err)
56 55 return err
57 56 }
58 57 go func() {
... ... @@ -77,7 +76,7 @@ func (e *EtcdClient)Get(key string) map[string]string {
77 76 resp, err := e.etcd.Get(ctx, fmt.Sprintf("/%s/", key))
78 77 cancel()
79 78 if err != nil {
80   - utils.Sugar.Errorf("etcd get key: %s, err: %v", key, err)
  79 + logger.Error("etcd get key: %s, err: %v", key, err)
81 80 return nil
82 81 }
83 82 m := make(map[string]string)
... ... @@ -92,7 +91,7 @@ func (e *EtcdClient)GetByPrefix(prefix string) map[string]string {
92 91 resp, err := e.etcd.Get(ctx, fmt.Sprintf("/%s/", prefix), clientv3.WithPrefix())
93 92 cancel()
94 93 if err != nil {
95   - utils.Sugar.Errorf("etcd get prefix: %s, err: %v", prefix, err)
  94 + logger.Error("etcd get prefix: %s, err: %v", prefix, err)
96 95 return nil
97 96 }
98 97 m := make(map[string]string)
... ...
components/etcd/etcd_test.go renamed to src/components/etcd/etcd_test.go
... ... @@ -6,7 +6,7 @@ import (
6 6 "go.etcd.io/etcd/api/v3/mvccpb"
7 7 clientv3 "go.etcd.io/etcd/client/v3"
8 8 "pro2d/conf"
9   - "pro2d/utils"
  9 + "pro2d/src/components/logger"
10 10 "testing"
11 11 )
12 12  
... ... @@ -14,7 +14,7 @@ func TestEtcdClient_GetByPrefix(t *testing.T) {
14 14 etcd := NewEtcdClient(conf.GlobalConf.Etcd)
15 15 gameInfo := etcd.GetByPrefix(conf.GlobalConf.AccountConf.Name)
16 16 for k, v := range gameInfo {
17   - utils.Sugar.Debugf("game info key: %v val: %v", k, v)
  17 + logger.Debug("game info key: %v val: %v", k, v)
18 18 }
19 19  
20 20 rch := etcd.etcd.Watch(context.Background(), fmt.Sprintf("/%s/", conf.GlobalConf.AccountConf.Name), clientv3.WithPrefix())
... ... @@ -23,9 +23,9 @@ func TestEtcdClient_GetByPrefix(t *testing.T) {
23 23 for _, ev := range wresp.Events {
24 24 switch ev.Type {
25 25 case mvccpb.PUT: //修改或者新增
26   - utils.Sugar.Debugf("account put key: %s val: %s", ev.Kv.Key, ev.Kv.Value)
  26 + logger.Debug("account put key: %s val: %s", ev.Kv.Key, ev.Kv.Value)
27 27 case mvccpb.DELETE: //删除
28   - utils.Sugar.Debugf("account delete key: %s val: %s", ev.Kv.Key, ev.Kv.Value)
  28 + logger.Debug("account delete key: %s val: %s", ev.Kv.Key, ev.Kv.Value)
29 29 }
30 30 }
31 31 }
... ... @@ -36,9 +36,9 @@ func TestEtcdClient_GetByPrefix(t *testing.T) {
36 36 for _, ev := range wresp.Events {
37 37 switch ev.Type {
38 38 case mvccpb.PUT: //修改或者新增
39   - utils.Sugar.Debugf("game put key: %s val: %s", ev.Kv.Key, ev.Kv.Value)
  39 + logger.Debug("game put key: %s val: %s", ev.Kv.Key, ev.Kv.Value)
40 40 case mvccpb.DELETE: //删除
41   - utils.Sugar.Debugf("game delete key: %s val: %s", ev.Kv.Key, ev.Kv.Value)
  41 + logger.Debug("game delete key: %s val: %s", ev.Kv.Key, ev.Kv.Value)
42 42 }
43 43 }
44 44 }
... ...
components/jwt/jwt.go renamed to src/components/jwt/jwt.go
... ... @@ -3,9 +3,9 @@ package jwt
3 3 import (
4 4 "context"
5 5 "fmt"
6   - "pro2d/common"
7 6 "pro2d/conf"
8   - "pro2d/utils"
  7 + "pro2d/src/common"
  8 + "pro2d/src/utils"
9 9 "time"
10 10  
11 11 jwt "github.com/dgrijalva/jwt-go"
... ...
components/jwt/jwt_test.go renamed to src/components/jwt/jwt_test.go
src/components/logger/README.md 0 → 100644
... ... @@ -0,0 +1,143 @@
  1 +# logger
  2 +convenient log package
  3 +
  4 +# 1. 使用说明
  5 +```go
  6 + import "github.com/wonderivan/logger"
  7 +
  8 + // 配置logger,如果不配置时默认为控制台输出,等级为DEBG
  9 + logger.SetLogger(`{"Console": {"level": "DEBG"}`)
  10 + // 配置说明见下文
  11 +
  12 + // 设置完成后,即可在控制台和日志文件app.log中看到如下输出
  13 + logger.Trace("this is Trace")
  14 + logger.Debug("this is Debug")
  15 + logger.Info("this is Info")
  16 + logger.Warn("this is Warn")
  17 + logger.Error("this is Error")
  18 + logger.Crit("this is Critical")
  19 + logger.Alert("this is Alert")
  20 + logger.Emer("this is Emergency")
  21 +```
  22 +输出结果:
  23 +
  24 +![](images/output1.png)
  25 +
  26 +# 2. 日志等级
  27 +
  28 +当前日志输出等级共8种,从0-7对应的等级由高到底,当配置为某个输出等级时,只有大于等于该等级的日志才会输出。不同的输出适配器支持不同的日志等级配置:
  29 +
  30 +| 等级 | 配置 | 释义 | 控制台颜色 |
  31 +| ---- | ---- | ------------------------------------------------ | ---------- |
  32 +| 0 | EMER | 系统级紧急,比如磁盘出错,内存异常,网络不可用等 | 红色底 |
  33 +| 1 | ALRT | 系统级警告,比如数据库访问异常,配置文件出错等 | 紫色 |
  34 +| 2 | CRIT | 系统级危险,比如权限出错,访问异常等 | 蓝色 |
  35 +| 3 | EROR | 用户级错误 | 红色 |
  36 +| 4 | WARN | 用户级警告 | 黄色 |
  37 +| 5 | INFO | 用户级重要 | 天蓝色 |
  38 +| 6 | DEBG | 用户级调试 | 绿色 |
  39 +| 7 | TRAC | 用户级基本输出 | 绿色 |
  40 +
  41 +
  42 +# 3. 配置说明
  43 +logger当前支持控制台、文件、网络3种方式适配器输出,可以通过各自的参数进行设置,该logger支持多个方式同时输出,如果未配置某项适配器时,则不初始化也不会输出到该适配器。
  44 +
  45 +通过调用logger.SetLogger(config string)方法设置参数,config支持json配置,也支持指定内容为json配置的文件路径,例如:
  46 +```go
  47 + // 通过配置参数直接配置
  48 + logger.SetLogger(`{"Console": {"level": "DEBG"}}`)
  49 + // 通过配置文件配置
  50 + logger.SetLogger("/home/log.json")
  51 +
  52 +```
  53 +
  54 +```json
  55 +{
  56 + "TimeFormat":"2006-01-02 15:04:05", // 输出日志开头时间格式
  57 + "Console": { // 控制台日志配置
  58 + "level": "TRAC", // 控制台日志输出等级
  59 + "color": true // 控制台日志颜色开关
  60 + },
  61 + "File": { // 文件日志配置
  62 + "filename": "app.log", // 初始日志文件名
  63 + "level": "TRAC", // 日志文件日志输出等级
  64 + "daily": true, // 跨天后是否创建新日志文件,当append=true时有效
  65 + "maxlines": 1000000, // 日志文件最大行数,当append=true时有效
  66 + "maxsize": 1, // 日志文件最大大小,当append=true时有效
  67 + "maxdays": -1, // 日志文件有效期
  68 + "append": true, // 是否支持日志追加
  69 + "permit": "0660" // 新创建的日志文件权限属性
  70 + },
  71 + "Conn": { // 网络日志配置
  72 + "net":"tcp", // 日志传输模式
  73 + "addr":"10.1.55.10:1024", // 日志接收服务器
  74 + "level": "Warn", // 网络日志输出等级
  75 + "reconnect":true, // 网络断开后是否重连
  76 + "reconnectOnMsg":false, // 发送完每条消息后是否断开网络
  77 + }
  78 +}
  79 +```
  80 +
  81 +- 时间格式
  82 +
  83 +| 时间类型 | 时间格式 |
  84 +| ------------ | ----------------------------------------- |
  85 +| ANSIC | "Mon Jan _2 15:04:05 2006" |
  86 +| UnixDate | "Mon Jan _2 15:04:05 MST 2006" |
  87 +| RubyDate | "Mon Jan 02 15:04:05 -0700 2006" |
  88 +| RFC822 | "02 Jan 06 15:04 MST" |
  89 +| RFC822Z | "02 Jan 06 15:04 -0700" |
  90 +| RFC850 | "Monday, 02-Jan-06 15:04:05 MST" |
  91 +| RFC1123 | "Mon, 02 Jan 2006 15:04:05 MST" |
  92 +| RFC1123Z | "Mon, 02 Jan 2006 15:04:05 -0700" |
  93 +| RFC3339 | "2006-01-02T15:04:05Z07:00" |
  94 +| RFC3339Nano | "2006-01-02T15:04:05.999999999Z07:00" |
  95 +| Kitchen | "3:04PM" |
  96 +| Stamp | "Jan _2 15:04:05" |
  97 +| StampMilli | "Jan _2 15:04:05.000" |
  98 +| StampMicro | "Jan _2 15:04:05.000000" |
  99 +| StampNano | "Jan _2 15:04:05.000000000" |
  100 +| RFC3339Nano1 | "2006-01-02 15:04:05.999999999 -0700 MST" |
  101 +| DEFAULT | "2006-01-02 15:04:05" |
  102 +
  103 +- 时间格式打印:
  104 +```
  105 +========RFC1123Z time format========
  106 +Thu, 02 Aug 2018 18:48:04 +0800 [DEBG] [github.com/wonderivan/logger/log_test.go:115] Debug RFC1123Z
  107 +========Stamp time format========
  108 +Aug 2 18:48:04 [DEBG] [github.com/wonderivan/logger/log_test.go:115] Debug Stamp
  109 +========StampMilli time format========
  110 +Aug 2 18:48:04.489 [DEBG] [github.com/wonderivan/logger/log_test.go:115] Debug StampMilli
  111 +========StampNano time format========
  112 +Aug 2 18:48:04.490002155 [DEBG] [github.com/wonderivan/logger/log_test.go:115] Debug StampNano
  113 +========RubyDate time format========
  114 +Thu Aug 02 18:48:04 +0800 2018 [DEBG] [github.com/wonderivan/logger/log_test.go:115] Debug RubyDate
  115 +========RFC822 time format========
  116 +02 Aug 18 18:48 CST [DEBG] [github.com/wonderivan/logger/log_test.go:115] Debug RFC822
  117 +========RFC822Z time format========
  118 +02 Aug 18 18:48 +0800 [DEBG] [github.com/wonderivan/logger/log_test.go:115] Debug RFC822Z
  119 +========RFC1123 time format========
  120 +Thu, 02 Aug 2018 18:48:04 CST [DEBG] [github.com/wonderivan/logger/log_test.go:115] Debug RFC1123
  121 +========RFC3339 time format========
  122 +2018-08-02T18:48:04+08:00 [DEBG] [github.com/wonderivan/logger/log_test.go:115] Debug RFC3339
  123 +========RFC3339Nano time format========
  124 +2018-08-02T18:48:04.490377325+08:00 [DEBG] [github.com/wonderivan/logger/log_test.go:115] Debug RFC3339Nano
  125 +========ANSIC time format========
  126 +Thu Aug 2 18:48:04 2018 [DEBG] [github.com/wonderivan/logger/log_test.go:115] Debug ANSIC
  127 +========UnixDate time format========
  128 +Thu Aug 2 18:48:04 CST 2018 [DEBG] [github.com/wonderivan/logger/log_test.go:115] Debug UnixDate
  129 +========RFC850 time format========
  130 +Thursday, 02-Aug-18 18:48:04 CST [DEBG] [github.com/wonderivan/logger/log_test.go:115] Debug RFC850
  131 +========Kitchen time format========
  132 +6:48PM [DEBG] [github.com/wonderivan/logger/log_test.go:115] Debug Kitchen
  133 +========StampMicro time format========
  134 +Aug 2 18:48:04.490662 [DEBG] [github.com/wonderivan/logger/log_test.go:115] Debug StampMicro
  135 +```
  136 +
  137 +# 4. 其他
  138 +
  139 +1. logger默认是控制台输出,输出等级为DEBG,默认是支持颜色区分的。
  140 +2. 日志文件append为true时,当写入的日志文件发生跨天(daily为true)或超过最大限制时,会创建一个新文件,原有文件格式被重命名为: ****.xxxx-xx-xx.xxx.xxx 格式,例如:当向app.log写入日志时,触发了创建新文件操作,则将app.log重命名为 app.2018-01-01.001.log, 如果此时app.2018-01-01.001.log已经存在,则将刚才的app.log重命名为 app.2018-01-01.002.log,以此类推。
  141 +3. logger package默认初始化了全局的defaultLogger,直接调用logger包的Debug方法时,会默认调用defaultLogger.Debug,所以普通调用时,仅需要import logger即可使用。
  142 +4. 网络配置中的reconnectOnMsg为每条消息都重连一次网络日志中心,适用于写日志频率极低的情况下的服务调用,避免长时间连接,占用资源。但强烈不建议普通使用时设置为true,这将会导致调用方反复的网络重连,极大增加资源消耗和延迟。
  143 +5. conn网络输出适配器经过ELK集成环境的测试验证,通过该方式发送的日志,能够正常通过Elecsearch和Kibana检索和分析
0 144 \ No newline at end of file
... ...
src/components/logger/conn.go 0 → 100644
... ... @@ -0,0 +1,115 @@
  1 +package logger
  2 +
  3 +import (
  4 + "encoding/json"
  5 + "fmt"
  6 + "io"
  7 + "net"
  8 + "strings"
  9 + "sync"
  10 + "time"
  11 +)
  12 +
  13 +type connLogger struct {
  14 + sync.Mutex
  15 + innerWriter io.WriteCloser
  16 + Net string `json:"net"`
  17 + Addr string `json:"addr"`
  18 + Level string `json:"level"`
  19 + LogLevel int
  20 + illNetFlag bool //网络异常标记
  21 +}
  22 +
  23 +func (c *connLogger) Init(jsonConfig string, appName string) error {
  24 + if len(jsonConfig) == 0 {
  25 + return nil
  26 + }
  27 + //fmt.Printf("consoleWriter Init:%s\n", jsonConfig)
  28 + err := json.Unmarshal([]byte(jsonConfig), c)
  29 + if err != nil {
  30 + return err
  31 + }
  32 + if l, ok := LevelMap[c.Level]; ok {
  33 + c.LogLevel = l
  34 + }
  35 + if c.innerWriter != nil {
  36 + c.innerWriter.Close()
  37 + c.innerWriter = nil
  38 + }
  39 +
  40 + go func() {
  41 + for {
  42 + c.connect()
  43 + time.Sleep(10*time.Millisecond)
  44 + }
  45 + }()
  46 +
  47 + return nil
  48 +}
  49 +
  50 +func (c *connLogger) LogWrite(when time.Time, msgText interface{}, level int) (err error) {
  51 + if level > c.LogLevel {
  52 + return nil
  53 + }
  54 +
  55 + msg, ok := msgText.(*loginfo)
  56 + if !ok {
  57 + return
  58 + }
  59 +
  60 + if c.innerWriter != nil {
  61 + err = c.println(when, msg)
  62 + //网络异常,通知处理网络的go程自动重连
  63 + if err != nil {
  64 + c.innerWriter.Close()
  65 + c.innerWriter = nil
  66 + }
  67 + }
  68 +
  69 + return
  70 +}
  71 +
  72 +func (c *connLogger) Destroy() {
  73 + if c.innerWriter != nil {
  74 + c.innerWriter.Close()
  75 + }
  76 +}
  77 +
  78 +func (c *connLogger) connect() error {
  79 + if c.innerWriter != nil {
  80 + return nil
  81 + }
  82 + addrs := strings.Split(c.Addr, ";")
  83 + for _, addr := range addrs {
  84 + conn, err := net.DialTimeout(c.Net, addr, 1 * time.Second)
  85 + if err != nil {
  86 + fmt.Printf("net.Dial error:%v\n", err)
  87 + //continue
  88 + return err
  89 + }
  90 +
  91 + if tcpConn, ok := conn.(*net.TCPConn); ok {
  92 + tcpConn.SetKeepAlive(true)
  93 + }
  94 + c.innerWriter = conn
  95 + return nil
  96 + }
  97 + return fmt.Errorf("hava no valid logs service addr:%v", c.Addr)
  98 +}
  99 +
  100 +func (c *connLogger) println(when time.Time, msg *loginfo) error {
  101 + c.Lock()
  102 + defer c.Unlock()
  103 + ss, err := json.Marshal(msg)
  104 + if err != nil {
  105 + return err
  106 + }
  107 + _, err = c.innerWriter.Write(append(ss, '\n'))
  108 +
  109 + //返回err,解决日志系统网络异常后的自动重连
  110 + return err
  111 +}
  112 +
  113 +func init() {
  114 + Register(AdapterConn, &connLogger{LogLevel: LevelTrace})
  115 +}
... ...
src/components/logger/console.go 0 → 100644
... ... @@ -0,0 +1,92 @@
  1 +package logger
  2 +
  3 +import (
  4 + "encoding/json"
  5 + //"fmt"
  6 + "os"
  7 + "runtime"
  8 + "sync"
  9 + "time"
  10 +)
  11 +
  12 +type brush func(string) string
  13 +
  14 +func newBrush(color string) brush {
  15 + pre := "\033["
  16 + reset := "\033[0m"
  17 + return func(text string) string {
  18 + return pre + color + "m" + text + reset
  19 + }
  20 +}
  21 +
  22 +//鉴于终端的通常使用习惯,一般白色和黑色字体是不可行的,所以30,37不可用,
  23 +var colors = []brush{
  24 + newBrush("1;41"), // Emergency 红色底
  25 + newBrush("1;35"), // Alert 紫色
  26 + newBrush("1;34"), // Critical 蓝色
  27 + newBrush("1;31"), // Error 红色
  28 + newBrush("1;33"), // Warn 黄色
  29 + newBrush("1;36"), // Informational 天蓝色
  30 + newBrush("1;32"), // Debug 绿色
  31 + newBrush("1;32"), // Trace 绿色
  32 +}
  33 +
  34 +type consoleLogger struct {
  35 + sync.Mutex
  36 + Level string `json:"level"`
  37 + Colorful bool `json:"color"`
  38 + LogLevel int
  39 +}
  40 +
  41 +func (c *consoleLogger) Init(jsonConfig string, appName string) error {
  42 + if len(jsonConfig) == 0 {
  43 + return nil
  44 + }
  45 + if jsonConfig != "{}" {
  46 + //fmt.Fprintf(os.Stdout, "consoleLogger Init:%s\n", jsonConfig)
  47 + }
  48 +
  49 + err := json.Unmarshal([]byte(jsonConfig), c)
  50 + if runtime.GOOS == "windows" {
  51 + c.Colorful = false
  52 + }
  53 +
  54 + if l, ok := LevelMap[c.Level]; ok {
  55 + c.LogLevel = l
  56 + return nil
  57 + }
  58 +
  59 + return err
  60 +}
  61 +
  62 +func (c *consoleLogger) LogWrite(when time.Time, msgText interface{}, level int) error {
  63 + if level > c.LogLevel {
  64 + return nil
  65 + }
  66 + msg, ok := msgText.(string)
  67 + if !ok {
  68 + return nil
  69 + }
  70 + if c.Colorful {
  71 + msg = colors[level](msg)
  72 + }
  73 + c.printlnConsole(when, msg)
  74 + return nil
  75 +}
  76 +
  77 +func (c *consoleLogger) Destroy() {
  78 +
  79 +}
  80 +
  81 +func (c *consoleLogger) printlnConsole(when time.Time, msg string) {
  82 + c.Lock()
  83 + defer c.Unlock()
  84 + os.Stdout.Write(append([]byte(msg), '\n'))
  85 +}
  86 +
  87 +func init() {
  88 + Register(AdapterConsole, &consoleLogger{
  89 + LogLevel: LevelDebug,
  90 + Colorful: runtime.GOOS != "windows",
  91 + })
  92 +}
... ...
src/components/logger/file.go 0 → 100644
... ... @@ -0,0 +1,288 @@
  1 +package logger
  2 +
  3 +import (
  4 + "bytes"
  5 + "encoding/json"
  6 + "errors"
  7 + "fmt"
  8 + "io"
  9 + "os"
  10 + "path/filepath"
  11 + "strconv"
  12 + "strings"
  13 + "sync"
  14 + "time"
  15 +)
  16 +
  17 +type fileLogger struct {
  18 + sync.RWMutex
  19 + fileWriter *os.File
  20 +
  21 + Filename string //`json:"filename"`
  22 + Append bool `json:"append"`
  23 + MaxLines int `json:"maxlines"`
  24 + MaxSize int `json:"maxsize"`
  25 + Daily bool `json:"daily"`
  26 + MaxDays int64 `json:"maxdays"`
  27 + Level string `json:"level"`
  28 + PermitMask string `json:"permit"`
  29 +
  30 + LogLevel int
  31 + maxSizeCurSize int
  32 + maxLinesCurLines int
  33 + dailyOpenDate int
  34 + dailyOpenTime time.Time
  35 + fileNameOnly, suffix string
  36 +}
  37 +
  38 +// Init file logger with json config.
  39 +// jsonConfig like:
  40 +// {
  41 +// "filename":"log/app.log",
  42 +// "maxlines":10000,
  43 +// "maxsize":1024,
  44 +// "daily":true,
  45 +// "maxdays":15,
  46 +// "rotate":true,
  47 +// "permit":"0600"
  48 +// }
  49 +func (f *fileLogger) Init(jsonConfig string, appName string) error {
  50 + //fmt.Printf("fileLogger Init:%s\n", jsonConfig)
  51 + if len(jsonConfig) == 0 {
  52 + return nil
  53 + }
  54 + err := json.Unmarshal([]byte(jsonConfig), f)
  55 + if err != nil {
  56 + return err
  57 + }
  58 + f.Filename = appName
  59 + if len(f.Filename) == 0 {
  60 + return errors.New("jsonconfig must have filename")
  61 + }
  62 + f.suffix = filepath.Ext(f.Filename)
  63 + f.fileNameOnly = strings.TrimSuffix(f.Filename, f.suffix)
  64 + f.MaxSize *= 1024 * 1024 // 将单位转换成MB
  65 + if f.suffix == "" {
  66 + f.suffix = ".log"
  67 + f.Filename += f.suffix
  68 + }
  69 + if l, ok := LevelMap[f.Level]; ok {
  70 + f.LogLevel = l
  71 + }
  72 + err = f.newFile()
  73 + return err
  74 +}
  75 +
  76 +func (f *fileLogger) needCreateFresh(size int, day int) bool {
  77 + return (f.MaxLines > 0 && f.maxLinesCurLines >= f.MaxLines) ||
  78 + (f.MaxSize > 0 && f.maxSizeCurSize+size >= f.MaxSize) ||
  79 + (f.Daily && day != f.dailyOpenDate)
  80 +
  81 +}
  82 +
  83 +// WriteMsg write logger message into file.
  84 +func (f *fileLogger) LogWrite(when time.Time, msgText interface{}, level int) error {
  85 + msg, ok := msgText.(string)
  86 + if !ok {
  87 + return nil
  88 + }
  89 + if level > f.LogLevel {
  90 + return nil
  91 + }
  92 +
  93 + day := when.Day()
  94 + msg += "\n"
  95 + if f.Append {
  96 + f.RLock()
  97 + if f.needCreateFresh(len(msg), day) {
  98 + f.RUnlock()
  99 + f.Lock()
  100 + if f.needCreateFresh(len(msg), day) {
  101 + if err := f.createFreshFile(when); err != nil {
  102 + fmt.Fprintf(os.Stdout, "createFreshFile(%q): %s\n", f.Filename, err)
  103 + }
  104 + }
  105 + f.Unlock()
  106 + } else {
  107 + f.RUnlock()
  108 + }
  109 + }
  110 +
  111 + f.Lock()
  112 + _, err := f.fileWriter.Write([]byte(msg))
  113 + if err == nil {
  114 + f.maxLinesCurLines++
  115 + f.maxSizeCurSize += len(msg)
  116 + }
  117 + f.Unlock()
  118 + return err
  119 +}
  120 +
  121 +func (f *fileLogger) createLogFile() (*os.File, error) {
  122 + // Open the log file
  123 + perm, err := strconv.ParseInt(f.PermitMask, 8, 64)
  124 + if err != nil {
  125 + return nil, err
  126 + }
  127 + fd, err := os.OpenFile(f.Filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE, os.FileMode(perm))
  128 + if err == nil {
  129 + // Make sure file perm is user set perm cause of `os.OpenFile` will obey umask
  130 + os.Chmod(f.Filename, os.FileMode(perm))
  131 + }
  132 + return fd, err
  133 +}
  134 +
  135 +func (f *fileLogger) newFile() error {
  136 + file, err := f.createLogFile()
  137 + if err != nil {
  138 + return err
  139 + }
  140 + if f.fileWriter != nil {
  141 + f.fileWriter.Close()
  142 + }
  143 + f.fileWriter = file
  144 +
  145 + fInfo, err := file.Stat()
  146 + if err != nil {
  147 + return fmt.Errorf("get stat err: %s", err)
  148 + }
  149 + f.maxSizeCurSize = int(fInfo.Size())
  150 + f.dailyOpenTime = time.Now()
  151 + f.dailyOpenDate = f.dailyOpenTime.Day()
  152 + f.maxLinesCurLines = 0
  153 + if f.maxSizeCurSize > 0 {
  154 + count, err := f.lines()
  155 + if err != nil {
  156 + return err
  157 + }
  158 + f.maxLinesCurLines = count
  159 + }
  160 + return nil
  161 +}
  162 +
  163 +func (f *fileLogger) lines() (int, error) {
  164 + fd, err := os.Open(f.Filename)
  165 + if err != nil {
  166 + return 0, err
  167 + }
  168 + defer fd.Close()
  169 +
  170 + buf := make([]byte, 32768) // 32k
  171 + count := 0
  172 + lineSep := []byte{'\n'}
  173 +
  174 + for {
  175 + c, err := fd.Read(buf)
  176 + if err != nil && err != io.EOF {
  177 + return count, err
  178 + }
  179 +
  180 + count += bytes.Count(buf[:c], lineSep)
  181 +
  182 + if err == io.EOF {
  183 + break
  184 + }
  185 + }
  186 +
  187 + return count, nil
  188 +}
  189 +
  190 +// new file name like xx.2013-01-01.001.log
  191 +func (f *fileLogger) createFreshFile(logTime time.Time) error {
  192 + // file exists
  193 + // Find the next available number
  194 + num := 1
  195 + fName := ""
  196 + rotatePerm, err := strconv.ParseInt(f.PermitMask, 8, 64)
  197 + if err != nil {
  198 + return err
  199 + }
  200 +
  201 + _, err = os.Lstat(f.Filename)
  202 + if err != nil {
  203 + // 初始日志文件不存在,无需创建新文件
  204 + goto RESTART_LOGGER
  205 + }
  206 + // 日期变了, 说明跨天,重命名时需要保存为昨天的日期
  207 + if f.dailyOpenDate != logTime.Day() {
  208 + for ; err == nil && num <= 999; num++ {
  209 + fName = f.fileNameOnly + fmt.Sprintf(".%s.%03d%s", f.dailyOpenTime.Format("2006-01-02"), num, f.suffix)
  210 + _, err = os.Lstat(fName)
  211 + }
  212 + } else { //如果仅仅是文件大小或行数达到了限制,仅仅变更后缀序号即可
  213 + for ; err == nil && num <= 999; num++ {
  214 + fName = f.fileNameOnly + fmt.Sprintf(".%s.%03d%s", logTime.Format("2006-01-02"), num, f.suffix)
  215 + _, err = os.Lstat(fName)
  216 + }
  217 + }
  218 +
  219 + if err == nil {
  220 + return fmt.Errorf("Cannot find free log number to rename %s", f.Filename)
  221 + }
  222 + f.fileWriter.Close()
  223 +
  224 + // 当创建新文件标记为true时
  225 + // 当日志文件超过最大限制行
  226 + // 当日志文件超过最大限制字节
  227 + // 当日志文件隔天更新标记为true时
  228 + // 将旧文件重命名,然后创建新文件
  229 + err = os.Rename(f.Filename, fName)
  230 + if err != nil {
  231 + fmt.Fprintf(os.Stdout, "os.Rename %s to %s err:%s\n", f.Filename, fName, err.Error())
  232 + goto RESTART_LOGGER
  233 + }
  234 +
  235 + err = os.Chmod(fName, os.FileMode(rotatePerm))
  236 +
  237 +RESTART_LOGGER:
  238 +
  239 + startLoggerErr := f.newFile()
  240 + go f.deleteOldLog()
  241 +
  242 + if startLoggerErr != nil {
  243 + return fmt.Errorf("Rotate StartLogger: %s", startLoggerErr)
  244 + }
  245 + if err != nil {
  246 + return fmt.Errorf("Rotate: %s", err)
  247 + }
  248 + return nil
  249 +}
  250 +
  251 +func (f *fileLogger) deleteOldLog() {
  252 + dir := filepath.Dir(f.Filename)
  253 + filepath.Walk(dir, func(path string, info os.FileInfo, err error) (returnErr error) {
  254 + defer func() {
  255 + if r := recover(); r != nil {
  256 + fmt.Fprintf(os.Stdout, "Unable to delete old log '%s', error: %v\n", path, r)
  257 + }
  258 + }()
  259 +
  260 + if info == nil {
  261 + return
  262 + }
  263 +
  264 + if f.MaxDays != -1 && !info.IsDir() && info.ModTime().Add(24*time.Hour*time.Duration(f.MaxDays)).Before(time.Now()) {
  265 + if strings.HasPrefix(filepath.Base(path), filepath.Base(f.fileNameOnly)) &&
  266 + strings.HasSuffix(filepath.Base(path), f.suffix) {
  267 + os.Remove(path)
  268 + }
  269 + }
  270 + return
  271 + })
  272 +}
  273 +
  274 +func (f *fileLogger) Destroy() {
  275 + f.fileWriter.Close()
  276 +}
  277 +
  278 +func init() {
  279 + Register(AdapterFile, &fileLogger{
  280 + Daily: true,
  281 + MaxDays: 7,
  282 + Append: true,
  283 + LogLevel: LevelDebug,
  284 + PermitMask: "0777",
  285 + MaxLines: 10,
  286 + MaxSize: 10 * 1024 * 1024,
  287 + })
  288 +}
... ...
src/components/logger/log.go 0 → 100644
... ... @@ -0,0 +1,472 @@
  1 +package logger
  2 +
  3 +import (
  4 + "encoding/json"
  5 + "fmt"
  6 + "io/ioutil"
  7 + "os"
  8 + "runtime"
  9 + "strings"
  10 + "sync"
  11 + "time"
  12 +)
  13 +
  14 +// 默认日志输出
  15 +var defaultLogger *LocalLogger
  16 +var appName = "app"
  17 +
  18 +// 日志等级,从0-7,日优先级由高到低
  19 +const (
  20 + LevelEmergency = iota // 系统级紧急,比如磁盘出错,内存异常,网络不可用等
  21 + LevelAlert // 系统级警告,比如数据库访问异常,配置文件出错等
  22 + LevelCritical // 系统级危险,比如权限出错,访问异常等
  23 + LevelError // 用户级错误
  24 + LevelWarning // 用户级警告
  25 + LevelInformational // 用户级信息
  26 + LevelDebug // 用户级调试
  27 + LevelTrace // 用户级基本输出
  28 +)
  29 +
  30 +// 日志等级和描述映射关系
  31 +var LevelMap = map[string]int{
  32 + "EMER": LevelEmergency,
  33 + "ALRT": LevelAlert,
  34 + "CRIT": LevelCritical,
  35 + "EROR": LevelError,
  36 + "WARN": LevelWarning,
  37 + "INFO": LevelInformational,
  38 + "DEBG": LevelDebug,
  39 + "TRAC": LevelTrace,
  40 +}
  41 +
  42 +// 注册实现的适配器, 当前支持控制台,文件和网络输出
  43 +var adapters = make(map[string]Logger)
  44 +
  45 +// 日志记录等级字段
  46 +var levelPrefix = [LevelTrace + 1]string{
  47 + "EMER",
  48 + "ALRT",
  49 + "CRIT",
  50 + "EROR",
  51 + "WARN",
  52 + "INFO",
  53 + "DEBG",
  54 + "TRAC",
  55 +}
  56 +
  57 +const (
  58 + logTimeDefaultFormat = "2006-01-02 15:04:05" // 日志输出默认格式
  59 + AdapterConsole = "console" // 控制台输出配置项
  60 + AdapterFile = "file" // 文件输出配置项
  61 + AdapterConn = "conn" // 网络输出配置项
  62 +)
  63 +
  64 +// log provider interface
  65 +type Logger interface {
  66 + Init(config string, appName string) error
  67 + LogWrite(when time.Time, msg interface{}, level int) error
  68 + Destroy()
  69 +}
  70 +
  71 +// 日志输出适配器注册,log需要实现Init,LogWrite,Destroy方法
  72 +func Register(name string, log Logger) {
  73 + if log == nil {
  74 + panic("logs: Register provide is nil")
  75 + }
  76 + if _, ok := adapters[name]; ok {
  77 + panic("logs: Register called twice for provider " + name)
  78 + }
  79 + adapters[name] = log
  80 +}
  81 +
  82 +type loginfo struct {
  83 + Time string
  84 + Level string
  85 + Path string
  86 + Name string
  87 + Content string
  88 +}
  89 +
  90 +type nameLogger struct {
  91 + Logger
  92 + name string
  93 + config string
  94 +}
  95 +
  96 +type LocalLogger struct {
  97 + lock sync.RWMutex
  98 + init bool
  99 + outputs []*nameLogger
  100 + appName string
  101 + callDepth int
  102 + timeFormat string
  103 + usePath string
  104 +}
  105 +
  106 +func NewLogger(depth ...int) *LocalLogger {
  107 + dep := append(depth, 2)[0]
  108 + l := new(LocalLogger)
  109 + // appName用于记录网络传输时标记的程序发送方,
  110 + // 通过环境变量APPSN进行设置,默认为NONE,此时无法通过网络日志检索区分不同服务发送方
  111 + appSn := os.Getenv("APPSN")
  112 + if appSn == "" {
  113 + appSn = "NONE"
  114 + }
  115 + l.appName = "[" + appSn + "]"
  116 + l.callDepth = dep
  117 + l.SetLogger(AdapterConsole)
  118 + l.timeFormat = logTimeDefaultFormat
  119 + return l
  120 +}
  121 +
  122 +//配置文件
  123 +type logConfig struct {
  124 + TimeFormat string `json:"TimeFormat"`
  125 + Console *consoleLogger `json:"Console,omitempty"`
  126 + File *fileLogger `json:"File,omitempty"`
  127 + Conn *connLogger `json:"Conn,omitempty"`
  128 +}
  129 +
  130 +func init() {
  131 + defaultLogger = NewLogger(3)
  132 +}
  133 +
  134 +func (this *LocalLogger) SetLogger(adapterName string, configs ...string) error {
  135 + this.lock.Lock()
  136 + defer this.lock.Unlock()
  137 +
  138 + if !this.init {
  139 + this.outputs = []*nameLogger{}
  140 + this.init = true
  141 + }
  142 +
  143 + config := append(configs, "{}")[0]
  144 + var num int = -1
  145 + var i int
  146 + var l *nameLogger
  147 + for i, l = range this.outputs {
  148 + if l.name == adapterName {
  149 + if l.config == config {
  150 + //配置没有变动,不重新设置
  151 + return fmt.Errorf("you have set same config for this adaptername %s", adapterName)
  152 + }
  153 + l.Logger.Destroy()
  154 + num = i
  155 + break
  156 + }
  157 + }
  158 + logger, ok := adapters[adapterName]
  159 + if !ok {
  160 + return fmt.Errorf("unknown adaptername %s (forgotten Register?)", adapterName)
  161 + }
  162 +
  163 + err := logger.Init(config, appName)
  164 + if err != nil {
  165 + fmt.Fprintf(os.Stdout, "logger Init <%s> err:%v, %s output ignore!\n",
  166 + adapterName, err, adapterName)
  167 + return err
  168 + }
  169 + if num >= 0 {
  170 + this.outputs[i] = &nameLogger{name: adapterName, Logger: logger, config: config}
  171 + return nil
  172 + }
  173 + this.outputs = append(this.outputs, &nameLogger{name: adapterName, Logger: logger, config: config})
  174 + return nil
  175 +}
  176 +
  177 +func (this *LocalLogger) DelLogger(adapterName string) error {
  178 + this.lock.Lock()
  179 + defer this.lock.Unlock()
  180 + outputs := []*nameLogger{}
  181 + for _, lg := range this.outputs {
  182 + if lg.name == adapterName {
  183 + lg.Destroy()
  184 + } else {
  185 + outputs = append(outputs, lg)
  186 + }
  187 + }
  188 + if len(outputs) == len(this.outputs) {
  189 + return fmt.Errorf("logs: unknown adaptername %s (forgotten Register?)", adapterName)
  190 + }
  191 + this.outputs = outputs
  192 + return nil
  193 +}
  194 +
  195 +// 设置日志起始路径
  196 +func (this *LocalLogger) SetLogPathTrim(trimPath string) {
  197 + this.usePath = trimPath
  198 +}
  199 +
  200 +func (this *LocalLogger) writeToLoggers(when time.Time, msg *loginfo, level int) {
  201 + this.lock.RLock()
  202 + defer this.lock.RUnlock()
  203 + for _, l := range this.outputs {
  204 + if l.name == AdapterConn {
  205 + //网络日志,使用json格式发送,此处使用结构体,用于类似ElasticSearch功能检索
  206 + err := l.LogWrite(when, msg, level)
  207 + if err != nil {
  208 + fmt.Fprintf(os.Stdout, "unable to WriteMsg to adapter:%v,error:%v\n", l.name, err)
  209 + }
  210 + continue
  211 + }
  212 +
  213 + msgStr := when.Format(this.timeFormat) + " [" + msg.Level + "] " + "[" + msg.Path + "] " + msg.Content
  214 + err := l.LogWrite(when, msgStr, level)
  215 + if err != nil {
  216 + fmt.Fprintf(os.Stdout, "unable to WriteMsg to adapter:%v,error:%v\n", l.name, err)
  217 + }
  218 + }
  219 +}
  220 +
  221 +func (this *LocalLogger) writeMsg(logLevel int, msg string, v ...interface{}) error {
  222 + if !this.init {
  223 + this.SetLogger(AdapterConsole)
  224 + }
  225 + msgSt := new(loginfo)
  226 + src := ""
  227 + if len(v) > 0 {
  228 + msg = fmt.Sprintf(msg, v...)
  229 + }
  230 + when := time.Now()
  231 + _, file, lineno, ok := runtime.Caller(this.callDepth)
  232 + var strim string = "src/"
  233 + if this.usePath != "" {
  234 + strim = this.usePath
  235 + }
  236 + if ok {
  237 +
  238 + src = strings.Replace(
  239 + fmt.Sprintf("%s:%d", stringTrim(file, strim), lineno), "%2e", ".", -1)
  240 + }
  241 +
  242 + msgSt.Level = levelPrefix[logLevel]
  243 + msgSt.Path = src
  244 + msgSt.Content = msg
  245 + msgSt.Name = this.appName
  246 + msgSt.Time = when.Format(this.timeFormat)
  247 + this.writeToLoggers(when, msgSt, logLevel)
  248 +
  249 + return nil
  250 +}
  251 +
  252 +func (this *LocalLogger) Fatal(format string, args ...interface{}) {
  253 + this.Emer("###Exec Panic:"+format, args...)
  254 + os.Exit(1)
  255 +}
  256 +
  257 +func (this *LocalLogger) Panic(format string, args ...interface{}) {
  258 + this.Emer("###Exec Panic:"+format, args...)
  259 + panic(fmt.Sprintf(format, args...))
  260 +}
  261 +
  262 +// Emer Log EMERGENCY level message.
  263 +func (this *LocalLogger) Emer(format string, v ...interface{}) {
  264 + this.writeMsg(LevelEmergency, format, v...)
  265 +}
  266 +
  267 +// Alert Log ALERT level message.
  268 +func (this *LocalLogger) Alert(format string, v ...interface{}) {
  269 + this.writeMsg(LevelAlert, format, v...)
  270 +}
  271 +
  272 +// Crit Log CRITICAL level message.
  273 +func (this *LocalLogger) Crit(format string, v ...interface{}) {
  274 + this.writeMsg(LevelCritical, format, v...)
  275 +}
  276 +
  277 +// Error Log ERROR level message.
  278 +func (this *LocalLogger) Error(format string, v ...interface{}) {
  279 + this.writeMsg(LevelError, format, v...)
  280 +}
  281 +
  282 +// Warn Log WARNING level message.
  283 +func (this *LocalLogger) Warn(format string, v ...interface{}) {
  284 + this.writeMsg(LevelWarning, format, v...)
  285 +}
  286 +
  287 +// Info Log INFO level message.
  288 +func (this *LocalLogger) Info(format string, v ...interface{}) {
  289 + this.writeMsg(LevelInformational, format, v...)
  290 +}
  291 +
  292 +// Debug Log DEBUG level message.
  293 +func (this *LocalLogger) Debug(format string, v ...interface{}) {
  294 + this.writeMsg(LevelDebug, format, v...)
  295 +}
  296 +
  297 +// Trace Log TRAC level message.
  298 +func (this *LocalLogger) Trace(format string, v ...interface{}) {
  299 + this.writeMsg(LevelTrace, format, v...)
  300 +}
  301 +
  302 +func (this *LocalLogger) Close() {
  303 +
  304 + for _, l := range this.outputs {
  305 + l.Destroy()
  306 + }
  307 + this.outputs = nil
  308 +
  309 +}
  310 +
  311 +func (this *LocalLogger) Reset() {
  312 + this.lock.Lock()
  313 + defer this.lock.Unlock()
  314 + for _, l := range this.outputs {
  315 + l.Destroy()
  316 + }
  317 + this.outputs = nil
  318 +}
  319 +
  320 +func (this *LocalLogger) SetCallDepth(depth int) {
  321 + this.callDepth = depth
  322 +}
  323 +
  324 +// GetlocalLogger returns the defaultLogger
  325 +func GetlocalLogger() *LocalLogger {
  326 + return defaultLogger
  327 +}
  328 +
  329 +// Reset will remove all the adapter
  330 +func Reset() {
  331 + defaultLogger.Reset()
  332 +}
  333 +
  334 +func SetLogPathTrim(trimPath string) {
  335 + defaultLogger.SetLogPathTrim(trimPath)
  336 +}
  337 +
  338 +// param 可以是log配置文件名,也可以是log配置内容,默认DEBUG输出到控制台
  339 +func SetLogger(param ...string) error {
  340 + if 0 == len(param) {
  341 + //默认只输出到控制台
  342 + defaultLogger.SetLogger(AdapterConsole)
  343 + return nil
  344 + }
  345 +
  346 + c := param[0]
  347 + if len(param) > 1 {
  348 + appName = param[1]
  349 + }
  350 + conf := new(logConfig)
  351 + err := json.Unmarshal([]byte(c), conf)
  352 + if err != nil { //不是json,就认为是配置文件,如果都不是,打印日志,然后退出
  353 + // Open the configuration file
  354 + fd, err := os.Open(c)
  355 + if err != nil {
  356 + fmt.Fprintf(os.Stdout, "Could not open %s for configure: %s\n", c, err)
  357 + os.Exit(1)
  358 + return err
  359 + }
  360 +
  361 + contents, err := ioutil.ReadAll(fd)
  362 + if err != nil {
  363 + fmt.Fprintf(os.Stdout, "Could not read %s: %s\n", c, err)
  364 + os.Exit(1)
  365 + return err
  366 + }
  367 + err = json.Unmarshal(contents, conf)
  368 + if err != nil {
  369 + fmt.Fprintf(os.Stdout, "Could not Unmarshal %s: %s\n", contents, err)
  370 + os.Exit(1)
  371 + return err
  372 + }
  373 + }
  374 + if conf.TimeFormat != "" {
  375 + defaultLogger.timeFormat = conf.TimeFormat
  376 + }
  377 + if conf.Console != nil {
  378 + console, _ := json.Marshal(conf.Console)
  379 + defaultLogger.SetLogger(AdapterConsole, string(console))
  380 + }
  381 + if conf.File != nil {
  382 + file, _ := json.Marshal(conf.File)
  383 + defaultLogger.SetLogger(AdapterFile, string(file))
  384 + }
  385 + if conf.Conn != nil {
  386 + conn, _ := json.Marshal(conf.Conn)
  387 + defaultLogger.SetLogger(AdapterConn, string(conn))
  388 + }
  389 + return nil
  390 +}
  391 +
  392 +// Painc logs a message at emergency level and panic.
  393 +func Painc(f interface{}, v ...interface{}) {
  394 + defaultLogger.Panic(formatLog(f, v...))
  395 +}
  396 +
  397 +// Fatal logs a message at emergency level and exit.
  398 +func Fatal(f interface{}, v ...interface{}) {
  399 + defaultLogger.Fatal(formatLog(f, v...))
  400 +}
  401 +
  402 +// Emer logs a message at emergency level.
  403 +func Emer(f interface{}, v ...interface{}) {
  404 + defaultLogger.Emer(formatLog(f, v...))
  405 +}
  406 +
  407 +// Alert logs a message at alert level.
  408 +func Alert(f interface{}, v ...interface{}) {
  409 + defaultLogger.Alert(formatLog(f, v...))
  410 +}
  411 +
  412 +// Crit logs a message at critical level.
  413 +func Crit(f interface{}, v ...interface{}) {
  414 + defaultLogger.Crit(formatLog(f, v...))
  415 +}
  416 +
  417 +// Error logs a message at error level.
  418 +func Error(f interface{}, v ...interface{}) {
  419 + defaultLogger.Error(formatLog(f, v...))
  420 +}
  421 +
  422 +// Warn logs a message at warning level.
  423 +func Warn(f interface{}, v ...interface{}) {
  424 + defaultLogger.Warn(formatLog(f, v...))
  425 +}
  426 +
  427 +// Info logs a message at info level.
  428 +func Info(f interface{}, v ...interface{}) {
  429 + defaultLogger.Info(formatLog(f, v...))
  430 +}
  431 +
  432 +// Notice logs a message at debug level.
  433 +func Debug(f interface{}, v ...interface{}) {
  434 + defaultLogger.Debug(formatLog(f, v...))
  435 +}
  436 +
  437 +// Trace logs a message at trace level.
  438 +func Trace(f interface{}, v ...interface{}) {
  439 + defaultLogger.Trace(formatLog(f, v...))
  440 +}
  441 +
  442 +func formatLog(f interface{}, v ...interface{}) string {
  443 + var msg string
  444 + switch f.(type) {
  445 + case string:
  446 + msg = f.(string)
  447 + if len(v) == 0 {
  448 + return msg
  449 + }
  450 + if strings.Contains(msg, "%") && !strings.Contains(msg, "%%") {
  451 + //format string
  452 + } else {
  453 + //do not contain format char
  454 + msg += strings.Repeat(" %v", len(v))
  455 + }
  456 + default:
  457 + msg = fmt.Sprint(f)
  458 + if len(v) == 0 {
  459 + return msg
  460 + }
  461 + msg += strings.Repeat(" %v", len(v))
  462 + }
  463 + return fmt.Sprintf(msg, v...)
  464 +}
  465 +
  466 +func stringTrim(s string, cut string) string {
  467 + ss := strings.SplitN(s, cut, 2)
  468 + if 1 == len(ss) {
  469 + return ss[0]
  470 + }
  471 + return ss[1]
  472 +}
... ...
components/net/conn.go renamed to src/components/net/conn.go
... ... @@ -4,8 +4,8 @@ import (
4 4 "bufio"
5 5 "fmt"
6 6 "net"
7   - "pro2d/common"
8   - "pro2d/utils"
  7 + "pro2d/src/common"
  8 + "pro2d/src/components/logger"
9 9 )
10 10  
11 11 type Head struct {
... ... @@ -116,7 +116,7 @@ func (c *Connection) SendMsgByCode(errCode int32, cmd int32, data []byte){
116 116 }
117 117 buf, err := EncodeMsg(pkg)
118 118 if err != nil {
119   - utils.Sugar.Errorf("SendMsg error: %v", err)
  119 + logger.Error("SendMsg error: %v", err)
120 120 return
121 121 }
122 122 c.WBuffer <- buf
... ...
components/net/msg.go renamed to src/components/net/msg.go
... ... @@ -4,7 +4,7 @@ import (
4 4 "bytes"
5 5 "encoding/binary"
6 6 "fmt"
7   - "pro2d/common"
  7 + "pro2d/src/common"
8 8 )
9 9  
10 10 func ParseMsg (data []byte, atEOF bool) (advance int, token []byte, err error) {
... ...
components/net/server.go renamed to src/components/net/server.go
... ... @@ -4,12 +4,12 @@ import (
4 4 "fmt"
5 5 "github.com/golang/protobuf/proto"
6 6 "net"
7   - "pro2d/components/db"
8   - "pro2d/components/etcd"
9 7 "pro2d/conf"
10   - "pro2d/models"
11 8 "pro2d/protos/pb"
12   - "pro2d/utils"
  9 + "pro2d/src/components/db"
  10 + "pro2d/src/components/etcd"
  11 + "pro2d/src/components/logger"
  12 + "pro2d/src/models"
13 13 "sync"
14 14 )
15 15  
... ... @@ -31,7 +31,7 @@ func NewServer(sConf *conf.SConf) *Server {
31 31 }
32 32  
33 33 func (s *Server) OnRecv(msg *MsgPkg) {
34   - utils.Sugar.Debugf("cmd: %d, data: %s", msg.Head.Cmd, msg.Body)
  34 + logger.Debug("cmd: %d, data: %s", msg.Head.Cmd, msg.Body)
35 35 if md, ok := ActionMap[pb.ProtoCode(msg.Head.Cmd)]; ok {
36 36 errCode, protomsg := md(msg)
37 37 rsp, err := proto.Marshal(protomsg)
... ... @@ -42,7 +42,7 @@ func (s *Server) OnRecv(msg *MsgPkg) {
42 42 msg.Conn.SendMsgByCode(errCode, msg.Head.Cmd, rsp)
43 43 return
44 44 }
45   - utils.Sugar.Errorf("protocode not handler: %d", msg.Head.Cmd)
  45 + logger.Error("protocode not handler: %d", msg.Head.Cmd)
46 46 }
47 47  
48 48 func (s *Server) OnClose(conn *Connection) {
... ... @@ -64,7 +64,7 @@ func (s *Server)Start() error {
64 64 return err
65 65 }
66 66  
67   - utils.Sugar.Debugf("listen on %s\n", port)
  67 + logger.Debug("listen on %s\n", port)
68 68 id := 0
69 69 for {
70 70 conn, err := l.Accept()
... ...
models/account.go renamed to src/models/account.go
1 1 package models
2 2  
3 3 import (
4   - "pro2d/components/db"
5 4 "pro2d/protos/pb"
  5 + "pro2d/src/components/db"
6 6 )
7 7  
8 8 type AccountModel struct {
... ... @@ -24,7 +24,7 @@ func NewAccount(phone string) *AccountModel {
24 24 }
25 25 account := &AccountModel{
26 26 MgoColl: db.NewMongoColl(phone, ac),
27   - Account: ac,
  27 + Account: ac,
28 28 }
29 29  
30 30 return account
... ...
models/equip.go renamed to src/models/equip.go
1 1 package models
2 2  
3 3 import (
4   - "pro2d/components/db"
5 4 "pro2d/protos/pb"
  5 + "pro2d/src/components/db"
6 6 "strconv"
7 7 )
8 8  
... ... @@ -11,13 +11,13 @@ type EquipModels struct {
11 11 Equip *pb.Equipment
12 12 }
13 13  
14   -func NewEquip(id int64) *EquipModels{
  14 +func NewEquip(id int64) *EquipModels {
15 15 data := &pb.Equipment{
16 16 Id: id,
17 17 }
18   - m := &EquipModels {
  18 + m := &EquipModels{
19 19 MgoColl: db.NewMongoColl(strconv.Itoa(int(id)), data),
20   - Equip: data,
  20 + Equip: data,
21 21 }
22 22  
23 23 return m
... ...
models/hero.go renamed to src/models/hero.go
1 1 package models
2 2  
3 3 import (
4   - "pro2d/components/db"
5 4 "pro2d/protos/pb"
  5 + "pro2d/src/components/db"
6 6 "strconv"
7 7 )
8 8  
... ... @@ -26,7 +26,7 @@ func NewHero(id int64) *HeroModel {
26 26 }
27 27 m := &HeroModel{
28 28 MgoColl: db.NewMongoColl(strconv.Itoa(int(id)), h),
29   - Hero: h,
  29 + Hero: h,
30 30 }
31 31 return m
32 32 }
... ...
models/init.go renamed to src/models/init.go
1 1 package models
2 2  
3 3 import (
4   - "pro2d/components/db"
5 4 "pro2d/protos/pb"
6   - "pro2d/utils"
  5 + "pro2d/src/components/db"
  6 + "pro2d/src/components/logger"
  7 + "pro2d/src/utils"
7 8 )
8 9  
9 10 func InitDoc(schema ...interface{}) {
... ... @@ -12,10 +13,10 @@ func InitDoc(schema ...interface{}) {
12 13 for _, index := range keys {
13 14 db.CreateCollection(coll)
14 15  
15   - utils.Sugar.Debugf("InitDoc collect: %v, createIndex: %s", coll, index)
  16 + logger.Debug("InitDoc collect: %v, createIndex: %s", coll, index)
16 17 res, err := db.SetUnique(coll, index)
17 18 if err != nil {
18   - utils.Sugar.Errorf("InitDoc unique: %s, err: %v", res, err)
  19 + logger.Error("InitDoc unique: %s, err: %v", res, err)
19 20 continue
20 21 }
21 22 }
... ...
models/init_test.go renamed to src/models/init_test.go
... ... @@ -2,8 +2,8 @@ package models
2 2  
3 3 import (
4 4 "context"
5   - "pro2d/components/db"
6 5 _ "pro2d/conf"
  6 + "pro2d/src/components/db"
7 7 "testing"
8 8 )
9 9  
... ...
models/prop.go renamed to src/models/prop.go
1 1 package models
2 2  
3 3 import (
4   - "pro2d/components/db"
5 4 "pro2d/protos/pb"
  5 + "pro2d/src/components/db"
6 6 "strconv"
7 7 )
8 8  
... ... @@ -11,13 +11,13 @@ type PropModels struct {
11 11 Prop *pb.Prop
12 12 }
13 13  
14   -func NewProp(id int64) *PropModels{
  14 +func NewProp(id int64) *PropModels {
15 15 data := &pb.Prop{
16 16 Id: id,
17 17 }
18 18 m := &PropModels{
19 19 MgoColl: db.NewMongoColl(strconv.Itoa(int(id)), data),
20   - Prop: data,
  20 + Prop: data,
21 21 }
22 22  
23 23 return m
... ...
models/role.go renamed to src/models/role.go
... ... @@ -2,32 +2,32 @@ package models
2 2  
3 3 import (
4 4 "fmt"
5   - "pro2d/components/db"
6 5 "pro2d/protos/pb"
7   - "pro2d/utils"
  6 + "pro2d/src/components/db"
  7 + "pro2d/src/components/logger"
8 8 "strconv"
9 9 )
10 10  
11 11 type RoleModel struct {
12 12 *db.MgoColl
13   - Role *pb.Role
  13 + Role *pb.Role
14 14 Heros HeroMap
15 15 Teams *TeamModel
16 16 Equip *pb.Equipment
17   - Prop *pb.Prop
  17 + Prop *pb.Prop
18 18 }
19 19  
20   -func RoleExistByUid(uid string) *RoleModel{
  20 +func RoleExistByUid(uid string) *RoleModel {
21 21 data := &pb.Role{Uid: uid}
22 22  
23 23 if err := db.FindOne(db.GetBsonM("uid", uid), data); err != nil {
24   - utils.Sugar.Errorf("Role exist err: %v", err)
  24 + logger.Error("Role exist err: %v", err)
25 25 return nil
26 26 }
27 27  
28 28 return &RoleModel{
29 29 MgoColl: db.NewMongoColl(strconv.Itoa(int(data.Id)), data),
30   - Role: data,
  30 + Role: data,
31 31 }
32 32 }
33 33  
... ... @@ -35,8 +35,8 @@ func NewRole(id int64) *RoleModel {
35 35 data := &pb.Role{Id: id}
36 36 m := &RoleModel{
37 37 MgoColl: db.NewMongoColl(strconv.Itoa(int(id)), data),
38   - Role: data,
39   - Heros: make(HeroMap),
  38 + Role: data,
  39 + Heros: make(HeroMap),
40 40 }
41 41 return m
42 42 }
... ...
models/role_test.go renamed to src/models/role_test.go
... ... @@ -2,10 +2,11 @@ package models
2 2  
3 3 import (
4 4 "fmt"
5   - "pro2d/components/db"
6 5 "pro2d/conf"
7 6 "pro2d/protos/pb"
8   - "pro2d/utils"
  7 + "pro2d/src/components/db"
  8 + "pro2d/src/components/logger"
  9 + "pro2d/src/utils"
9 10 "testing"
10 11 )
11 12  
... ... @@ -13,8 +14,8 @@ func TestNewRole(t *testing.T) {
13 14 db.MongoDatabase = db.MongoClient.Database("game")
14 15  
15 16 var uid = conf.SnowFlack.NextValStr()
16   - ok, role := RoleExistByUid(uid)
17   - if ok {
  17 + role := RoleExistByUid(uid)
  18 + if role != nil {
18 19 //uid存在 , 更新角色
19 20 role.Role.Device = "222222"
20 21 role.AddHero(&pb.Hero{
... ... @@ -42,6 +43,6 @@ func TestNewRole(t *testing.T) {
42 43 func TestRoleIndex(t *testing.T) {
43 44 coll, keys := utils.FindIndex(pb.Role{})
44 45 for _, index := range keys {
45   - utils.Sugar.Debugf("coll: %s, key: %s", coll, index)
  46 + logger.Debug("coll: %s, key: %s", coll, index)
46 47 }
47 48 }
48 49 \ No newline at end of file
... ...
models/team.go renamed to src/models/team.go
1 1 package models
2 2  
3 3 import (
4   - "pro2d/components/db"
5 4 "pro2d/protos/pb"
  5 + "pro2d/src/components/db"
6 6 "strconv"
7 7 )
8 8  
... ... @@ -11,13 +11,13 @@ type TeamModel struct {
11 11 Team *pb.Team
12 12 }
13 13  
14   -func NewTeam(id int64) *TeamModel{
  14 +func NewTeam(id int64) *TeamModel {
15 15 data := &pb.Team{
16 16 Id: id,
17 17 }
18 18 m := &TeamModel{
19 19 MgoColl: db.NewMongoColl(strconv.Itoa(int(id)), data),
20   - Team: data,
  20 + Team: data,
21 21 }
22 22  
23 23 return m
... ...
utils/md5.go renamed to src/utils/md5.go
utils/snowflake.go renamed to src/utils/snowflake.go
utils/utils.go renamed to src/utils/utils.go
... ... @@ -44,13 +44,4 @@ func FindIndex(schema interface{}) (string, []string){
44 44 }
45 45 }
46 46 return strings.ToLower(s.Name()), index
47   -}
48   -
49   -func GetIdxBySlice(s []interface{}, i interface{}) (int){
50   - for idx, v := range s {
51   - if v == i {
52   - return idx
53   - }
54   - }
55   - return -1
56 47 }
57 48 \ No newline at end of file
... ...
test/client.go
... ... @@ -4,13 +4,13 @@ import (
4 4 "bytes"
5 5 "encoding/binary"
6 6 "net"
7   - net2 "pro2d/components/net"
8   - "pro2d/utils"
  7 + "pro2d/src/components/logger"
  8 + net2 "pro2d/src/components/net"
9 9 )
10 10  
11 11 func main() {
12 12  
13   - head := net2.Head{
  13 + head := &net2.Head{
14 14 Length: 0,
15 15 Cmd: 1,
16 16 ErrCode: 0,
... ... @@ -26,20 +26,20 @@ func main() {
26 26 buf := &bytes.Buffer{}
27 27 err := binary.Write(buf, binary.BigEndian, head)
28 28 if err != nil {
29   - utils.Sugar.Errorf("err: %v, head: %v", err, head)
  29 + logger.Error("err: %v, head: %v", err, head)
30 30 return
31 31 }
32   - utils.Sugar.Debugf("head: %v", head)
  32 + logger.Debug("head: %v", head)
33 33  
34 34 err = binary.Write(buf, binary.BigEndian, b.Body)
35 35 if err != nil {
36   - utils.Sugar.Errorf("err: %v, msg: %v", err, b.Body)
  36 + logger.Error("err: %v, msg: %v", err, b.Body)
37 37 return
38 38 }
39 39  
40 40 client, err := net.Dial("tcp", "localhost:8849")
41 41 if err != nil {
42   - utils.Sugar.Error(err)
  42 + logger.Error(err)
43 43 return
44 44 }
45 45 client.Write(buf.Bytes())
... ...
utils/logger.go deleted
... ... @@ -1,107 +0,0 @@
1   -package utils
2   -
3   -import (
4   - "go.uber.org/zap"
5   - "go.uber.org/zap/zapcore"
6   - lumberjack "gopkg.in/natefinch/lumberjack.v2"
7   - "net/http"
8   - "os"
9   -)
10   -
11   -var Sugar *zap.SugaredLogger
12   -var Logger *zap.Logger
13   -
14   -func InitLogger(conf *lumberjack.Logger) {
15   - writeSyncer := zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(conf)) //控制台和日志同时输出
16   - encoder := getEncoder()
17   - core := zapcore.NewCore(encoder, writeSyncer, zapcore.DebugLevel)
18   -
19   - Logger = zap.New(core, zap.AddCaller())
20   - Sugar = Logger.Sugar()
21   -}
22   -
23   -func getEncoder() zapcore.Encoder {
24   - encoderConfig := zap.NewProductionEncoderConfig()
25   - encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
26   - encoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
27   - return zapcore.NewConsoleEncoder(encoderConfig)
28   -}
29   -
30   -func simpleHttpGet(url string) {
31   - Sugar.Debugf("Trying to hit GET request for %s", url)
32   - resp, err := http.Get(url)
33   - if err != nil {
34   - Sugar.Errorf("Error fetching URL %s : Error = %s", url, err)
35   - } else {
36   - Sugar.Infof("Success! statusCode = %s for URL %s", resp.Status, url)
37   - resp.Body.Close()
38   - }
39   -}
40   -
41   -func LogTest() {
42   - lumberJackLogger := &lumberjack.Logger{
43   - Filename: "./pro2d.log", // ⽇志⽂件路径
44   - MaxSize: 1024, // 1M=1024KB=1024000byte
45   - MaxBackups: 5, // 最多保留5个备份
46   - MaxAge: 30, // days
47   - Compress: true, // 是否压缩 disabled by default
48   - }
49   -
50   - InitLogger(lumberJackLogger)
51   - defer Logger.Sync()
52   - for i:=0; i < 10000;i++ {
53   - simpleHttpGet("www.baidu.com")
54   - simpleHttpGet("http://www.baidu.com")
55   - }
56   -}
57   -
58   -//--使用sink 结合es使用
59   -//func registerSinkDemo() {
60   -// zap.RegisterSink("mq", mq.NewMqSink)
61   -// writer, close, err := zap.Open("mq://192.168.99.100:9876/log")
62   -// if err != nil {
63   -// panic(err)
64   -// }
65   -// defer close()
66   -// logger := zap.New(zapcore.NewCore(zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()), writer, zap.DebugLevel)).Sugar()
67   -// logger.Info("hello")
68   -//}
69   -//
70   -//type MqWriteSyncer struct {
71   -// topic string
72   -// producer rocketmq.Producer
73   -// ctx context.Context
74   -//}
75   -//
76   -//func (m *MqWriteSyncer) Close() error {
77   -// return m.producer.Shutdown()
78   -//}
79   -//
80   -//func (m *MqWriteSyncer) Write(p []byte) (n int, err error) {
81   -// msg := &primitive.Message{
82   -// Topic: m.topic,
83   -// Body: p,
84   -// }
85   -// err = m.producer.SendOneWay(m.ctx, msg)
86   -// return len(p), err
87   -//}
88   -//
89   -//func (m *MqWriteSyncer) Sync() error {
90   -// return nil
91   -//}
92   -//
93   -//func NewMqSink(url *url.URL) (zap.Sink, error) {
94   -// broker := fmt.Sprintf("%s:%s", url.Hostname(), url.Port())
95   -// topic := url.Path[1:len(url.Path)]
96   -// p, _ := rocketmq.NewProducer(
97   -// producer.WithNameServer([]string{broker}),
98   -// producer.WithRetry(2),
99   -// )
100   -// err := p.Start()
101   -// if err != nil {
102   -// fmt.Printf("start producer error: %s", err.Error())
103   -// return nil, err
104   -// }
105   -//
106   -// return &MqWriteSyncer{producer: p, ctx: context.Background(), topic: topic}, nil
107   -//}
108 0 \ No newline at end of file