158 lines
3.9 KiB
Go
158 lines
3.9 KiB
Go
/*
|
|
A small cli utility meant to convert json to zipkin thrift binary format, and
|
|
vice versa.
|
|
|
|
To convert from json to thrift,
|
|
the json is unmarshalled, converted to zipkincore.Span structures, and
|
|
marshalled into thrift binary protocol. The json must be in an array format (even if it only has one object),
|
|
because the tool automatically tries to unmarshall the json into an array of structs.
|
|
|
|
To convert from thrift to json,
|
|
the opposite process must happen. The thrift binary data must be read into an array of
|
|
zipkin span structures, and those spans must be marshalled into json.
|
|
|
|
Usage:
|
|
|
|
./thrift_serialize -input <input-file> -output <output-file> -deserialize<true|false>
|
|
|
|
If `deserialize` is set to true (false by default), the tool will interpret the input file as
|
|
thrift, and write it as json to the output file.
|
|
Otherwise, the input file will be interpreted as json, and the output will be encoded as thrift.
|
|
|
|
|
|
*/
|
|
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"flag"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"log"
|
|
|
|
"github.com/apache/thrift/lib/go/thrift"
|
|
"github.com/openzipkin/zipkin-go-opentracing/thrift/gen-go/zipkincore"
|
|
)
|
|
|
|
var (
|
|
filename string
|
|
outFileName string
|
|
inputType string
|
|
)
|
|
|
|
const usage = `./json_serialize -input <input> -output output -input-type<json|thrift>`
|
|
|
|
func init() {
|
|
flag.StringVar(&filename, "input", "", usage)
|
|
flag.StringVar(&outFileName, "output", "", usage)
|
|
flag.StringVar(&inputType, "input-type", "thrift", usage)
|
|
}
|
|
|
|
func main() {
|
|
flag.Parse()
|
|
contents, err := ioutil.ReadFile(filename)
|
|
if err != nil {
|
|
log.Fatalf("Error reading file: %v\n", err)
|
|
}
|
|
|
|
switch inputType {
|
|
case "json":
|
|
raw, err := jsonToZipkinThrift(contents)
|
|
if err != nil {
|
|
log.Fatalf("%v\n", err)
|
|
}
|
|
if err := ioutil.WriteFile(outFileName, raw, 0644); err != nil {
|
|
log.Fatalf("%v", err)
|
|
}
|
|
case "thrift":
|
|
raw, err := thriftToJSONSpans(contents)
|
|
if err != nil {
|
|
log.Fatalf("%v\n", err)
|
|
}
|
|
if err := ioutil.WriteFile(outFileName, raw, 0644); err != nil {
|
|
log.Fatalf("%v", err)
|
|
}
|
|
default:
|
|
log.Fatalf("Unsupported input type")
|
|
}
|
|
}
|
|
|
|
func jsonToZipkinThrift(jsonRaw []byte) ([]byte, error) {
|
|
if len(jsonRaw) == 0 {
|
|
return nil, errors.New("no data")
|
|
}
|
|
|
|
if string(jsonRaw)[0] != '[' {
|
|
return nil, errors.New("cannot unmarshal non array type")
|
|
}
|
|
|
|
var spans []*zipkincore.Span
|
|
err := json.Unmarshal(jsonRaw, &spans)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error unmarshalling: %v", err)
|
|
}
|
|
|
|
var zspans []*zipkincore.Span
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
zspans = append(zspans, spans...)
|
|
|
|
fmt.Println(spans)
|
|
|
|
buf := thrift.NewTMemoryBuffer()
|
|
transport := thrift.NewTBinaryProtocolTransport(buf)
|
|
|
|
if err = transport.WriteListBegin(thrift.STRUCT, len(spans)); err != nil {
|
|
return nil, fmt.Errorf("error in beginning thrift write: %v", err)
|
|
}
|
|
|
|
for _, span := range zspans {
|
|
err = span.Write(transport)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error converting zipkin struct to thrift: %v", err)
|
|
}
|
|
}
|
|
|
|
if err = transport.WriteListEnd(); err != nil {
|
|
return nil, fmt.Errorf("error finishing thrift write: %v", err)
|
|
}
|
|
|
|
return buf.Bytes(), nil
|
|
}
|
|
|
|
func thriftToJSONSpans(thriftData []byte) ([]byte, error) {
|
|
buffer := thrift.NewTMemoryBuffer()
|
|
if _, err := buffer.Write(thriftData); err != nil {
|
|
err = fmt.Errorf("error in buffer write: %v", err)
|
|
return nil, err
|
|
}
|
|
|
|
transport := thrift.NewTBinaryProtocolTransport(buffer)
|
|
_, size, err := transport.ReadListBegin()
|
|
if err != nil {
|
|
err = fmt.Errorf("error in ReadListBegin: %v", err)
|
|
return nil, err
|
|
}
|
|
|
|
var spans []*zipkincore.Span
|
|
for i := 0; i < size; i++ {
|
|
zs := &zipkincore.Span{}
|
|
if err = zs.Read(transport); err != nil {
|
|
err = fmt.Errorf("Error reading into zipkin struct: %v", err)
|
|
return nil, err
|
|
}
|
|
spans = append(spans, zs)
|
|
}
|
|
|
|
err = transport.ReadListEnd()
|
|
if err != nil {
|
|
err = fmt.Errorf("error ending thrift read: %v", err)
|
|
return nil, err
|
|
}
|
|
|
|
out, _ := json.MarshalIndent(spans, "", " ")
|
|
return out, nil
|
|
}
|