Пример #1
0
func (server *Server) execTemplate(writer http.ResponseWriter, status int, data interface{}, files ...string) error {
	var err error

	tmpl := template.New(path.Base(files[0])).Funcs(template.FuncMap{
		"asset":  server.templateAsset,
		"dump":   templateDumpMap,
		"eq":     templateEqual,
		"hl":     templateHighlight,
		"ne":     templateNotEqual,
		"substr": templateSubstr,
	})

	// Execute template
	tmpl, err = tmpl.ParseFiles(files...)
	if err != nil {
		return err
	}

	tmplData := bytes.NewBuffer(nil)

	err = tmpl.Execute(tmplData, data)
	if err != nil {
		return err
	}

	writer.WriteHeader(status)

	if utils.HTTPGetContentType(writer) == "text/xml" {
		writer.Write([]byte("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"))
	}

	writer.Write(tmplData.Bytes())

	return err
}
Пример #2
0
func kairosdbCheckBackendResponse(r *http.Response) error {
	if r.StatusCode != 200 {
		return fmt.Errorf("got HTTP status code %d, expected 200", r.StatusCode)
	}

	if utils.HTTPGetContentType(r) != "application/json" {
		return fmt.Errorf("got HTTP content type `%s', expected `application/json'", r.Header["Content-Type"])
	}

	return nil
}
Пример #3
0
func (server *Server) parseStoreRequest(writer http.ResponseWriter, request *http.Request,
	id string) (*serverResponse, int) {

	if request.Method == "POST" && id != "" || request.Method == "PUT" && id == "" {
		return &serverResponse{mesgMethodNotAllowed}, http.StatusMethodNotAllowed
	} else if utils.HTTPGetContentType(request) != "application/json" {
		return &serverResponse{mesgUnsupportedMediaType}, http.StatusUnsupportedMediaType
	}

	return nil, http.StatusOK
}
Пример #4
0
func (server *Server) servePlots(writer http.ResponseWriter, request *http.Request) {
	var (
		err   error
		graph *library.Graph
		item  interface{}
	)

	if request.Method != "POST" && request.Method != "HEAD" {
		server.serveResponse(writer, serverResponse{mesgMethodNotAllowed}, http.StatusMethodNotAllowed)
		return
	} else if utils.HTTPGetContentType(request) != "application/json" {
		server.serveResponse(writer, serverResponse{mesgUnsupportedMediaType}, http.StatusUnsupportedMediaType)
		return
	}

	// Check for requests loop
	if request.Header.Get("X-Facette-Requestor") == server.ID {
		logger.Log(logger.LevelWarning, "server", "request loop detected, cancelled")
		server.serveResponse(writer, serverResponse{mesgEmptyData}, http.StatusBadRequest)
		return
	}

	// Parse plots request
	plotReq, err := parsePlotRequest(request)
	if err != nil {
		logger.Log(logger.LevelError, "server", "%s", err)
		server.serveResponse(writer, serverResponse{mesgResourceInvalid}, http.StatusBadRequest)
		return
	}

	// Get graph definition from the plot request
	graph = plotReq.Graph

	// If a Graph ID has been provided in the plot request, fetch the graph definition from the library instead
	if plotReq.ID != "" {
		graph = &library.Graph{}
		if item, err = server.Library.GetItem(plotReq.ID, library.LibraryItemGraph); err == nil {
			utils.Clone(item.(*library.Graph), graph)
		}
	}

	if graph == nil {
		err = os.ErrNotExist
	}

	// Stop if an error was encountered
	if err != nil {
		if os.IsNotExist(err) {
			server.serveResponse(writer, serverResponse{mesgResourceNotFound}, http.StatusNotFound)
		} else {
			logger.Log(logger.LevelError, "server", "%s", err)
			server.serveResponse(writer, serverResponse{mesgUnhandledError}, http.StatusInternalServerError)
		}

		return
	}

	// If linked graph, expand its template
	if graph.Link != "" || graph.ID == "" && len(graph.Attributes) > 0 {
		if graph.Link != "" {
			// Get graph template from library
			item, err := server.Library.GetItem(graph.Link, library.LibraryItemGraph)
			if err != nil {
				logger.Log(logger.LevelError, "server", "graph template not found: %s", graph.Link)
				return
			}

			utils.Clone(item.(*library.Graph), graph)
		}

		if err = server.expandGraphTemplate(graph); err != nil {
			logger.Log(logger.LevelError, "server", "unable to apply graph template: %s", err)
			server.serveResponse(writer, serverResponse{mesgUnhandledError}, http.StatusInternalServerError)
		}
	}

	// Prepare queries to be executed by the providers
	providerQueries, err := server.prepareProviderQueries(plotReq, graph)
	if err != nil {
		if os.IsNotExist(err) {
			server.serveResponse(writer, serverResponse{mesgResourceNotFound}, http.StatusNotFound)
		} else {
			logger.Log(logger.LevelError, "server", "%s", err)
			server.serveResponse(writer, serverResponse{mesgUnhandledError}, http.StatusInternalServerError)
		}

		return
	}

	plotSeries, err := executeQueries(providerQueries)
	if err != nil {
		logger.Log(logger.LevelError, "server", "unable to execute provider queries: %s", err)
		server.serveResponse(writer, serverResponse{mesgProviderQueryError}, http.StatusInternalServerError)
		return
	}

	if len(plotSeries) == 0 {
		server.serveResponse(writer, serverResponse{mesgEmptyData}, http.StatusOK)
		return
	}

	response, err := makePlotsResponse(plotSeries, plotReq, graph)
	if err != nil {
		logger.Log(logger.LevelError, "server", "unable to make plots response: %s", err)
		server.serveResponse(writer, serverResponse{mesgPlotOperationError}, http.StatusInternalServerError)
		return
	}

	server.serveResponse(writer, response, http.StatusOK)
}
Пример #5
0
func (server *Server) serveGraphPlots(writer http.ResponseWriter, request *http.Request) {
	var (
		err                error
		graph              *library.Graph
		item               interface{}
		startTime, endTime time.Time
	)

	if request.Method != "POST" && request.Method != "HEAD" {
		server.serveResponse(writer, serverResponse{mesgMethodNotAllowed}, http.StatusMethodNotAllowed)
		return
	} else if utils.HTTPGetContentType(request) != "application/json" {
		server.serveResponse(writer, serverResponse{mesgUnsupportedMediaType}, http.StatusUnsupportedMediaType)
		return
	}

	// Parse input JSON for graph data
	body, _ := ioutil.ReadAll(request.Body)

	plotReq := PlotRequest{}

	if err := json.Unmarshal(body, &plotReq); err != nil {
		logger.Log(logger.LevelError, "server", "%s", err)
		server.serveResponse(writer, serverResponse{mesgResourceInvalid}, http.StatusBadRequest)
		return
	}

	if plotReq.Time == "" {
		endTime = time.Now()
	} else if strings.HasPrefix(strings.Trim(plotReq.Range, " "), "-") {
		if endTime, err = time.Parse(time.RFC3339, plotReq.Time); err != nil {
			logger.Log(logger.LevelError, "server", "%s", err)
			server.serveResponse(writer, serverResponse{mesgResourceInvalid}, http.StatusBadRequest)
			return
		}
	} else {
		if startTime, err = time.Parse(time.RFC3339, plotReq.Time); err != nil {
			logger.Log(logger.LevelError, "server", "%s", err)
			server.serveResponse(writer, serverResponse{mesgResourceInvalid}, http.StatusBadRequest)
			return
		}
	}

	if startTime.IsZero() {
		if startTime, err = utils.TimeApplyRange(endTime, plotReq.Range); err != nil {
			logger.Log(logger.LevelError, "server", "%s", err)
			server.serveResponse(writer, serverResponse{mesgResourceInvalid}, http.StatusBadRequest)
			return
		}
	} else if endTime, err = utils.TimeApplyRange(startTime, plotReq.Range); err != nil {
		logger.Log(logger.LevelError, "server", "%s", err)
		server.serveResponse(writer, serverResponse{mesgResourceInvalid}, http.StatusBadRequest)
		return
	}

	if plotReq.Sample == 0 {
		plotReq.Sample = config.DefaultPlotSample
	}

	// Get graph from library
	graph = plotReq.Graph

	if plotReq.ID != "" {
		if item, err = server.Library.GetItem(plotReq.ID, library.LibraryItemGraph); err == nil {
			graph = item.(*library.Graph)
		}
	}

	if graph == nil {
		err = os.ErrNotExist
	}

	if err != nil {
		if os.IsNotExist(err) {
			server.serveResponse(writer, serverResponse{mesgResourceNotFound}, http.StatusNotFound)
		} else {
			logger.Log(logger.LevelError, "server", "%s", err)
			server.serveResponse(writer, serverResponse{mesgUnhandledError}, http.StatusInternalServerError)
		}

		return
	}

	step := endTime.Sub(startTime) / time.Duration(plotReq.Sample)

	// Get plots data
	groupOptions := make(map[string]map[string]interface{})

	data := make([][]*types.PlotResult, 0)

	for _, groupItem := range graph.Groups {
		groupOptions[groupItem.Name] = groupItem.Options

		query, providerConnector, err := server.preparePlotQuery(&plotReq, groupItem)
		if err != nil {
			if err != os.ErrInvalid {
				logger.Log(logger.LevelError, "server", "%s", err)
			}

			data = append(data, nil)
			continue
		}

		plotResults, err := providerConnector.GetPlots(&types.PlotQuery{query, startTime, endTime, step,
			plotReq.Percentiles})
		if err != nil {
			logger.Log(logger.LevelError, "server", "%s", err)
		}

		if len(plotResults) > 1 {
			for index, entry := range plotResults {
				entry.Name = fmt.Sprintf("%s (%s)", groupItem.Name, query.Series[index].Metric.Name)
			}
		} else if len(plotResults) == 1 {
			plotResults[0].Name = groupItem.Name
		}

		data = append(data, plotResults)
	}

	response := &PlotResponse{
		ID:          graph.ID,
		Start:       startTime.Format(time.RFC3339),
		End:         endTime.Format(time.RFC3339),
		Step:        step.Seconds(),
		Name:        graph.Name,
		Description: graph.Description,
		Type:        graph.Type,
		StackMode:   graph.StackMode,
		UnitLabel:   graph.UnitLabel,
		UnitType:    graph.UnitType,
		Modified:    graph.Modified,
	}

	if len(data) == 0 {
		server.serveResponse(writer, serverResponse{mesgEmptyData}, http.StatusOK)
		return
	}

	plotMax := 0

	for _, groupItem := range graph.Groups {
		var plotResult []*types.PlotResult

		plotResult, data = data[0], data[1:]

		for _, serieResult := range plotResult {
			if len(serieResult.Plots) > plotMax {
				plotMax = len(serieResult.Plots)
			}

			response.Series = append(response.Series, &SerieResponse{
				Name:    serieResult.Name,
				Plots:   serieResult.Plots,
				Info:    serieResult.Info,
				Options: groupOptions[groupItem.Name],
			})
		}
	}

	if plotMax > 0 {
		response.Step = (endTime.Sub(startTime) / time.Duration(plotMax)).Seconds()
	}

	server.serveResponse(writer, response, http.StatusOK)
}