From f03d4037828fe021109c49d8afad3881c76114cb Mon Sep 17 00:00:00 2001 From: stack Date: Sat, 7 Feb 2015 21:52:23 -0800 Subject: [PATCH] HTRACE-105 Cleanup our REST vocabulary supported by htraced Changes /writeSpans to /span POST In htraced, beefed up the help output with REST examples. Changed the supported REST removing /writeSpans and GET against / of a span id. Instead, to write, you POST to /span. You then GET against /span/ID, etc. Removed PathPrefix("/span"). Couldn't make POST and GET on same path work. In htrace client, small edit of usage. In java REST client, changes to match new REST paths. Also 'fixed' an overwrite issue if doing many span POSTs at a time. --- .../src/go/src/org/apache/htrace/client/client.go | 2 +- .../src/go/src/org/apache/htrace/htrace/cmd.go | 4 +- .../go/src/org/apache/htrace/htraced/htraced.go | 45 +++++++++++++++++----- .../src/go/src/org/apache/htrace/htraced/rest.go | 15 ++++---- .../apache/htrace/impl/HTracedRESTReceiver.java | 25 +++++++++--- 5 files changed, 65 insertions(+), 26 deletions(-) diff --git a/htrace-core/src/go/src/org/apache/htrace/client/client.go b/htrace-core/src/go/src/org/apache/htrace/client/client.go index 82400fe..808de95 100644 --- a/htrace-core/src/go/src/org/apache/htrace/client/client.go +++ b/htrace-core/src/go/src/org/apache/htrace/client/client.go @@ -82,7 +82,7 @@ func (hcl *Client) WriteSpan(span *common.Span) error { if err != nil { return err } - _, _, err = hcl.makeRestRequest("POST", "writeSpans", bytes.NewReader(buf)) + _, _, err = hcl.makeRestRequest("POST", "span", bytes.NewReader(buf)) if err != nil { return err } diff --git a/htrace-core/src/go/src/org/apache/htrace/htrace/cmd.go b/htrace-core/src/go/src/org/apache/htrace/htrace/cmd.go index 7007343..eb35600 100644 --- a/htrace-core/src/go/src/org/apache/htrace/htrace/cmd.go +++ b/htrace-core/src/go/src/org/apache/htrace/htrace/cmd.go @@ -55,11 +55,11 @@ func main() { 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() + addr := app.Flag("web.address", "Server address, hostname:port.").String() verbose = app.Flag("verbose", "Verbose.").Default("false").Bool() version := app.Command("version", "Print the version of this program.") serverInfo := app.Command("serverInfo", "Print information retrieved from an htraced server.") - findSpan := app.Command("findSpan", "Print information about a trace span with a given ID.") + findSpan := app.Command("findSpan", "Print trace span with given ID. ID is a zero padded, 16-character hexadecimal.") findSpanId := findSpan.Arg("id", "Span ID to find. Example: 0x123456789abcdef").Required().Uint64() 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: 0x123456789abcdef"). diff --git a/htrace-core/src/go/src/org/apache/htrace/htraced/htraced.go b/htrace-core/src/go/src/org/apache/htrace/htraced/htraced.go index d2cbafc..9173dc8 100644 --- a/htrace-core/src/go/src/org/apache/htrace/htraced/htraced.go +++ b/htrace-core/src/go/src/org/apache/htrace/htraced/htraced.go @@ -33,24 +33,51 @@ var GIT_VERSION string const USAGE = `htraced: the HTrace server daemon. -htraced receives trace spans sent from HTrace clients. It exposes a REST -interface which others can query. It also runs a web server with a graphical -user interface. htraced stores its span data in levelDB files on the local -disks. +htraced receives JSON trace spans sent from HTrace clients. It exposes a +REST interface. It also runs a web server with a graphical user interface. +htraced stores its span data in levelDB files on the local disks. Usage: ---help: this help message + --help This help message --Dk=v: set configuration key 'k' to value 'v' -For example -Dweb.address=127.0.0.1:8080 sets the web address to localhost, -port 8080. + -Dk=v Set configuration key 'k' to value 'v'. For example, + -Dweb.address=127.0.0.1:8080 sets the web address to localhost, + port 8080. --Dk: set configuration key 'k' to 'true' + -Dk Set configuration key 'k' to 'true' Normally, configuration options should be set in the ` + conf.CONFIG_FILE_NAME + ` configuration file. We find this file by searching the paths in the ` + conf.HTRACED_CONF_DIR + `. The command-line options are just an alternate way of setting configuration when launching the daemon. + +REST examples: +Using curl (http://curl.haxx.se/), to query htraced server vitals: + + $ curl -v http://localhost:9095/server/info + +This will return the server version and git hash as JSON. + +To write a JSON trace span to htraced: + + $ curl -v --data-binary \ + '{"i":"0000000000000000","s":"0000000000000000","b":0,"e":0,"d":null,"r":null,"p":["0000000000000001"]}' \ + http://localhost:9097/span + +Note, that all ids in spans are zero-padded 16 character hexadecimals. +To query htraced for the span we just wrote: + + $ curl -v http://localhost:9097/span/0000000000000000 + +To query the first 10 ids of a spans' children: + + $ curl -v http://localhost:9097/span/0000000000000000/children?lim=10 + +There is also a basic query language at: + + $ curl -v http://localhost:9097/query?QUERY + +Also see the htrace client. It provides a clean command-line interface to htraced. ` func main() { diff --git a/htrace-core/src/go/src/org/apache/htrace/htraced/rest.go b/htrace-core/src/go/src/org/apache/htrace/htraced/rest.go index 9cdab20..30214ec 100644 --- a/htrace-core/src/go/src/org/apache/htrace/htraced/rest.go +++ b/htrace-core/src/go/src/org/apache/htrace/htraced/rest.go @@ -262,20 +262,19 @@ func CreateRestServer(cnf *conf.Config, store *dataStore) (*RestServer, error) { r.Handle("/server/info", &serverInfoHandler{lg: rsv.lg}).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") + writeSpansH := &writeSpansHandler{dataStoreHandler: dataStoreHandler{ + store: store, lg: rsv.lg}} + r.Handle("/span", writeSpansH).Methods("POST") findChildrenH := &findChildrenHandler{dataStoreHandler: dataStoreHandler{store: store, lg: rsv.lg}} - span.Handle("/{id}/children", findChildrenH).Methods("GET") + r.Handle("/span/{id}/children", findChildrenH).Methods("GET") + + findSidH := &findSidHandler{dataStoreHandler: dataStoreHandler{store: store, lg: rsv.lg}} + r.Handle("/span/{id}", findSidH).Methods("GET") // Default Handler. This will serve requests for static requests. r.PathPrefix("/").Handler(&defaultServeHandler{lg: rsv.lg}).Methods("GET") diff --git a/htrace-htraced/src/main/java/org/apache/htrace/impl/HTracedRESTReceiver.java b/htrace-htraced/src/main/java/org/apache/htrace/impl/HTracedRESTReceiver.java index 35cd332..0661a27 100644 --- a/htrace-htraced/src/main/java/org/apache/htrace/impl/HTracedRESTReceiver.java +++ b/htrace-htraced/src/main/java/org/apache/htrace/impl/HTracedRESTReceiver.java @@ -151,7 +151,7 @@ public class HTracedRESTReceiver implements SpanReceiver { // Build up the writeSpans URL. URL restServer = new URL(conf.get(HTRACED_REST_URL_KEY, HTRACED_REST_URL_DEFAULT)); URL url = - new URL(restServer.getProtocol(), restServer.getHost(), restServer.getPort(), "/writeSpans"); + new URL(restServer.getProtocol(), restServer.getHost(), restServer.getPort(), "/span"); this.writeSpansRESTURL = url.toString(); // Make a scheduler with one thread to run our POST of spans on a period. this.scheduler = Executors.newScheduledThreadPool(1); @@ -183,21 +183,34 @@ public class HTracedRESTReceiver implements SpanReceiver { @Override public void run() { Span span = null; - // Cycle until we drain queue. Send maxToSendAtATime if more than this in queue. + StringBuffer stringBuffer = null; + // Cycle until we drain queue. Send in batches of maxToSendAtATime. while ((span = this.q.poll()) != null) { // We got a span. Send at least this one span. Request request = httpClient.newRequest(writeSpansRESTURL).method(HttpMethod.POST); request.header(HttpHeader.CONTENT_TYPE, "application/json"); int count = 1; - request.content(new StringContentProvider(span.toJson())); - // Drain queue or until we have maxToSendAtATime spans, if more than just one. + String json = span.toJson(); + if (stringBuffer == null) { + // Make a guess at the size of the StringBuffer we'll need to accumulate stuff in. Make it + // count of elements times size of current span times two to avoid resize + int spanCount = Math.min(this.maxToSendAtATime, this.q.size() + 1); + stringBuffer = new StringBuffer(spanCount * json.length() * 2); + } else { + // Reuse already allocated buffer. Zero it. + stringBuffer.setLength(0); + } + // Add current json. + stringBuffer.append(json); + // Drain queue or until we have maxToSendAtATime spans. Accumulate in stringBuffer. while ((span = this.q.poll()) != null) { - request.content(new StringContentProvider(span.toJson())); + stringBuffer.append(span.toJson()); count++; // If we've accumulated sufficient to send, go ahead and send what we have. Can do the // rest in out next go around. if (count > this.maxToSendAtATime) break; } + request.content(new StringContentProvider(stringBuffer.toString())); try { ContentResponse response = request.send(); if (response.getStatus() == HttpStatus.OK_200) { @@ -250,4 +263,4 @@ public class HTracedRESTReceiver implements SpanReceiver { } } } -} +} \ No newline at end of file -- 2.2.1