Files
cybertron/service/searchService.go
2025-01-09 16:06:55 +05:30

201 lines
7.4 KiB
Go

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.agentId",
"extra.metadata.external_customer_id",
"extra.metadata.deviceId",
"extra.metadata.web_session_id", "extra.metadata.id")
should_query := utils.CreateMustQuery(term_query, multiMatchQuery)
boolQuery := utils.CreateBoolQuery(should_query)
search_query := utils.CreateSearchQuery(boolQuery)
source_query := utils.CreateSourceQuery("error", "error_hash", "created_at")
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,
})
}