Implement "SHOW DIAGNOSTICS"

pull/2061/head
Philip O'Toole 2015-03-23 20:13:54 -07:00 committed by Philip O'Toole
parent fba41df82b
commit 1c440f8542
5 changed files with 139 additions and 1 deletions

View File

@ -79,6 +79,7 @@ func (*ShowRetentionPoliciesStatement) node() {}
func (*ShowMeasurementsStatement) node() {}
func (*ShowSeriesStatement) node() {}
func (*ShowStatsStatement) node() {}
func (*ShowDiagnosticsStatement) node() {}
func (*ShowTagKeysStatement) node() {}
func (*ShowTagValuesStatement) node() {}
func (*ShowUsersStatement) node() {}
@ -172,6 +173,7 @@ func (*ShowMeasurementsStatement) stmt() {}
func (*ShowRetentionPoliciesStatement) stmt() {}
func (*ShowSeriesStatement) stmt() {}
func (*ShowStatsStatement) stmt() {}
func (*ShowDiagnosticsStatement) stmt() {}
func (*ShowTagKeysStatement) stmt() {}
func (*ShowTagValuesStatement) stmt() {}
func (*ShowUsersStatement) stmt() {}
@ -1386,6 +1388,17 @@ func (s *ShowStatsStatement) RequiredPrivileges() ExecutionPrivileges {
return ExecutionPrivileges{{Name: "", Privilege: AllPrivileges}}
}
// ShowDiagnosticsStatement represents a command for show node diagnostics.
type ShowDiagnosticsStatement struct{}
// String returns a string representation of the ShowDiagnosticsStatement.
func (s *ShowDiagnosticsStatement) String() string { return "SHOW DIAGNOSTICS" }
// RequiredPrivileges returns the privilege required to execute a ShowDiagnosticsStatement
func (s *ShowDiagnosticsStatement) RequiredPrivileges() ExecutionPrivileges {
return ExecutionPrivileges{{Name: "", Privilege: AllPrivileges}}
}
// ShowTagKeysStatement represents a command for listing tag keys.
type ShowTagKeysStatement struct {
// Data source that fields are extracted from.

View File

@ -113,6 +113,8 @@ func (p *Parser) parseShowStatement() (Statement, error) {
return p.parseShowSeriesStatement()
case STATS:
return p.parseShowStatsStatement()
case DIAGNOSTICS:
return p.parseShowDiagnosticsStatement()
case TAG:
tok, pos, lit := p.scanIgnoreWhitespace()
if tok == KEYS {
@ -1193,6 +1195,12 @@ func (p *Parser) parseShowStatsStatement() (*ShowStatsStatement, error) {
return stmt, err
}
// parseShowDiagnostics parses a string and returns a ShowDiagnosticsStatement.
func (p *Parser) parseShowDiagnosticsStatement() (*ShowDiagnosticsStatement, error) {
stmt := &ShowDiagnosticsStatement{}
return stmt, nil
}
// parseDropContinuousQueriesStatement parses a string and returns a DropContinuousQueryStatement.
// This function assumes the "DROP CONTINUOUS" tokens have already been consumed.
func (p *Parser) parseDropContinuousQueryStatement() (*DropContinuousQueryStatement, error) {

View File

@ -771,6 +771,12 @@ func TestParser_ParseStatement(t *testing.T) {
},
},
// SHOW DIAGNOSTICS
{
s: `SHOW DIAGNOSTICS`,
stmt: &influxql.ShowDiagnosticsStatement{},
},
// Errors
{s: ``, err: `found EOF, expected SELECT, DELETE, SHOW, CREATE, DROP, GRANT, REVOKE, ALTER at line 1, char 1`},
{s: `SELECT`, err: `found EOF, expected identifier, string, number, bool at line 1, char 8`},

View File

@ -107,6 +107,7 @@ const (
SHOW
SLIMIT
STATS
DIAGNOSTICS
SOFFSET
TAG
TO
@ -210,6 +211,7 @@ var tokens = [...]string{
SLIMIT: "SLIMIT",
SOFFSET: "SOFFSET",
STATS: "STATS",
DIAGNOSTICS: "DIAGNOSTICS",
TAG: "TAG",
TO: "TO",
USER: "USER",

111
server.go
View File

@ -51,6 +51,12 @@ const (
retentionPolicyMinDuration = time.Hour
)
var startTime time.Time
func init() {
startTime = time.Now().UTC()
}
// Server represents a collection of metadata and raw metric data.
type Server struct {
mu sync.RWMutex
@ -2036,6 +2042,8 @@ func (s *Server) ExecuteQuery(q *influxql.Query, database string, user *User) Re
res = s.executeShowFieldKeysStatement(stmt, database, user)
case *influxql.ShowStatsStatement:
res = s.executeShowStatsStatement(stmt, user)
case *influxql.ShowDiagnosticsStatement:
res = s.executeShowDiagnosticsStatement(stmt, user)
case *influxql.GrantStatement:
res = s.executeGrantStatement(stmt, user)
case *influxql.RevokeStatement:
@ -2668,6 +2676,107 @@ func (s *Server) executeShowStatsStatement(stmt *influxql.ShowStatsStatement, us
return &Result{Series: rows}
}
func (s *Server) executeShowDiagnosticsStatement(stmt *influxql.ShowDiagnosticsStatement, user *User) *Result {
rows := make([]*influxql.Row, 0)
var m runtime.MemStats
runtime.ReadMemStats(&m)
hostname, err := os.Hostname()
if err != nil {
hostname = "unknown"
}
diags := []struct {
name string
fields map[string]interface{}
}{
{
name: "build",
fields: map[string]interface{}{
"version": s.Version,
"commitHash": s.CommitHash,
},
},
{
name: "server",
fields: map[string]interface{}{
"id": s.id,
"path": s.path,
"authEnabled": s.authenticationEnabled,
"index": s.index,
"retentionAutoCreate": s.RetentionAutoCreate,
"numShards": len(s.shards),
},
},
{
name: "cq",
fields: map[string]interface{}{
"lastRun": s.lastContinuousQueryRun,
},
},
{
name: "system",
fields: map[string]interface{}{
"startTime": startTime,
"uptime": time.Since(startTime).String(),
"hostname": hostname,
"pid": os.Getpid(),
"os": runtime.GOOS,
"arch": runtime.GOARCH,
"numcpu": runtime.NumCPU(),
},
},
{
name: "memory",
fields: map[string]interface{}{
"alloc": m.Alloc,
"totalAlloc": m.TotalAlloc,
"sys": m.Sys,
"lookups": m.Lookups,
"mallocs": m.Mallocs,
"frees": m.Frees,
"heapAlloc": m.HeapAlloc,
"heapSys": m.HeapSys,
"heapIdle": m.HeapIdle,
"heapInUse": m.HeapInuse,
"heapReleased": m.HeapReleased,
"heapObjects": m.HeapObjects,
"pauseTotalNs": m.PauseTotalNs,
"numGC": m.NumGC,
},
},
{
name: "go",
fields: map[string]interface{}{
"goMaxProcs": runtime.GOMAXPROCS(0),
"numGoroutine": runtime.NumGoroutine(),
"version": runtime.Version(),
},
},
}
for _, d := range diags {
row := &influxql.Row{Columns: []string{}}
row.Name = d.name
// Get sorted list of keys.
sortedKeys := make([]string, 0, len(d.fields))
for k, _ := range d.fields {
sortedKeys = append(sortedKeys, k)
}
sort.Strings(sortedKeys)
for _, k := range sortedKeys {
row.Columns = append(row.Columns, k)
row.Values = append(row.Values, []interface{}{d.fields[k]})
}
rows = append(rows, row)
}
return &Result{Series: rows}
}
// filterMeasurementsByExpr filters a list of measurements by a tags expression.
func filterMeasurementsByExpr(measurements Measurements, expr influxql.Expr) (Measurements, error) {
// Create a list to hold result measurements.
@ -3667,7 +3776,7 @@ func (s *Server) reportStats(clusterID uint64) {
"name":"reports",
"columns":["os", "arch", "version", "server_id", "id", "num_series", "num_measurements", "num_databases"],
"points":[["%s", "%s", "%s", "%x", "%x", "%d", "%d", "%d"]]
}]`, runtime.GOOS, runtime.GOARCH, version, s.ID(), clusterID, numSeries, numMeasurements, numDatabases)
}]`, runtime.GOOS, runtime.GOARCH, s.Version, s.ID(), clusterID, numSeries, numMeasurements, numDatabases)
data := bytes.NewBufferString(json)