func NewReaper(cnf *conf.Config) *Reaper { rpr := &Reaper{ lg: common.NewLogger("reaper", cnf), spanExpiryMs: cnf.GetInt64(conf.HTRACE_SPAN_EXPIRY_MS), heartbeats: make(chan interface{}, 1), } if rpr.spanExpiryMs >= MAX_SPAN_EXPIRY_MS { rpr.spanExpiryMs = MAX_SPAN_EXPIRY_MS } else if rpr.spanExpiryMs <= 0 { rpr.spanExpiryMs = MAX_SPAN_EXPIRY_MS } rpr.hb = NewHeartbeater("ReaperHeartbeater", cnf.GetInt64(conf.HTRACE_REAPER_HEARTBEAT_PERIOD_MS), rpr.lg) rpr.exited.Add(1) go rpr.run() rpr.hb.AddHeartbeatTarget(&HeartbeatTarget{ name: "reaper", targetChan: rpr.heartbeats, }) var when string if rpr.spanExpiryMs >= MAX_SPAN_EXPIRY_MS { when = "never" } else { when = "after " + time.Duration(rpr.spanExpiryMs).String() } rpr.lg.Infof("Initializing span reaper: span time out = %s.\n", when) return rpr }
func CreateRestServer(cnf *conf.Config, store *dataStore) (*RestServer, error) { var err error rsv := &RestServer{} rsv.listener, err = net.Listen("tcp", cnf.Get(conf.HTRACE_WEB_ADDRESS)) if err != nil { return nil, err } var success bool defer func() { if !success { rsv.Close() } }() rsv.lg = common.NewLogger("rest", cnf) r := mux.NewRouter().StrictSlash(false) r.Handle("/server/info", &serverInfoHandler{lg: rsv.lg}).Methods("GET") serverStatsH := &serverStatsHandler{dataStoreHandler: dataStoreHandler{ store: store, lg: rsv.lg}} r.Handle("/server/stats", serverStatsH).Methods("GET") writeSpansH := &writeSpansHandler{dataStoreHandler: dataStoreHandler{ store: store, lg: rsv.lg}} r.Handle("/writeSpans", writeSpansH).Methods("POST") queryH := &queryHandler{lg: rsv.lg, dataStoreHandler: dataStoreHandler{store: store}} r.Handle("/query", queryH).Methods("GET") span := r.PathPrefix("/span").Subrouter() findSidH := &findSidHandler{dataStoreHandler: dataStoreHandler{store: store, lg: rsv.lg}} span.Handle("/{id}", findSidH).Methods("GET") findChildrenH := &findChildrenHandler{dataStoreHandler: dataStoreHandler{store: store, lg: rsv.lg}} span.Handle("/{id}/children", findChildrenH).Methods("GET") // Default Handler. This will serve requests for static requests. webdir := os.Getenv("HTRACED_WEB_DIR") if webdir == "" { webdir, err = filepath.Abs(filepath.Join(filepath.Dir(os.Args[0]), "..", "web")) if err != nil { return nil, err } } rsv.lg.Infof("Serving static files from %s\n.", webdir) r.PathPrefix("/").Handler(http.FileServer(http.Dir(webdir))).Methods("GET") // Log an error message for unknown non-GET requests. r.PathPrefix("/").Handler(&logErrorHandler{lg: rsv.lg}) go http.Serve(rsv.listener, r) rsv.lg.Infof("Started REST server on %s...\n", rsv.listener.Addr().String()) success = true return rsv, nil }
func NewMetricsSink(cnf *conf.Config) *MetricsSink { return &MetricsSink{ lg: common.NewLogger("metrics", cnf), maxMtx: cnf.GetInt(conf.HTRACE_METRICS_MAX_ADDR_ENTRIES), HostSpanMetrics: make(common.SpanMetricsMap), wsLatencyCircBuf: NewCircBufU32(LATENCY_CIRC_BUF_SIZE), } }
func CreateRestServer(cnf *conf.Config, store *dataStore, listener net.Listener) (*RestServer, error) { var err error rsv := &RestServer{} rsv.lg = common.NewLogger("rest", cnf) r := mux.NewRouter().StrictSlash(false) r.Handle("/server/info", &serverVersionHandler{lg: rsv.lg}).Methods("GET") r.Handle("/server/version", &serverVersionHandler{lg: rsv.lg}).Methods("GET") r.Handle("/server/debugInfo", &serverDebugInfoHandler{lg: rsv.lg}).Methods("GET") serverStatsH := &serverStatsHandler{dataStoreHandler: dataStoreHandler{ store: store, lg: rsv.lg}} r.Handle("/server/stats", serverStatsH).Methods("GET") serverConfH := &serverConfHandler{cnf: cnf, lg: rsv.lg} r.Handle("/server/conf", serverConfH).Methods("GET") writeSpansH := &writeSpansHandler{dataStoreHandler: dataStoreHandler{ store: store, lg: rsv.lg}} r.Handle("/writeSpans", writeSpansH).Methods("POST") queryH := &queryHandler{lg: rsv.lg, dataStoreHandler: dataStoreHandler{store: store}} r.Handle("/query", queryH).Methods("GET") span := r.PathPrefix("/span").Subrouter() findSidH := &findSidHandler{dataStoreHandler: dataStoreHandler{store: store, lg: rsv.lg}} span.Handle("/{id}", findSidH).Methods("GET") findChildrenH := &findChildrenHandler{dataStoreHandler: dataStoreHandler{store: store, lg: rsv.lg}} span.Handle("/{id}/children", findChildrenH).Methods("GET") // Default Handler. This will serve requests for static requests. webdir := os.Getenv("HTRACED_WEB_DIR") if webdir == "" { webdir, err = filepath.Abs(filepath.Join(filepath.Dir(os.Args[0]), "..", "web")) if err != nil { return nil, err } } rsv.lg.Infof(`Serving static files from "%s"`+"\n", webdir) r.PathPrefix("/").Handler(http.FileServer(http.Dir(webdir))).Methods("GET") // Log an error message for unknown non-GET requests. r.PathPrefix("/").Handler(&logErrorHandler{lg: rsv.lg}) rsv.listener = listener rsv.Handler = r rsv.ErrorLog = rsv.lg.Wrap("[REST] ", common.INFO) go rsv.Serve(rsv.listener) rsv.lg.Infof("Started REST server on %s\n", rsv.listener.Addr().String()) return rsv, nil }
func main() { for idx := range os.Args { arg := os.Args[idx] if strings.HasPrefix(arg, "--h") || strings.HasPrefix(arg, "-h") { fmt.Fprintf(os.Stderr, USAGE) os.Exit(0) } } cnf := common.LoadApplicationConfig() common.InstallSignalHandlers(cnf) lg := common.NewLogger("main", cnf) defer lg.Close() store, err := CreateDataStore(cnf, nil) if err != nil { lg.Errorf("Error creating datastore: %s\n", err.Error()) os.Exit(1) } var rsv *RestServer rsv, err = CreateRestServer(cnf, store) if err != nil { lg.Errorf("Error creating REST server: %s\n", err.Error()) os.Exit(1) } var hsv *HrpcServer if cnf.Get(conf.HTRACE_HRPC_ADDRESS) != "" { hsv, err = CreateHrpcServer(cnf, store) if err != nil { lg.Errorf("Error creating HRPC server: %s\n", err.Error()) os.Exit(1) } } else { lg.Infof("Not starting HRPC server because no value was given for %s.\n", conf.HTRACE_HRPC_ADDRESS) } naddr := cnf.Get(conf.HTRACE_STARTUP_NOTIFICATION_ADDRESS) if naddr != "" { notif := StartupNotification{ HttpAddr: rsv.Addr().String(), ProcessId: os.Getpid(), } if hsv != nil { notif.HrpcAddr = hsv.Addr().String() } err = sendStartupNotification(naddr, ¬if) if err != nil { fmt.Fprintf(os.Stderr, "Failed to send startup notification: "+ "%s\n", err.Error()) os.Exit(1) } } for { time.Sleep(time.Duration(10) * time.Hour) } }
func TestHeartbeaterStartupShutdown(t *testing.T) { cnfBld := conf.Builder{ Values: conf.TEST_VALUES(), Defaults: conf.DEFAULTS, } cnf, err := cnfBld.Build() if err != nil { t.Fatalf("failed to create conf: %s", err.Error()) } lg := common.NewLogger("heartbeater", cnf) hb := NewHeartbeater("ExampleHeartbeater", 1, lg) if hb.String() != "ExampleHeartbeater" { t.Fatalf("hb.String() returned %s instead of %s\n", hb.String(), "ExampleHeartbeater") } hb.Shutdown() }
func CreateHrpcServer(cnf *conf.Config, store *dataStore, testHooks *hrpcTestHooks) (*HrpcServer, error) { lg := common.NewLogger("hrpc", cnf) numHandlers := cnf.GetInt(conf.HTRACE_NUM_HRPC_HANDLERS) if numHandlers < 1 { lg.Warnf("%s must be positive: using 1 handler.\n", conf.HTRACE_NUM_HRPC_HANDLERS) numHandlers = 1 } if numHandlers > MAX_HRPC_HANDLERS { lg.Warnf("%s cannot be more than %d: using %d handlers\n", conf.HTRACE_NUM_HRPC_HANDLERS, MAX_HRPC_HANDLERS, MAX_HRPC_HANDLERS) numHandlers = MAX_HRPC_HANDLERS } hsv := &HrpcServer{ Server: rpc.NewServer(), hand: &HrpcHandler{ lg: lg, store: store, }, cdcs: make(chan *HrpcServerCodec, numHandlers), shutdown: make(chan interface{}), ioTimeo: time.Millisecond * time.Duration(cnf.GetInt64(conf.HTRACE_HRPC_IO_TIMEOUT_MS)), testHooks: testHooks, } for i := 0; i < numHandlers; i++ { hsv.cdcs <- &HrpcServerCodec{ lg: lg, hsv: hsv, msgpackHandle: codec.MsgpackHandle{ WriteExt: true, }, } } var err error hsv.listener, err = net.Listen("tcp", cnf.Get(conf.HTRACE_HRPC_ADDRESS)) if err != nil { return nil, err } hsv.Server.Register(hsv.hand) hsv.exited.Add(1) go hsv.run() lg.Infof("Started HRPC server on %s with %d handler routines. "+ "ioTimeo=%s.\n", hsv.listener.Addr().String(), numHandlers, hsv.ioTimeo.String()) return hsv, nil }
func CreateHrpcServer(cnf *conf.Config, store *dataStore) (*HrpcServer, error) { lg := common.NewLogger("hrpc", cnf) hsv := &HrpcServer{ Server: rpc.NewServer(), hand: &HrpcHandler{ lg: lg, store: store, }, } var err error hsv.listener, err = net.Listen("tcp", cnf.Get(conf.HTRACE_HRPC_ADDRESS)) if err != nil { return nil, err } hsv.Server.Register(hsv.hand) go hsv.run() lg.Infof("Started HRPC server on %s...\n", hsv.listener.Addr().String()) return hsv, nil }
func CreateDataStore(cnf *conf.Config, writtenSpans chan *common.Span) (*dataStore, error) { // Get the configuration. clearStored := cnf.GetBool(conf.HTRACE_DATA_STORE_CLEAR) dirsStr := cnf.Get(conf.HTRACE_DATA_STORE_DIRECTORIES) dirs := strings.Split(dirsStr, conf.PATH_LIST_SEP) var err error lg := common.NewLogger("datastore", cnf) store := &dataStore{lg: lg, shards: []*shard{}, WrittenSpans: writtenSpans} // If we return an error, close the store. defer func() { if err != nil { store.Close() store = nil } }() store.readOpts = levigo.NewReadOptions() store.readOpts.SetFillCache(true) store.writeOpts = levigo.NewWriteOptions() store.writeOpts.SetSync(false) // Open all shards for idx := range dirs { path := dirs[idx] + conf.PATH_SEP + "db" var shd *shard shd, err = CreateShard(store, cnf, path, clearStored) if err != nil { lg.Errorf("Error creating shard %s: %s\n", path, err.Error()) return nil, err } store.shards = append(store.shards, shd) } for idx := range store.shards { shd := store.shards[idx] shd.exited = make(chan bool, 1) go shd.processIncoming() } return store, nil }
// Create a new datastore loader. // Initializes the loader, but does not load any leveldb instances. func NewDataStoreLoader(cnf *conf.Config) *DataStoreLoader { dld := &DataStoreLoader{ lg: common.NewLogger("datastore", cnf), ClearStored: cnf.GetBool(conf.HTRACE_DATA_STORE_CLEAR), } dld.readOpts = levigo.NewReadOptions() dld.readOpts.SetFillCache(true) dld.readOpts.SetVerifyChecksums(false) dld.writeOpts = levigo.NewWriteOptions() dld.writeOpts.SetSync(false) dirsStr := cnf.Get(conf.HTRACE_DATA_STORE_DIRECTORIES) rdirs := strings.Split(dirsStr, conf.PATH_LIST_SEP) // Filter out empty entries dirs := make([]string, 0, len(rdirs)) for i := range rdirs { if strings.TrimSpace(rdirs[i]) != "" { dirs = append(dirs, rdirs[i]) } } dld.shards = make([]*ShardLoader, len(dirs)) for i := range dirs { dld.shards[i] = &ShardLoader{ dld: dld, path: dirs[i] + conf.PATH_SEP + "db", } } dld.openOpts = levigo.NewOptions() cacheSize := cnf.GetInt(conf.HTRACE_LEVELDB_CACHE_SIZE) dld.openOpts.SetCache(levigo.NewLRUCache(cacheSize)) dld.openOpts.SetParanoidChecks(false) writeBufferSize := cnf.GetInt(conf.HTRACE_LEVELDB_WRITE_BUFFER_SIZE) if writeBufferSize > 0 { dld.openOpts.SetWriteBufferSize(writeBufferSize) } maxFdPerShard := dld.calculateMaxOpenFilesPerShard() if maxFdPerShard > 0 { dld.openOpts.SetMaxOpenFiles(maxFdPerShard) } return dld }
func TestHeartbeaterSendsHeartbeats(t *testing.T) { cnfBld := conf.Builder{ Values: conf.TEST_VALUES(), Defaults: conf.DEFAULTS, } cnf, err := cnfBld.Build() if err != nil { t.Fatalf("failed to create conf: %s", err.Error()) } lg := common.NewLogger("heartbeater", cnf) // The minimum amount of time which the heartbeater test should take MINIMUM_TEST_DURATION := time.Millisecond * (NUM_TEST_HEARTBEATS * HEARTBEATER_PERIOD) duration := MINIMUM_TEST_DURATION for duration <= MINIMUM_TEST_DURATION { start := time.Now() testHeartbeaterSendsHeartbeatsImpl(t, lg) end := time.Now() duration = end.Sub(start) lg.Debugf("Measured duration: %v; minimum expected duration: %v\n", duration, MINIMUM_TEST_DURATION) } }
func main() { for idx := range os.Args { arg := os.Args[idx] if strings.HasPrefix(arg, "--h") || strings.HasPrefix(arg, "-h") { fmt.Fprintf(os.Stderr, USAGE) os.Exit(0) } } // Load the htraced configuration. cnf, cnfLog := conf.LoadApplicationConfig("htraced.") // Open the HTTP port. // We want to do this first, before initializing the datastore or setting up // logging. That way, if someone accidentally starts two daemons with the // same config file, the second invocation will exit with a "port in use" // error rather than potentially disrupting the first invocation. rstListener, listenErr := net.Listen("tcp", cnf.Get(conf.HTRACE_WEB_ADDRESS)) if listenErr != nil { fmt.Fprintf(os.Stderr, "Error opening HTTP port: %s\n", listenErr.Error()) os.Exit(1) } // Print out the startup banner and information about the daemon // configuration. lg := common.NewLogger("main", cnf) defer lg.Close() lg.Infof("*** Starting htraced %s [%s]***\n", RELEASE_VERSION, GIT_VERSION) scanner := bufio.NewScanner(cnfLog) for scanner.Scan() { lg.Infof(scanner.Text() + "\n") } common.InstallSignalHandlers(cnf) if runtime.GOMAXPROCS(0) == 1 { ncpu := runtime.NumCPU() runtime.GOMAXPROCS(ncpu) lg.Infof("setting GOMAXPROCS=%d\n", ncpu) } else { lg.Infof("GOMAXPROCS=%d\n", runtime.GOMAXPROCS(0)) } lg.Infof("leveldb version=%d.%d\n", levigo.GetLevelDBMajorVersion(), levigo.GetLevelDBMinorVersion()) // Initialize the datastore. store, err := CreateDataStore(cnf, nil) if err != nil { lg.Errorf("Error creating datastore: %s\n", err.Error()) os.Exit(1) } var rsv *RestServer rsv, err = CreateRestServer(cnf, store, rstListener) if err != nil { lg.Errorf("Error creating REST server: %s\n", err.Error()) os.Exit(1) } var hsv *HrpcServer if cnf.Get(conf.HTRACE_HRPC_ADDRESS) != "" { hsv, err = CreateHrpcServer(cnf, store, nil) if err != nil { lg.Errorf("Error creating HRPC server: %s\n", err.Error()) os.Exit(1) } } else { lg.Infof("Not starting HRPC server because no value was given for %s.\n", conf.HTRACE_HRPC_ADDRESS) } naddr := cnf.Get(conf.HTRACE_STARTUP_NOTIFICATION_ADDRESS) if naddr != "" { notif := StartupNotification{ HttpAddr: rsv.Addr().String(), ProcessId: os.Getpid(), } if hsv != nil { notif.HrpcAddr = hsv.Addr().String() } err = sendStartupNotification(naddr, ¬if) if err != nil { fmt.Fprintf(os.Stderr, "Failed to send startup notification: "+ "%s\n", err.Error()) os.Exit(1) } } for { time.Sleep(time.Duration(10) * time.Hour) } }
func (bld *MiniHTracedBuilder) Build() (*MiniHTraced, error) { var err error var store *dataStore var rsv *RestServer var hsv *HrpcServer if bld.Name == "" { bld.Name = "HTraceTest" } if bld.Cnf == nil { bld.Cnf = make(map[string]string) } if bld.DataDirs == nil { bld.DataDirs = make([]string, 2) } for idx := range bld.DataDirs { if bld.DataDirs[idx] == "" { bld.DataDirs[idx], err = ioutil.TempDir(os.TempDir(), fmt.Sprintf("%s%d", bld.Name, idx+1)) if err != nil { return nil, err } } } // Copy the default test configuration values. for k, v := range conf.TEST_VALUES() { _, hasVal := bld.Cnf[k] if !hasVal { bld.Cnf[k] = v } } bld.Cnf[conf.HTRACE_DATA_STORE_DIRECTORIES] = strings.Join(bld.DataDirs, conf.PATH_LIST_SEP) cnfBld := conf.Builder{Values: bld.Cnf, Defaults: conf.DEFAULTS} cnf, err := cnfBld.Build() if err != nil { return nil, err } lg := common.NewLogger("mini.htraced", cnf) defer func() { if err != nil { if store != nil { store.Close() } for idx := range bld.DataDirs { if !bld.KeepDataDirsOnClose { if bld.DataDirs[idx] != "" { os.RemoveAll(bld.DataDirs[idx]) } } } if rsv != nil { rsv.Close() } lg.Infof("Failed to create MiniHTraced %s: %s\n", bld.Name, err.Error()) lg.Close() } }() store, err = CreateDataStore(cnf, bld.WrittenSpans) if err != nil { return nil, err } rstListener, listenErr := net.Listen("tcp", cnf.Get(conf.HTRACE_WEB_ADDRESS)) if listenErr != nil { return nil, listenErr } defer func() { if rstListener != nil { rstListener.Close() } }() rsv, err = CreateRestServer(cnf, store, rstListener) if err != nil { return nil, err } rstListener = nil hsv, err = CreateHrpcServer(cnf, store, bld.HrpcTestHooks) if err != nil { return nil, err } lg.Infof("Created MiniHTraced %s\n", bld.Name) return &MiniHTraced{ Name: bld.Name, Cnf: cnf, DataDirs: bld.DataDirs, Store: store, Rsv: rsv, Hsv: hsv, Lg: lg, KeepDataDirsOnClose: bld.KeepDataDirsOnClose, }, nil }
func main() { // Load htraced configuration cnf, cnfLog := conf.LoadApplicationConfig("htrace.tool.") lg := common.NewLogger("conf", cnf) defer lg.Close() scanner := bufio.NewScanner(cnfLog) for scanner.Scan() { lg.Debugf(scanner.Text() + "\n") } // Parse argv app := kingpin.New(os.Args[0], USAGE) app.Flag("Dmy.key", "Set configuration key 'my.key' to 'my.value'. Replace 'my.key' "+ "with any key you want to set.").Default("my.value").String() addr := app.Flag("addr", "Server address.").String() verbose = *app.Flag("verbose", "Verbose.").Default("false").Bool() version := app.Command("version", "Print the version of this program.") serverVersion := app.Command("serverVersion", "Print the version of the htraced server.") serverStats := app.Command("serverStats", "Print statistics retrieved from the htraced server.") serverStatsJson := serverStats.Flag("json", "Display statistics as raw JSON.").Default("false").Bool() serverDebugInfo := app.Command("serverDebugInfo", "Print the debug info of the htraced server.") serverConf := app.Command("serverConf", "Print the server configuration retrieved from the htraced server.") findSpan := app.Command("findSpan", "Print information about a trace span with a given ID.") findSpanId := findSpan.Arg("id", "Span ID to find. Example: be305e54-4534-2110-a0b2-e06b9effe112").Required().String() findChildren := app.Command("findChildren", "Print out the span IDs that are children of a given span ID.") parentSpanId := findChildren.Arg("id", "Span ID to print children for. Example: be305e54-4534-2110-a0b2-e06b9effe112"). Required().String() childLim := findChildren.Flag("lim", "Maximum number of child IDs to print.").Default("20").Int() loadFile := app.Command("loadFile", "Write whitespace-separated JSON spans from a file to the server.") loadFilePath := loadFile.Arg("path", "A file containing whitespace-separated span JSON.").Required().String() loadJson := app.Command("load", "Write JSON spans from the command-line to the server.") loadJsonArg := loadJson.Arg("json", "A JSON span to write to the server.").Required().String() dumpAll := app.Command("dumpAll", "Dump all spans from the htraced daemon.") dumpAllOutPath := dumpAll.Arg("path", "The path to dump the trace spans to.").Default("-").String() dumpAllLim := dumpAll.Flag("lim", "The number of spans to transfer from the server at once."). Default("100").Int() graph := app.Command("graph", "Visualize span JSON as a graph.") graphJsonFile := graph.Arg("input", "The JSON file to load").Required().String() graphDotFile := graph.Flag("output", "The path to write a GraphViz dotfile to. This file can be used as input to "+ "GraphViz, in order to generate a pretty picture. See graphviz.org for more "+ "information about generating pictures of graphs.").Default("-").String() query := app.Command("query", "Send a query to htraced.") queryLim := query.Flag("lim", "Maximum number of spans to retrieve.").Default("20").Int() queryArg := query.Arg("query", "The query string to send. Query strings have the format "+ "[TYPE] [OPERATOR] [CONST], joined by AND statements.").Required().String() rawQuery := app.Command("rawQuery", "Send a raw JSON query to htraced.") rawQueryArg := rawQuery.Arg("json", "The query JSON to send.").Required().String() cmd := kingpin.MustParse(app.Parse(os.Args[1:])) // Add the command-line settings into the configuration. if *addr != "" { cnf = cnf.Clone(conf.HTRACE_WEB_ADDRESS, *addr) } // Handle commands that don't require an HTrace client. switch cmd { case version.FullCommand(): os.Exit(printVersion()) case graph.FullCommand(): err := jsonSpanFileToDotFile(*graphJsonFile, *graphDotFile) if err != nil { fmt.Printf("graphing error: %s\n", err.Error()) os.Exit(EXIT_FAILURE) } os.Exit(EXIT_SUCCESS) } // Create HTrace client hcl, err := htrace.NewClient(cnf, nil) if err != nil { fmt.Printf("Failed to create HTrace client: %s\n", err.Error()) os.Exit(EXIT_FAILURE) } // Handle commands that require an HTrace client. switch cmd { case version.FullCommand(): os.Exit(printVersion()) case serverVersion.FullCommand(): os.Exit(printServerVersion(hcl)) case serverStats.FullCommand(): if *serverStatsJson { os.Exit(printServerStatsJson(hcl)) } else { os.Exit(printServerStats(hcl)) } case serverDebugInfo.FullCommand(): os.Exit(printServerDebugInfo(hcl)) case serverConf.FullCommand(): os.Exit(printServerConfJson(hcl)) case findSpan.FullCommand(): var id *common.SpanId id.FromString(*findSpanId) os.Exit(doFindSpan(hcl, *id)) case findChildren.FullCommand(): var id *common.SpanId id.FromString(*parentSpanId) os.Exit(doFindChildren(hcl, *id, *childLim)) case loadJson.FullCommand(): os.Exit(doLoadSpanJson(hcl, *loadJsonArg)) case loadFile.FullCommand(): os.Exit(doLoadSpanJsonFile(hcl, *loadFilePath)) case dumpAll.FullCommand(): err := doDumpAll(hcl, *dumpAllOutPath, *dumpAllLim) if err != nil { fmt.Printf("dumpAll error: %s\n", err.Error()) os.Exit(EXIT_FAILURE) } os.Exit(EXIT_SUCCESS) case query.FullCommand(): err := doQueryFromString(hcl, *queryArg, *queryLim) if err != nil { fmt.Printf("query error: %s\n", err.Error()) os.Exit(EXIT_FAILURE) } os.Exit(EXIT_SUCCESS) case rawQuery.FullCommand(): err := doRawQuery(hcl, *rawQueryArg) if err != nil { fmt.Printf("raw query error: %s\n", err.Error()) os.Exit(EXIT_FAILURE) } os.Exit(EXIT_SUCCESS) } app.UsageErrorf(os.Stderr, "You must supply a command to run.") }
func (bld *MiniHTracedBuilder) Build() (*MiniHTraced, error) { var err error var store *dataStore var rsv *RestServer var hsv *HrpcServer if bld.Name == "" { bld.Name = "HTraceTest" } if bld.Cnf == nil { bld.Cnf = make(map[string]string) } if bld.DataDirs == nil { bld.DataDirs = make([]string, 2) } for idx := range bld.DataDirs { if bld.DataDirs[idx] == "" { bld.DataDirs[idx], err = ioutil.TempDir(os.TempDir(), fmt.Sprintf("%s%d", bld.Name, idx+1)) if err != nil { return nil, err } } } bld.Cnf[conf.HTRACE_DATA_STORE_DIRECTORIES] = strings.Join(bld.DataDirs, conf.PATH_LIST_SEP) bld.Cnf[conf.HTRACE_WEB_ADDRESS] = ":0" // use a random port for the REST server bld.Cnf[conf.HTRACE_HRPC_ADDRESS] = ":0" // use a random port for the HRPC server bld.Cnf[conf.HTRACE_LOG_LEVEL] = "TRACE" cnfBld := conf.Builder{Values: bld.Cnf, Defaults: conf.DEFAULTS} cnf, err := cnfBld.Build() if err != nil { return nil, err } lg := common.NewLogger("mini.htraced", cnf) defer func() { if err != nil { if store != nil { store.Close() } for idx := range bld.DataDirs { if bld.DataDirs[idx] != "" { os.RemoveAll(bld.DataDirs[idx]) } } if rsv != nil { rsv.Close() } lg.Infof("Failed to create MiniHTraced %s: %s\n", bld.Name, err.Error()) lg.Close() } }() store, err = CreateDataStore(cnf, bld.WrittenSpans) if err != nil { return nil, err } rsv, err = CreateRestServer(cnf, store) if err != nil { return nil, err } hsv, err = CreateHrpcServer(cnf, store) if err != nil { return nil, err } lg.Infof("Created MiniHTraced %s\n", bld.Name) return &MiniHTraced{ Name: bld.Name, Cnf: cnf, DataDirs: bld.DataDirs, Store: store, Rsv: rsv, Hsv: hsv, Lg: lg, KeepDataDirsOnClose: bld.KeepDataDirsOnClose, }, nil }