func (server *Server) serveMetricList(writer http.ResponseWriter, request *http.Request) { var offset, limit int if response, status := server.parseListRequest(writer, request, &offset, &limit); status != http.StatusOK { server.serveResponse(writer, response, status) return } originName := request.FormValue("origin") sourceName := request.FormValue("source") sourceSet := set.New(set.ThreadSafe) if strings.HasPrefix(sourceName, library.LibraryGroupPrefix) { for _, entryName := range server.Library.ExpandGroup( strings.TrimPrefix(sourceName, library.LibraryGroupPrefix), library.LibraryItemSourceGroup, ) { sourceSet.Add(entryName) } } else if sourceName != "" { sourceSet.Add(sourceName) } metricSet := set.New(set.ThreadSafe) for _, origin := range server.Catalog.Origins { if originName != "" && origin.Name != originName { continue } for _, source := range origin.Sources { if sourceName != "" && sourceSet.IsEmpty() || !sourceSet.IsEmpty() && !sourceSet.Has(source.Name) { continue } for key := range source.Metrics { if request.FormValue("filter") != "" && !utils.FilterMatch(request.FormValue("filter"), key) { continue } metricSet.Add(key) } } } response := &listResponse{ list: StringListResponse(set.StringSlice(metricSet)), offset: offset, limit: limit, } server.applyResponseLimit(writer, request, response) server.serveResponse(writer, response.list, http.StatusOK) }
func (server *Server) serveOriginList(writer http.ResponseWriter, request *http.Request) { var offset, limit int if response, status := server.parseListRequest(writer, request, &offset, &limit); status != http.StatusOK { server.serveResponse(writer, response, status) return } originSet := set.New(set.ThreadSafe) for _, origin := range server.Catalog.Origins { if request.FormValue("filter") != "" && !utils.FilterMatch(request.FormValue("filter"), origin.Name) { continue } originSet.Add(origin.Name) } response := &listResponse{ list: StringListResponse(set.StringSlice(originSet)), offset: offset, limit: limit, } server.applyResponseLimit(writer, request, response) server.serveResponse(writer, response.list, http.StatusOK) }
func (server *Server) serveSource(writer http.ResponseWriter, request *http.Request) { sourceName := strings.TrimPrefix(request.URL.Path, urlCatalogPath+"sources/") if sourceName == "" { server.serveSourceList(writer, request) return } else if response, status := server.parseShowRequest(writer, request); status != http.StatusOK { server.serveResponse(writer, response, status) return } originSet := set.New(set.ThreadSafe) for _, origin := range server.Catalog.Origins { if _, ok := origin.Sources[sourceName]; ok { originSet.Add(origin.Name) } } if originSet.Size() == 0 { server.serveResponse(writer, serverResponse{mesgResourceNotFound}, http.StatusNotFound) return } origins := set.StringSlice(originSet) sort.Strings(origins) response := SourceResponse{ Name: sourceName, Origins: origins, } server.serveResponse(writer, response, http.StatusOK) }
func (server *Server) serveGraphList(writer http.ResponseWriter, request *http.Request) { var offset, limit int if response, status := server.parseListRequest(writer, request, &offset, &limit); status != http.StatusOK { server.serveResponse(writer, response, status) return } graphSet := set.New(set.ThreadSafe) // Filter on collection if any if request.FormValue("collection") != "" { item, err := server.Library.GetItem(request.FormValue("collection"), library.LibraryItemCollection) if os.IsNotExist(err) { server.serveResponse(writer, serverResponse{mesgResourceNotFound}, http.StatusNotFound) return } else if err != nil { logger.Log(logger.LevelError, "server", "%s", err) server.serveResponse(writer, serverResponse{mesgUnhandledError}, http.StatusInternalServerError) return } collection := item.(*library.Collection) for _, graph := range collection.Entries { graphSet.Add(graph.ID) } } // Fill graphs list items := make(ItemListResponse, 0) for _, graph := range server.Library.Graphs { if !graphSet.IsEmpty() && !graphSet.Has(graph.ID) { continue } if request.FormValue("filter") != "" && !utils.FilterMatch(request.FormValue("filter"), graph.Name) { continue } items = append(items, &ItemResponse{ ID: graph.ID, Name: graph.Name, Description: graph.Description, Modified: graph.Modified.Format(time.RFC3339), }) } response := &listResponse{ list: items, offset: offset, limit: limit, } server.applyResponseLimit(writer, request, response) server.serveResponse(writer, response.list, http.StatusOK) }
func (server *Server) getStats(writer http.ResponseWriter, request *http.Request) *statsResponse { sourceSet := set.New(set.ThreadSafe) metricSet := set.New(set.ThreadSafe) for _, origin := range server.Catalog.Origins { for key, source := range origin.Sources { sourceSet.Add(key) for key := range source.Metrics { metricSet.Add(key) } } } return &statsResponse{ Origins: len(server.Catalog.Origins), Sources: sourceSet.Size(), Metrics: metricSet.Size(), Graphs: len(server.Library.Graphs), Collections: len(server.Library.Collections), Groups: len(server.Library.Groups), } }
// ExpandGroup expands a group returning a list of matching items. func (library *Library) ExpandGroup(name string, groupType int) []string { item, err := library.GetItemByName(name, groupType) if err != nil { logger.Log(logger.LevelError, "library", "unknown item `%s': %s", name, err) return make([]string, 0) } group := item.(*Group) itemSet := set.New(set.ThreadSafe) for _, entry := range group.Entries { var re *regexp.Regexp if strings.HasPrefix(entry.Pattern, LibraryMatchPrefixRegexp) { re = regexp.MustCompile(strings.TrimPrefix(entry.Pattern, LibraryMatchPrefixRegexp)) } if _, ok := library.Catalog.Origins[entry.Origin]; !ok { logger.Log(logger.LevelError, "library", "unknown group entry `%s'", entry.Origin) continue } if groupType == LibraryItemSourceGroup { for _, source := range library.Catalog.Origins[entry.Origin].Sources { if strings.HasPrefix(entry.Pattern, LibraryMatchPrefixGlob) { if ok, _ := path.Match(strings.TrimPrefix(entry.Pattern, LibraryMatchPrefixGlob), source.Name); !ok { continue } } else if strings.HasPrefix(entry.Pattern, LibraryMatchPrefixRegexp) { if !re.MatchString(source.Name) { continue } } else if entry.Pattern != source.Name { continue } itemSet.Add(source.Name) } } else if groupType == LibraryItemMetricGroup { for _, source := range library.Catalog.Origins[entry.Origin].Sources { for _, metric := range source.Metrics { if strings.HasPrefix(entry.Pattern, LibraryMatchPrefixGlob) { if ok, _ := path.Match(strings.TrimPrefix(entry.Pattern, LibraryMatchPrefixGlob), metric.Name); !ok { continue } } else if strings.HasPrefix(entry.Pattern, LibraryMatchPrefixRegexp) { if !re.MatchString(metric.Name) { continue } } else if entry.Pattern != metric.Name { continue } itemSet.Add(metric.Name) } } } } result := set.StringSlice(itemSet) sort.Strings(result) return result }
func (server *Server) serveCollectionList(writer http.ResponseWriter, request *http.Request) { var ( collection *library.Collection offset, limit int ) if response, status := server.parseListRequest(writer, request, &offset, &limit); status != http.StatusOK { server.serveResponse(writer, response, status) return } // Check for item exclusion excludeSet := set.New(set.ThreadSafe) collectionStack := make([]*library.Collection, 0) if request.FormValue("exclude") != "" { if item, err := server.Library.GetItem(request.FormValue("exclude"), library.LibraryItemCollection); err == nil { collectionStack = append(collectionStack, item.(*library.Collection)) } for len(collectionStack) > 0 { collection, collectionStack = collectionStack[0], collectionStack[1:] excludeSet.Add(collection.ID) collectionStack = append(collectionStack, collection.Children...) } } // Fill collections list items := make(CollectionListResponse, 0) for _, collection := range server.Library.Collections { if request.FormValue("parent") != "" && (request.FormValue("parent") == "" && collection.Parent != nil || request.FormValue("parent") != "" && (collection.Parent == nil || collection.Parent.ID != request.FormValue("parent"))) { continue } if request.FormValue("filter") != "" && !utils.FilterMatch(request.FormValue("filter"), collection.Name) { continue } // Skip excluded items if excludeSet.Has(collection.ID) { continue } collectionItem := &CollectionResponse{ItemResponse: ItemResponse{ ID: collection.ID, Name: collection.Name, Description: collection.Description, Modified: collection.Modified.Format(time.RFC3339), }, HasChildren: len(collection.Children) > 0} if collection.Parent != nil { collectionItem.Parent = &collection.Parent.ID } items = append(items, collectionItem) } response := &listResponse{ list: items, offset: offset, limit: limit, } server.applyResponseLimit(writer, request, response) server.serveResponse(writer, response.list, http.StatusOK) }
// StoreItem stores an item into the library. func (library *Library) StoreItem(item interface{}, itemType int) error { var itemStruct *Item switch itemType { case LibraryItemSourceGroup, LibraryItemMetricGroup: itemStruct = item.(*Group).GetItem() case LibraryItemScale: itemStruct = item.(*Scale).GetItem() case LibraryItemGraph: itemStruct = item.(*Graph).GetItem() case LibraryItemCollection: itemStruct = item.(*Collection).GetItem() default: return os.ErrInvalid } if itemStruct.ID == "" { uuidTemp, err := uuid.NewV4() if err != nil { return err } itemStruct.ID = uuidTemp.String() } else if !library.ItemExists(itemStruct.ID, itemType) { return os.ErrNotExist } // Check for name field presence/duplicates if itemStruct.Name == "" { return os.ErrInvalid } itemTemp, err := library.GetItemByName(itemStruct.Name, itemType) // Item exists, check for duplicates if err == nil { switch itemType { case LibraryItemSourceGroup, LibraryItemMetricGroup: if itemTemp.(*Group).ID != itemStruct.ID { logger.Log(logger.LevelError, "library", "duplicate group identifier `%s'", itemStruct.ID) return os.ErrExist } case LibraryItemScale: if itemTemp.(*Scale).ID != itemStruct.ID { logger.Log(logger.LevelError, "library", "duplicate scale identifier `%s'", itemStruct.ID) return os.ErrExist } case LibraryItemGraph: if itemTemp.(*Graph).ID != itemStruct.ID { logger.Log(logger.LevelError, "library", "duplicate graph identifier `%s'", itemStruct.ID) return os.ErrExist } case LibraryItemCollection: if itemTemp.(*Collection).ID != itemStruct.ID { logger.Log(logger.LevelError, "library", "duplicate collection identifier `%s'", itemStruct.ID) return os.ErrExist } } } // Item does not exist, store it into library switch itemType { case LibraryItemSourceGroup, LibraryItemMetricGroup: library.Groups[itemStruct.ID] = item.(*Group) library.Groups[itemStruct.ID].ID = itemStruct.ID case LibraryItemScale: library.Scales[itemStruct.ID] = item.(*Scale) library.Scales[itemStruct.ID].ID = itemStruct.ID case LibraryItemGraph: // Check for definition names duplicates groupSet := set.New(set.ThreadSafe) serieSet := set.New(set.ThreadSafe) for _, group := range item.(*Graph).Groups { if group == nil { logger.Log(logger.LevelError, "library", "found null group") return os.ErrInvalid } else if groupSet.Has(group.Name) { logger.Log(logger.LevelError, "library", "duplicate group name `%s'", group.Name) return os.ErrExist } groupSet.Add(group.Name) for _, serie := range group.Series { if serie == nil { logger.Log(logger.LevelError, "library", "found null serie in group `%s'", group.Name) return os.ErrInvalid } else if serieSet.Has(serie.Name) { logger.Log(logger.LevelError, "library", "duplicate serie name `%s'", serie.Name) return os.ErrExist } serieSet.Add(serie.Name) } } library.Graphs[itemStruct.ID] = item.(*Graph) library.Graphs[itemStruct.ID].ID = itemStruct.ID case LibraryItemCollection: library.Collections[itemStruct.ID] = item.(*Collection) library.Collections[itemStruct.ID].ID = itemStruct.ID } // Store JSON data if err := utils.JSONDump(library.getFilePath(itemStruct.ID, itemType), item, itemStruct.Modified); err != nil { return err } return nil }