tlog.app/go/tlog@v0.23.1/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 runtime.NumCPU() },
    34  	"_gomaxprocs": func() interface{} { return 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  }