func parsePlotRequest(request *http.Request) (*PlotRequest, error) { var err error plotReq := &PlotRequest{} // Parse input JSON for plots request body, _ := ioutil.ReadAll(request.Body) if err = json.Unmarshal(body, plotReq); err != nil { return nil, err } // Check plots request parameters if plotReq.Time.IsZero() { plotReq.endTime = time.Now() } else if strings.HasPrefix(strings.Trim(plotReq.Range, " "), "-") { plotReq.endTime = plotReq.Time } else { plotReq.startTime = plotReq.Time } if plotReq.startTime.IsZero() { if plotReq.startTime, err = utils.TimeApplyRange(plotReq.endTime, plotReq.Range); err != nil { return nil, err } } else if plotReq.endTime, err = utils.TimeApplyRange(plotReq.startTime, plotReq.Range); err != nil { return nil, err } if plotReq.Sample == 0 { plotReq.Sample = config.DefaultPlotSample } // Append plot requestor identifier plotReq.requestor = request.Header.Get("X-Facette-Requestor") return plotReq, nil }
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) }