mirror of https://github.com/etcd-io/dbtester.git
162 lines
3.4 KiB
Go
162 lines
3.4 KiB
Go
// Package schema represents linux-inspect schema.
|
|
package schema
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"reflect"
|
|
"strings"
|
|
)
|
|
|
|
// Generate generates go struct text from given RawData.
|
|
func Generate(raw RawData) string {
|
|
tagstr := "yaml"
|
|
if !raw.IsYAML {
|
|
tagstr = "column"
|
|
}
|
|
|
|
buf := new(bytes.Buffer)
|
|
for _, col := range raw.Columns {
|
|
goFieldName := ToField(col.Name)
|
|
goFieldTagName := col.Name
|
|
if !raw.IsYAML {
|
|
goFieldTagName = ToFieldTag(goFieldTagName)
|
|
}
|
|
if col.Godoc != "" {
|
|
buf.WriteString(fmt.Sprintf("\t// %s is %s.\n", goFieldName, col.Godoc))
|
|
}
|
|
buf.WriteString(fmt.Sprintf("\t%s\t%s\t`%s:\"%s\"`\n",
|
|
goFieldName,
|
|
GoType(col.Kind),
|
|
tagstr,
|
|
goFieldTagName,
|
|
))
|
|
|
|
// additional parsed column
|
|
if v, ok := raw.ColumnsToParse[col.Name]; ok {
|
|
switch v {
|
|
case TypeInt64, TypeFloat64:
|
|
// need no additional columns
|
|
|
|
case TypeBytes:
|
|
ntstr := "uint64"
|
|
if col.Kind == reflect.Int64 {
|
|
ntstr = "int64"
|
|
}
|
|
buf.WriteString(fmt.Sprintf("\t%sBytesN\t%s\t`%s:\"%s_bytes_n\"`\n",
|
|
goFieldName,
|
|
ntstr,
|
|
tagstr,
|
|
goFieldTagName,
|
|
))
|
|
buf.WriteString(fmt.Sprintf("\t%sParsedBytes\tstring\t`%s:\"%s_parsed_bytes\"`\n",
|
|
goFieldName,
|
|
tagstr,
|
|
goFieldTagName,
|
|
))
|
|
|
|
case TypeTimeMicroseconds, TypeTimeSeconds:
|
|
buf.WriteString(fmt.Sprintf("\t%sParsedTime\tstring\t`%s:\"%s_parsed_time\"`\n",
|
|
goFieldName,
|
|
tagstr,
|
|
goFieldTagName,
|
|
))
|
|
|
|
case TypeIPAddress:
|
|
buf.WriteString(fmt.Sprintf("\t%sParsedIPHost\tstring\t`%s:\"%s_parsed_ip_host\"`\n",
|
|
goFieldName,
|
|
tagstr,
|
|
goFieldTagName,
|
|
))
|
|
buf.WriteString(fmt.Sprintf("\t%sParsedIPPort\tint64\t`%s:\"%s_parsed_ip_port\"`\n",
|
|
goFieldName,
|
|
tagstr,
|
|
goFieldTagName,
|
|
))
|
|
|
|
case TypeStatus:
|
|
buf.WriteString(fmt.Sprintf("\t%sParsedStatus\tstring\t`%s:\"%s_parsed_status\"`\n",
|
|
goFieldName,
|
|
tagstr,
|
|
goFieldTagName,
|
|
))
|
|
|
|
default:
|
|
panic(fmt.Errorf("unknown parse type %d", raw.ColumnsToParse[col.Name]))
|
|
}
|
|
}
|
|
}
|
|
|
|
return buf.String()
|
|
}
|
|
|
|
// RawDataType defines how the raw data bytes are defined.
|
|
type RawDataType int
|
|
|
|
const (
|
|
TypeBytes RawDataType = iota
|
|
TypeInt64
|
|
TypeFloat64
|
|
TypeTimeMicroseconds
|
|
TypeTimeSeconds
|
|
TypeIPAddress
|
|
TypeStatus
|
|
)
|
|
|
|
// RawData defines 'proc' raw data.
|
|
type RawData struct {
|
|
// IsYAML is true if raw data is parsable in YAML.
|
|
IsYAML bool
|
|
|
|
Columns []Column
|
|
ColumnsToParse map[string]RawDataType
|
|
}
|
|
|
|
// Column represents the schema column.
|
|
type Column struct {
|
|
Name string
|
|
Godoc string
|
|
Kind reflect.Kind
|
|
}
|
|
|
|
// ToField converts raw YAML key to Go field name.
|
|
func ToField(s string) string {
|
|
s = strings.Replace(s, "-", "_", -1)
|
|
s = strings.Replace(s, "/", "", -1)
|
|
s = strings.Replace(s, ">", "", -1)
|
|
cs := strings.Split(s, "_")
|
|
var ss []string
|
|
for _, v := range cs {
|
|
if len(v) > 0 {
|
|
ss = append(ss, strings.Title(v))
|
|
}
|
|
}
|
|
return strings.TrimSpace(strings.Join(ss, ""))
|
|
}
|
|
|
|
// ToFieldTag converts raw key to field name.
|
|
func ToFieldTag(s string) string {
|
|
s = strings.ToLower(s)
|
|
s = strings.Replace(s, "-", "_", -1)
|
|
s = strings.Replace(s, "/", "", -1)
|
|
return strings.Replace(s, ">", "", -1)
|
|
}
|
|
|
|
// GoType converts to Go type.
|
|
func GoType(tp reflect.Kind) string {
|
|
switch tp {
|
|
case reflect.Float64:
|
|
return "float64"
|
|
case reflect.Uint64:
|
|
return "uint64"
|
|
case reflect.Int:
|
|
return "int"
|
|
case reflect.Int64:
|
|
return "int64"
|
|
case reflect.String:
|
|
return "string"
|
|
default:
|
|
panic(fmt.Errorf("unknown type %q", tp.String()))
|
|
}
|
|
}
|