package service import ( "cybertron/internal/client/elastic" "cybertron/pkg/log" "cybertron/pkg/utils" "github.com/gin-gonic/gin" "net/http" "strconv" ) type SearchService struct { logger *log.Logger elasticSearchClient *elastic.ElasticSearchClient } func NewSearchService(logger *log.Logger, elasticSearchClient *elastic.ElasticSearchClient) *SearchService { return &SearchService{ logger: logger, elasticSearchClient: elasticSearchClient, } } func (s *SearchService) Search(c *gin.Context) { } func (s *SearchService) GetErrorDetails(c *gin.Context) { error_hash := c.Query("error_hash") project_id := c.Query("project_id") from := c.DefaultQuery("from", "0") fromInNumber, err := strconv.ParseInt(from, 10, 64) if err != nil { c.JSON(http.StatusBadRequest, "from should be a number") return } term_query := utils.CreateTermSubQuery("error_hash", error_hash) project_id_term_query := utils.CreateTermSubQuery("project_id", project_id) mustQuery := utils.CreateMustQuery(term_query, project_id_term_query) boolQuery := utils.CreateBoolQuery(mustQuery) search_query := utils.CreateSearchQuery(boolQuery) size_query := utils.CreateSizeQuery(1) sort_query := utils.CreateSortQuery("created_at", "desc", "") after_query := utils.CreateFromQuery(fromInNumber) es_query := utils.CreateEsQuery(search_query, size_query, sort_query, after_query) searchRequestformatted := es_query fields := []string{"error", "significant_stack", "title"} response, _, total, err := s.elasticSearchClient.SearchDocuments(searchRequestformatted, fields) if err != nil { utils.ErrorResponse(c, "Failed to search please try again later") return } c.JSON(http.StatusOK, gin.H{ "results": response, "total": total, }) } func (s *SearchService) GetSearchResults(c *gin.Context) { projectId := c.Query("project_id") size := c.DefaultQuery("size", "10") search_key := c.DefaultQuery("search_key", "") sizeInNumber, sizeParseError := strconv.Atoi(size) if sizeParseError != nil { c.JSON(http.StatusBadRequest, "size should be a number") return } size_query := utils.CreateSizeQuery(int64(sizeInNumber)) term_query := utils.CreateTermSubQuery("project_id", projectId) multiMatchQuery := utils.CreateMultiMatchQuery(search_key, "error", "title", "extra.metadata") should_query := utils.CreateMustQuery(term_query, multiMatchQuery) boolQuery := utils.CreateBoolQuery(should_query) search_query := utils.CreateSearchQuery(boolQuery) source_query := utils.CreateSourceQuery("error") finalQuery := utils.CreateEsQuery(source_query, search_query, size_query) fields := []string{"error", "significant_stack", "title"} var res, _, total, err = s.elasticSearchClient.SearchDocuments(finalQuery, fields) if err != nil { utils.ErrorResponse(c, "Failed to search please try again later") return } //println("final query %s", finalQuery) c.JSON(http.StatusOK, gin.H{ "results": res, "total": total, }) } func (s *SearchService) GetErrorListV2(c *gin.Context) { projectId := c.Query("project_id") sortKey := c.DefaultQuery("sort_key", "lastSeen") var orderQuery = "" if sortKey == "lastSeen" { orderQuery = utils.CreateOrderQuery("last_seen", "desc") } if sortKey == "firstSeen" { orderQuery = utils.CreateOrderQuery("first_seen", "desc") } if sortKey == "count" { orderQuery = utils.CreateOrderQuery("_count", "desc") } //size := c.DefaultQuery("size", "100000") term_query := utils.CreateTermSubQuery("project_id", projectId) search_query := utils.CreateSearchQuery(term_query) size_query := utils.CreateSizeQuery(0) top_hits_aggs_name_query := utils.BuildAggregationQuery("unique_errors", utils.CreateTopHitsAggsQuery(1, []string{"error", "significant_stack", "created_at", "error_hash"})) last_seen_aggs_query := utils.BuildAggregationQuery("last_seen", utils.CreateMaxAggregationQuery("created_at")) first_seen_aggs_query := utils.BuildAggregationQuery("first_seen", utils.CreateMinAggregationQuery("created_at")) top_hits_aggs_query := utils.CreateAggregationQuery(top_hits_aggs_name_query, last_seen_aggs_query, first_seen_aggs_query) term_aggs_query := utils.CreateTermsAggregationQuery("error_hash", 100000, orderQuery) terms_aggs_query_with_name := utils.BuildAggregationQuery("errors_by_hash", term_aggs_query, top_hits_aggs_query) final_terms_aggs_query := utils.CreateAggregationQuery(terms_aggs_query_with_name) final_query := utils.CreateEsQuery(search_query, size_query, final_terms_aggs_query) println("final query %v", final_query) fields := []string{"error", "significant_stack", "title"} var _, aggs, total, err = s.elasticSearchClient.SearchDocuments(final_query, fields) if err != nil { utils.ErrorResponse(c, "search failed please try again") return } c.JSON(http.StatusOK, gin.H{ "results": aggs, "total": total, }) } func (s *SearchService) GetErrorList(c *gin.Context) { //todo pagination and aggregation of errors projectId := c.Query("project_id") size := c.DefaultQuery("size", "10") afterKey := c.DefaultQuery("after_key", "") sortKey := c.DefaultQuery("sort_key", "lastSeen") sizeInNumber, sizeParseError := strconv.Atoi(size) if sizeParseError != nil { c.JSON(http.StatusBadRequest, "size should be a number") return } term_query := utils.CreateTermSubQuery("project_id", projectId) search_query := utils.CreateSearchQuery(term_query) size_query := utils.CreateSizeQuery(0) top_hits_aggs_name_query := utils.BuildAggregationQuery("unique_errors", utils.CreateTopHitsAggsQuery(1, []string{"error", "significant_stack", "created_at", "error_hash"})) last_seen_aggs_query := utils.BuildAggregationQuery("last_seen", utils.CreateMaxAggregationQuery("created_at")) first_seen_aggs_query := utils.BuildAggregationQuery("first_seen", utils.CreateMinAggregationQuery("created_at")) sortQuery := utils.CreateSortQuery("last_seen", "desc", "") if sortKey == "lastSeen" { sortQuery = utils.CreateSortQuery("last_seen", "desc", "") } if sortKey == "firstSeen" { sortQuery = utils.CreateSortQuery("first_seen", "desc", "") } if sortKey == "count" { sortQuery = utils.CreateSortQuery("_count", "desc", "") } customSortQuery := utils.CreateCustomQueryWithBraces("bucket_sort", sortQuery) customFinalSortQuery := utils.CreateCustomQueryWithBraces("sorting", customSortQuery) top_hits_aggs_query := utils.CreateAggregationQuery(top_hits_aggs_name_query, last_seen_aggs_query, first_seen_aggs_query, customFinalSortQuery) //building composite aggregation composite_term_query := utils.CreateTermsAggregationQueryWithoutSize("error_hash") composite_aggregation_query_without_name := utils.CreateCompositeAggsQuery(sizeInNumber, "error_hash", "error_hash", afterKey, composite_term_query) composite_aggs_query := utils.BuildAggregationQuery("errors_by_hash", composite_aggregation_query_without_name, top_hits_aggs_query) compositeAggsQuery := utils.CreateAggregationQuery(composite_aggs_query) final_query := utils.CreateEsQuery(search_query, size_query, compositeAggsQuery) //s.logger.Info("%s", zap.String("final query", final_query)) fields := []string{"error", "significant_stack", "title"} var _, aggs, total, err = s.elasticSearchClient.SearchDocuments(final_query, fields) if err != nil { utils.ErrorResponse(c, "search failed please try again") return } c.JSON(http.StatusOK, gin.H{ "results": aggs, "total": total, }) }