| 
									
										
										
										
											2016-10-05 16:56:34 +08:00
										 |  |  | package influxdb | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-05 20:42:06 +08:00
										 |  |  | import ( | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2016-10-14 15:14:13 +08:00
										 |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2016-10-10 13:12:21 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/tsdb" | 
					
						
							| 
									
										
										
										
											2016-10-05 20:42:06 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var renders map[string]QueryDefinition | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-05 22:59:33 +08:00
										 |  |  | type DefinitionParameters struct { | 
					
						
							|  |  |  | 	Name string | 
					
						
							|  |  |  | 	Type string | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-05 20:42:06 +08:00
										 |  |  | type QueryDefinition struct { | 
					
						
							| 
									
										
										
										
											2016-10-13 17:42:51 +08:00
										 |  |  | 	Renderer func(query *Query, queryContext *tsdb.QueryContext, part *QueryPart, innerExpr string) string | 
					
						
							| 
									
										
										
										
											2016-10-05 22:59:33 +08:00
										 |  |  | 	Params   []DefinitionParameters | 
					
						
							| 
									
										
										
										
											2016-10-05 20:42:06 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func init() { | 
					
						
							|  |  |  | 	renders = make(map[string]QueryDefinition) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	renders["field"] = QueryDefinition{Renderer: fieldRenderer} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	renders["spread"] = QueryDefinition{Renderer: functionRenderer} | 
					
						
							|  |  |  | 	renders["count"] = QueryDefinition{Renderer: functionRenderer} | 
					
						
							|  |  |  | 	renders["distinct"] = QueryDefinition{Renderer: functionRenderer} | 
					
						
							|  |  |  | 	renders["integral"] = QueryDefinition{Renderer: functionRenderer} | 
					
						
							|  |  |  | 	renders["mean"] = QueryDefinition{Renderer: functionRenderer} | 
					
						
							|  |  |  | 	renders["median"] = QueryDefinition{Renderer: functionRenderer} | 
					
						
							|  |  |  | 	renders["sum"] = QueryDefinition{Renderer: functionRenderer} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-22 06:54:56 +08:00
										 |  |  | 	renders["holt_winters"] = QueryDefinition{ | 
					
						
							|  |  |  | 		Renderer: functionRenderer, | 
					
						
							|  |  |  | 		Params:   []DefinitionParameters{{Name: "number", Type: "number"}, {Name: "season", Type: "number"}}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	renders["holt_winters_with_fit"] = QueryDefinition{ | 
					
						
							|  |  |  | 		Renderer: functionRenderer, | 
					
						
							|  |  |  | 		Params:   []DefinitionParameters{{Name: "number", Type: "number"}, {Name: "season", Type: "number"}}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-05 20:42:06 +08:00
										 |  |  | 	renders["derivative"] = QueryDefinition{ | 
					
						
							|  |  |  | 		Renderer: functionRenderer, | 
					
						
							| 
									
										
										
										
											2016-10-05 22:59:33 +08:00
										 |  |  | 		Params:   []DefinitionParameters{{Name: "duration", Type: "interval"}}, | 
					
						
							| 
									
										
										
										
											2016-10-05 20:42:06 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	renders["non_negative_derivative"] = QueryDefinition{ | 
					
						
							|  |  |  | 		Renderer: functionRenderer, | 
					
						
							| 
									
										
										
										
											2016-10-05 22:59:33 +08:00
										 |  |  | 		Params:   []DefinitionParameters{{Name: "duration", Type: "interval"}}, | 
					
						
							| 
									
										
										
										
											2016-10-05 20:42:06 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	renders["difference"] = QueryDefinition{Renderer: functionRenderer} | 
					
						
							|  |  |  | 	renders["moving_average"] = QueryDefinition{ | 
					
						
							|  |  |  | 		Renderer: functionRenderer, | 
					
						
							| 
									
										
										
										
											2016-10-05 22:59:33 +08:00
										 |  |  | 		Params:   []DefinitionParameters{{Name: "window", Type: "number"}}, | 
					
						
							| 
									
										
										
										
											2016-10-05 20:42:06 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	renders["stddev"] = QueryDefinition{Renderer: functionRenderer} | 
					
						
							|  |  |  | 	renders["time"] = QueryDefinition{ | 
					
						
							|  |  |  | 		Renderer: functionRenderer, | 
					
						
							| 
									
										
										
										
											2016-12-22 06:54:56 +08:00
										 |  |  | 		Params:   []DefinitionParameters{{Name: "interval", Type: "time"}, {Name: "offset", Type: "time"}}, | 
					
						
							| 
									
										
										
										
											2016-10-05 20:42:06 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	renders["fill"] = QueryDefinition{ | 
					
						
							|  |  |  | 		Renderer: functionRenderer, | 
					
						
							| 
									
										
										
										
											2016-10-05 22:59:33 +08:00
										 |  |  | 		Params:   []DefinitionParameters{{Name: "fill", Type: "string"}}, | 
					
						
							| 
									
										
										
										
											2016-10-05 20:42:06 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	renders["elapsed"] = QueryDefinition{ | 
					
						
							|  |  |  | 		Renderer: functionRenderer, | 
					
						
							| 
									
										
										
										
											2016-10-05 22:59:33 +08:00
										 |  |  | 		Params:   []DefinitionParameters{{Name: "duration", Type: "interval"}}, | 
					
						
							| 
									
										
										
										
											2016-10-05 20:42:06 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	renders["bottom"] = QueryDefinition{ | 
					
						
							|  |  |  | 		Renderer: functionRenderer, | 
					
						
							| 
									
										
										
										
											2016-10-05 22:59:33 +08:00
										 |  |  | 		Params:   []DefinitionParameters{{Name: "count", Type: "int"}}, | 
					
						
							| 
									
										
										
										
											2016-10-05 20:42:06 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	renders["first"] = QueryDefinition{Renderer: functionRenderer} | 
					
						
							|  |  |  | 	renders["last"] = QueryDefinition{Renderer: functionRenderer} | 
					
						
							|  |  |  | 	renders["max"] = QueryDefinition{Renderer: functionRenderer} | 
					
						
							|  |  |  | 	renders["min"] = QueryDefinition{Renderer: functionRenderer} | 
					
						
							|  |  |  | 	renders["percentile"] = QueryDefinition{ | 
					
						
							|  |  |  | 		Renderer: functionRenderer, | 
					
						
							| 
									
										
										
										
											2016-10-05 22:59:33 +08:00
										 |  |  | 		Params:   []DefinitionParameters{{Name: "nth", Type: "int"}}, | 
					
						
							| 
									
										
										
										
											2016-10-05 20:42:06 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	renders["top"] = QueryDefinition{ | 
					
						
							|  |  |  | 		Renderer: functionRenderer, | 
					
						
							| 
									
										
										
										
											2016-10-05 22:59:33 +08:00
										 |  |  | 		Params:   []DefinitionParameters{{Name: "count", Type: "int"}}, | 
					
						
							| 
									
										
										
										
											2016-10-05 20:42:06 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	renders["tag"] = QueryDefinition{ | 
					
						
							|  |  |  | 		Renderer: fieldRenderer, | 
					
						
							| 
									
										
										
										
											2016-10-05 22:59:33 +08:00
										 |  |  | 		Params:   []DefinitionParameters{{Name: "tag", Type: "string"}}, | 
					
						
							| 
									
										
										
										
											2016-10-05 20:42:06 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	renders["math"] = QueryDefinition{Renderer: suffixRenderer} | 
					
						
							|  |  |  | 	renders["alias"] = QueryDefinition{Renderer: aliasRenderer} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-13 17:42:51 +08:00
										 |  |  | func fieldRenderer(query *Query, queryContext *tsdb.QueryContext, part *QueryPart, innerExpr string) string { | 
					
						
							| 
									
										
										
										
											2016-10-05 20:42:06 +08:00
										 |  |  | 	if part.Params[0] == "*" { | 
					
						
							|  |  |  | 		return "*" | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-10-05 22:59:33 +08:00
										 |  |  | 	return fmt.Sprintf(`"%s"`, part.Params[0]) | 
					
						
							| 
									
										
										
										
											2016-10-05 20:42:06 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-14 15:14:13 +08:00
										 |  |  | func getDefinedInterval(query *Query, queryContext *tsdb.QueryContext) string { | 
					
						
							|  |  |  | 	setInterval := strings.Replace(strings.Replace(query.Interval, "<", "", 1), ">", "", 1) | 
					
						
							|  |  |  | 	defaultInterval := tsdb.CalculateInterval(queryContext.TimeRange) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if strings.Contains(query.Interval, ">") { | 
					
						
							|  |  |  | 		parsedDefaultInterval, err := time.ParseDuration(defaultInterval) | 
					
						
							|  |  |  | 		parsedSetInterval, err2 := time.ParseDuration(setInterval) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if err == nil && err2 == nil && parsedDefaultInterval > parsedSetInterval { | 
					
						
							|  |  |  | 			return defaultInterval | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return setInterval | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-13 17:42:51 +08:00
										 |  |  | func functionRenderer(query *Query, queryContext *tsdb.QueryContext, part *QueryPart, innerExpr string) string { | 
					
						
							| 
									
										
										
										
											2016-10-14 15:14:13 +08:00
										 |  |  | 	for i, param := range part.Params { | 
					
						
							| 
									
										
										
										
											2016-12-21 17:01:20 +08:00
										 |  |  | 		if param == "$interval" || param == "auto" { | 
					
						
							| 
									
										
										
										
											2016-10-13 17:42:51 +08:00
										 |  |  | 			if query.Interval != "" { | 
					
						
							| 
									
										
										
										
											2016-10-14 15:14:13 +08:00
										 |  |  | 				part.Params[i] = getDefinedInterval(query, queryContext) | 
					
						
							| 
									
										
										
										
											2016-10-13 17:42:51 +08:00
										 |  |  | 			} else { | 
					
						
							|  |  |  | 				part.Params[i] = tsdb.CalculateInterval(queryContext.TimeRange) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2016-10-06 18:51:45 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-06 02:36:05 +08:00
										 |  |  | 	if innerExpr != "" { | 
					
						
							|  |  |  | 		part.Params = append([]string{innerExpr}, part.Params...) | 
					
						
							| 
									
										
										
										
											2016-10-05 20:42:06 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-06 02:36:05 +08:00
										 |  |  | 	params := strings.Join(part.Params, ", ") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return fmt.Sprintf("%s(%s)", part.Type, params) | 
					
						
							| 
									
										
										
										
											2016-10-05 20:42:06 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-13 17:42:51 +08:00
										 |  |  | func suffixRenderer(query *Query, queryContext *tsdb.QueryContext, part *QueryPart, innerExpr string) string { | 
					
						
							| 
									
										
										
										
											2016-10-05 20:42:06 +08:00
										 |  |  | 	return fmt.Sprintf("%s %s", innerExpr, part.Params[0]) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-13 17:42:51 +08:00
										 |  |  | func aliasRenderer(query *Query, queryContext *tsdb.QueryContext, part *QueryPart, innerExpr string) string { | 
					
						
							| 
									
										
										
										
											2016-10-05 20:42:06 +08:00
										 |  |  | 	return fmt.Sprintf(`%s AS "%s"`, innerExpr, part.Params[0]) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-13 17:42:51 +08:00
										 |  |  | func (r QueryDefinition) Render(query *Query, queryContext *tsdb.QueryContext, part *QueryPart, innerExpr string) string { | 
					
						
							|  |  |  | 	return r.Renderer(query, queryContext, part, innerExpr) | 
					
						
							| 
									
										
										
										
											2016-10-05 20:42:06 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-05 22:59:33 +08:00
										 |  |  | func NewQueryPart(typ string, params []string) (*QueryPart, error) { | 
					
						
							|  |  |  | 	def, exist := renders[typ] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if !exist { | 
					
						
							|  |  |  | 		return nil, fmt.Errorf("Missing query definition for %s", typ) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return &QueryPart{ | 
					
						
							|  |  |  | 		Type:   typ, | 
					
						
							|  |  |  | 		Params: params, | 
					
						
							|  |  |  | 		Def:    def, | 
					
						
							|  |  |  | 	}, nil | 
					
						
							| 
									
										
										
										
											2016-10-05 20:42:06 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type QueryPart struct { | 
					
						
							| 
									
										
										
										
											2016-10-05 22:59:33 +08:00
										 |  |  | 	Def    QueryDefinition | 
					
						
							| 
									
										
										
										
											2016-10-05 20:42:06 +08:00
										 |  |  | 	Type   string | 
					
						
							|  |  |  | 	Params []string | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-13 17:42:51 +08:00
										 |  |  | func (qp *QueryPart) Render(query *Query, queryContext *tsdb.QueryContext, expr string) string { | 
					
						
							|  |  |  | 	return qp.Def.Renderer(query, queryContext, qp, expr) | 
					
						
							| 
									
										
										
										
											2016-10-05 16:56:34 +08:00
										 |  |  | } |