diff --git a/CHANGELOG.md b/CHANGELOG.md index 02ae283036..e4e9b50956 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - [#1758](https://github.com/influxdb/influxdb/pull/1758): Add Graphite Integration Test. - [#1929](https://github.com/influxdb/influxdb/pull/1929): Default Retention Policy incorrectly auto created. - [#1930](https://github.com/influxdb/influxdb/pull/1930): Auto create database for graphite if not specified. +- [#1908](https://github.com/influxdb/influxdb/pull/1908): Cosmetic CLI output fixes. - [#1931](https://github.com/influxdb/influxdb/pull/1931): Add default column to SHOW RETENTION POLICIES. ### Features diff --git a/cmd/influx/main.go b/cmd/influx/main.go index 3afdb5ccd1..31673e162c 100644 --- a/cmd/influx/main.go +++ b/cmd/influx/main.go @@ -10,6 +10,7 @@ import ( "os" "os/user" "path/filepath" + "sort" "strconv" "strings" "text/tabwriter" @@ -267,20 +268,20 @@ func (c *CommandLine) executeQuery(query string) { func (c *CommandLine) FormatResults(results *client.Results, w io.Writer) { switch c.Format { case "json": - WriteJSON(results, c.Pretty, w) + c.writeJSON(results, w) case "csv": - WriteCSV(results, w) + c.writeCSV(results, w) case "column": - WriteColumns(results, w) + c.writeColumns(results, w) default: fmt.Fprintf(w, "Unknown output format %q.\n", c.Format) } } -func WriteJSON(results *client.Results, pretty bool, w io.Writer) { +func (c *CommandLine) writeJSON(results *client.Results, w io.Writer) { var data []byte var err error - if pretty { + if c.Pretty { data, err = json.MarshalIndent(results, "", " ") } else { data, err = json.Marshal(results) @@ -292,11 +293,11 @@ func WriteJSON(results *client.Results, pretty bool, w io.Writer) { fmt.Fprintln(w, string(data)) } -func WriteCSV(results *client.Results, w io.Writer) { +func (c *CommandLine) writeCSV(results *client.Results, w io.Writer) { csvw := csv.NewWriter(w) for _, result := range results.Results { // Create a tabbed writer for each result as they won't always line up - rows := resultToCSV(result, "\t", false) + rows := c.formatResults(result, "\t") for _, r := range rows { csvw.Write(strings.Split(r, "\t")) } @@ -304,12 +305,12 @@ func WriteCSV(results *client.Results, w io.Writer) { } } -func WriteColumns(results *client.Results, w io.Writer) { +func (c *CommandLine) writeColumns(results *client.Results, w io.Writer) { for _, result := range results.Results { // Create a tabbed writer for each result a they won't always line up w := new(tabwriter.Writer) w.Init(os.Stdout, 0, 8, 1, '\t', 0) - csv := resultToCSV(result, "\t", true) + csv := c.formatResults(result, "\t") for _, r := range csv { fmt.Fprintln(w, r) } @@ -317,40 +318,86 @@ func WriteColumns(results *client.Results, w io.Writer) { } } -func resultToCSV(result client.Result, seperator string, headerLines bool) []string { +// formatResults will behave differently if you are formatting for columns or csv +func (c *CommandLine) formatResults(result client.Result, separator string) []string { rows := []string{} // Create a tabbed writer for each result a they won't always line up - columnNames := []string{"name", "tags"} - for i, row := range result.Series { - // Output the column headings - if i == 0 { - for _, column := range row.Columns { - columnNames = append(columnNames, column) - } - rows = append(rows, strings.Join(columnNames, seperator)) - } - if headerLines { - // create column underscores - lines := []string{} - for _, columnName := range columnNames { - lines = append(lines, strings.Repeat("-", len(columnName))) - } - rows = append(rows, strings.Join(lines, seperator)) - } // gather tags tags := []string{} for k, v := range row.Tags { tags = append(tags, fmt.Sprintf("%s=%s", k, v)) + sort.Strings(tags) } + + columnNames := []string{} + + // Only put name/tags in a column if format is csv + if c.Format == "csv" { + if len(tags) > 0 { + columnNames = append([]string{"tags"}, columnNames...) + } + + if row.Name != "" { + columnNames = append([]string{"name"}, columnNames...) + } + } + + for _, column := range row.Columns { + columnNames = append(columnNames, column) + } + + // Output a line separator if we have more than one set or results and format is column + if i > 0 && c.Format == "column" { + rows = append(rows, "") + } + + // If we are column format, we break out the name/tag to seperate lines + if c.Format == "column" { + if row.Name != "" { + n := fmt.Sprintf("name: %s", row.Name) + rows = append(rows, n) + if len(tags) == 0 { + l := strings.Repeat("-", len(n)) + rows = append(rows, l) + } + } + if len(tags) > 0 { + t := fmt.Sprintf("tags: %s", (strings.Join(tags, ", "))) + rows = append(rows, t) + } + } + + rows = append(rows, strings.Join(columnNames, separator)) + + // if format is column, break tags to their own line/format + if c.Format == "column" && len(tags) > 0 { + lines := []string{} + for _, columnName := range columnNames { + lines = append(lines, strings.Repeat("-", len(columnName))) + } + rows = append(rows, strings.Join(lines, separator)) + } + for _, v := range row.Values { - values := []string{row.Name} - values = append(values, strings.Join(tags, ",")) + var values []string + if c.Format == "csv" { + if row.Name != "" { + values = append(values, row.Name) + } + if len(tags) > 0 { + values = append(values, strings.Join(tags, ",")) + } + } for _, vv := range v { values = append(values, interfaceToString(vv)) } - rows = append(rows, strings.Join(values, seperator)) + rows = append(rows, strings.Join(values, separator)) + } + // Outout a line separator if in column format + if c.Format == "column" { + rows = append(rows, "") } } return rows diff --git a/tests/create_write_single_with_multiple_measurements_values_tags.sh b/tests/create_write_single_with_multiple_measurements_values_tags.sh new file mode 100755 index 0000000000..f7ce8682ed --- /dev/null +++ b/tests/create_write_single_with_multiple_measurements_values_tags.sh @@ -0,0 +1,23 @@ +echo "creating database" +curl -G http://localhost:8086/query --data-urlencode "q=CREATE DATABASE foo" + +echo "creating retention policy" +curl -G http://localhost:8086/query --data-urlencode "q=CREATE RETENTION POLICY bar ON foo DURATION 300d REPLICATION 3 DEFAULT" + +echo "inserting data" +curl -d '{"database" : "foo", "retentionPolicy" : "bar", "points": [{"name": "cpu", "timestamp": "2015-02-26T22:01:11.703Z","fields": {"value": 8.9}}]}' -H "Content-Type: application/json" http://localhost:8086/write +curl -d '{"database" : "foo", "retentionPolicy" : "bar", "points": [{"name": "cpu", "timestamp": "2015-02-27T22:01:11.703Z","fields": {"value": 1.3}}]}' -H "Content-Type: application/json" http://localhost:8086/write +curl -d '{"database" : "foo", "retentionPolicy" : "bar", "points": [{"name": "cpu", "timestamp": "2015-02-28T22:01:11.703Z","fields": {"value": 50.4}}]}' -H "Content-Type: application/json" http://localhost:8086/write + + +curl -d '{"database" : "foo", "retentionPolicy" : "bar", "points": [{"name": "mem", "tags": {"host": "server01"},"timestamp": "2015-02-26T22:01:11.703Z","fields": {"value": 16432}}]}' -H "Content-Type: application/json" http://localhost:8086/write +curl -d '{"database" : "foo", "retentionPolicy" : "bar", "points": [{"name": "mem", "tags": {"host": "server01"},"timestamp": "2015-02-27T22:01:11.703Z","fields": {"value": 23453}}]}' -H "Content-Type: application/json" http://localhost:8086/write +curl -d '{"database" : "foo", "retentionPolicy" : "bar", "points": [{"name": "mem", "tags": {"host": "server02"},"timestamp": "2015-02-28T22:01:11.703Z","fields": {"value": 90234}}]}' -H "Content-Type: application/json" http://localhost:8086/write + +curl -d '{"database" : "foo", "retentionPolicy" : "bar", "points": [{"name": "temp", "tags": {"host": "server01","region":"uswest"}, "timestamp": "2015-02-26T22:01:11.703Z","fields": {"value": 98.6}}]}' -H "Content-Type: application/json" http://localhost:8086/write +curl -d '{"database" : "foo", "retentionPolicy" : "bar", "points": [{"name": "temp", "tags": {"host": "server01","region":"useast"}, "timestamp": "2015-02-27T22:01:11.703Z","fields": {"value": 101.1}}]}' -H "Content-Type: application/json" http://localhost:8086/write +curl -d '{"database" : "foo", "retentionPolicy" : "bar", "points": [{"name": "temp", "tags": {"host": "server02","region":"useast"}, "timestamp": "2015-02-28T22:01:11.703Z","fields": {"value": 105.4}}]}' -H "Content-Type: application/json" http://localhost:8086/write + +curl -d '{"database" : "foo", "retentionPolicy" : "bar", "points": [{"name": "network", "tags": {"host": "server01","region":"uswest"},"timestamp": "2015-02-26T22:01:11.703Z","fields": {"rx": 2342,"tx": 9804}}]}' -H "Content-Type: application/json" http://localhost:8086/write +curl -d '{"database" : "foo", "retentionPolicy" : "bar", "points": [{"name": "network", "tags": {"host": "server01","region":"useast"},"timestamp": "2015-02-27T22:01:11.703Z","fields": {"rx": 4324,"tx": 7930}}]}' -H "Content-Type: application/json" http://localhost:8086/write +curl -d '{"database" : "foo", "retentionPolicy" : "bar", "points": [{"name": "network", "tags": {"host": "server02","region":"useast"},"timestamp": "2015-02-28T22:01:11.703Z","fields": {"rx": 2342,"tx": 8234}}]}' -H "Content-Type: application/json" http://localhost:8086/write