github.com/nikandfor/tlog@v0.21.5-0.20231108111739-3ef89426a96d/labels.go (about) 1 package tlog 2 3 import ( 4 "crypto/md5" //nolint 5 "crypto/sha1" //nolint 6 "fmt" 7 "io" 8 "os" 9 "os/user" 10 "path/filepath" 11 "runtime" 12 "strconv" 13 "strings" 14 "time" 15 ) 16 17 // AutoLabels is a list of automatically filled labels 18 // 19 // _hostname - local hostname 20 // _user - current user 21 // _pid - process pid 22 // _timezone - local timezone code (UTC, MSK) 23 // _goversion - go version 24 // _execmd5 - this binary md5 hash 25 // _execsha1 - this binary sha1 hash 26 // _execname - executable base name (project name) 27 // _randid - random id. May be used to distinguish different runs. 28 var AutoLabels = map[string]func() interface{}{ 29 "_hostname": func() interface{} { return Hostname() }, 30 "_user": func() interface{} { return User() }, 31 "_os": func() interface{} { return runtime.GOOS }, 32 "_arch": func() interface{} { return runtime.GOARCH }, 33 "_numcpu": func() interface{} { return fmt.Sprintf("%v", runtime.NumCPU()) }, 34 "_gomaxprocs": func() interface{} { return fmt.Sprintf("%v", runtime.GOMAXPROCS(0)) }, 35 "_goversion": func() interface{} { return runtime.Version }, 36 "_pid": func() interface{} { 37 return os.Getpid() 38 }, 39 "_timezone": func() interface{} { 40 n, _ := time.Now().Zone() 41 return n 42 }, 43 "_execmd5": func() interface{} { return ExecutableMD5() }, 44 "_execsha1": func() interface{} { return ExecutableSHA1() }, 45 "_execname": func() interface{} { 46 return filepath.Base(os.Args[0]) 47 }, 48 "_randid": func() interface{} { 49 return MathRandID().StringFull() 50 }, 51 } 52 53 // Hostname returns hostname or err.Error(). 54 func Hostname() string { 55 h, err := os.Hostname() 56 if h == "" && err != nil { 57 h = err.Error() 58 } 59 60 return h 61 } 62 63 // User returns current username or err.Error(). 64 func User() string { 65 u, err := user.Current() 66 if u != nil && u.Username != "" { 67 return u.Username 68 } else if err != nil { 69 return err.Error() 70 } 71 72 return "" 73 } 74 75 // ExecutableMD5 returns current process executable md5 hash. 76 // May be useful to find exact executable later. 77 func ExecutableMD5() string { 78 path, err := os.Executable() 79 if err != nil { 80 return err.Error() 81 } 82 83 f, err := os.Open(path) 84 if err != nil { 85 return err.Error() 86 } 87 defer f.Close() 88 89 h := md5.New() //nolint 90 _, err = io.Copy(h, f) 91 if err != nil { 92 return err.Error() 93 } 94 95 return fmt.Sprintf("%02x", h.Sum(nil)) 96 } 97 98 // ExecutableSHA1 returns current process executable sha1 hash. 99 // May be useful to find exact executable later. 100 func ExecutableSHA1() string { 101 path, err := os.Executable() 102 if err != nil { 103 return err.Error() 104 } 105 106 f, err := os.Open(path) 107 if err != nil { 108 return err.Error() 109 } 110 defer f.Close() 111 112 h := sha1.New() //nolint 113 _, err = io.Copy(h, f) 114 if err != nil { 115 return err.Error() 116 } 117 118 return fmt.Sprintf("%02x", h.Sum(nil)) 119 } 120 121 // ParseLabels parses comma separated list of labels and fills them with values (See FillLabelsWithDefaults). 122 func ParseLabels(s string) []interface{} { 123 l := strings.Split(s, ",") 124 125 res := make([]interface{}, 0, len(l)*2) 126 127 for _, l := range l { 128 if l == "" { 129 continue 130 } 131 132 p := strings.IndexByte(l, '=') 133 if p == -1 { 134 if f, ok := AutoLabels[l]; ok { 135 res = append(res, l, f()) 136 } else { 137 res = append(res, l, "") 138 } 139 140 continue 141 } 142 143 k, v := l[:p], l[p+1:] 144 145 if x, err := strconv.Atoi(v); err == nil { 146 res = append(res, k, x) 147 continue 148 } 149 150 res = append(res, k, v) 151 } 152 153 return res 154 }