2023-03-07 00:26:25 +05:30
package explorer
import (
2023-08-25 09:22:46 +05:30
"context"
2023-03-07 00:26:25 +05:30
"encoding/json"
"fmt"
2024-09-20 18:02:33 +05:30
"slices"
2023-08-25 09:22:46 +05:30
"strings"
2023-03-07 00:26:25 +05:30
"time"
2025-03-20 21:01:41 +05:30
"github.com/SigNoz/signoz/pkg/query-service/model"
v3 "github.com/SigNoz/signoz/pkg/query-service/model/v3"
"github.com/SigNoz/signoz/pkg/query-service/telemetry"
2025-03-24 14:54:20 +05:30
"github.com/SigNoz/signoz/pkg/sqlstore"
2025-03-20 21:01:41 +05:30
"github.com/SigNoz/signoz/pkg/types"
"github.com/SigNoz/signoz/pkg/types/authtypes"
2023-03-07 00:26:25 +05:30
"github.com/google/uuid"
2024-09-14 13:23:49 +05:30
"go.uber.org/zap"
2023-03-07 00:26:25 +05:30
)
2025-03-24 14:54:20 +05:30
var store sqlstore . SQLStore
2023-03-07 00:26:25 +05:30
// InitWithDSN sets up setting up the connection pool global variable.
2025-03-24 14:54:20 +05:30
func InitWithDSN ( sqlStore sqlstore . SQLStore ) error {
store = sqlStore
2024-09-14 13:23:49 +05:30
telemetry . GetInstance ( ) . SetSavedViewsInfoCallback ( GetSavedViewsInfo )
2025-01-22 12:49:38 +05:30
return nil
2023-03-07 00:26:25 +05:30
}
2025-03-24 14:54:20 +05:30
func InitWithDB ( sqlStore sqlstore . SQLStore ) {
store = sqlStore
2023-03-07 00:26:25 +05:30
}
2025-03-12 17:18:11 +05:30
func GetViews ( ctx context . Context , orgID string ) ( [ ] * v3 . SavedView , error ) {
var views [ ] types . SavedView
2025-03-24 14:54:20 +05:30
err := store . BunDB ( ) . NewSelect ( ) . Model ( & views ) . Where ( "org_id = ?" , orgID ) . Scan ( ctx )
2023-03-07 00:26:25 +05:30
if err != nil {
2023-08-25 09:22:46 +05:30
return nil , fmt . Errorf ( "error in getting saved views: %s" , err . Error ( ) )
2023-03-07 00:26:25 +05:30
}
2023-08-25 09:22:46 +05:30
var savedViews [ ] * v3 . SavedView
for _ , view := range views {
2023-03-07 00:26:25 +05:30
var compositeQuery v3 . CompositeQuery
2023-08-25 09:22:46 +05:30
err = json . Unmarshal ( [ ] byte ( view . Data ) , & compositeQuery )
2023-03-07 00:26:25 +05:30
if err != nil {
2023-08-25 09:22:46 +05:30
return nil , fmt . Errorf ( "error in unmarshalling explorer query data: %s" , err . Error ( ) )
2023-03-07 00:26:25 +05:30
}
2023-08-25 09:22:46 +05:30
savedViews = append ( savedViews , & v3 . SavedView {
UUID : view . UUID ,
Name : view . Name ,
Category : view . Category ,
CreatedAt : view . CreatedAt ,
CreatedBy : view . CreatedBy ,
UpdatedAt : view . UpdatedAt ,
UpdatedBy : view . UpdatedBy ,
Tags : strings . Split ( view . Tags , "," ) ,
SourcePage : view . SourcePage ,
2023-03-07 00:26:25 +05:30
CompositeQuery : & compositeQuery ,
2023-08-25 09:22:46 +05:30
ExtraData : view . ExtraData ,
2023-03-07 00:26:25 +05:30
} )
}
2023-08-25 09:22:46 +05:30
return savedViews , nil
2023-03-07 00:26:25 +05:30
}
2025-03-12 17:18:11 +05:30
func GetViewsForFilters ( ctx context . Context , orgID string , sourcePage string , name string , category string ) ( [ ] * v3 . SavedView , error ) {
var views [ ] types . SavedView
2023-08-25 09:22:46 +05:30
var err error
if len ( category ) == 0 {
2025-03-24 14:54:20 +05:30
err = store . BunDB ( ) . NewSelect ( ) . Model ( & views ) . Where ( "org_id = ? AND source_page = ? AND name LIKE ?" , orgID , sourcePage , "%" + name + "%" ) . Scan ( ctx )
2023-08-25 09:22:46 +05:30
} else {
2025-03-24 14:54:20 +05:30
err = store . BunDB ( ) . NewSelect ( ) . Model ( & views ) . Where ( "org_id = ? AND source_page = ? AND category LIKE ? AND name LIKE ?" , orgID , sourcePage , "%" + category + "%" , "%" + name + "%" ) . Scan ( ctx )
2023-08-25 09:22:46 +05:30
}
if err != nil {
return nil , fmt . Errorf ( "error in getting saved views: %s" , err . Error ( ) )
}
var savedViews [ ] * v3 . SavedView
for _ , view := range views {
var compositeQuery v3 . CompositeQuery
err = json . Unmarshal ( [ ] byte ( view . Data ) , & compositeQuery )
if err != nil {
return nil , fmt . Errorf ( "error in unmarshalling explorer query data: %s" , err . Error ( ) )
}
savedViews = append ( savedViews , & v3 . SavedView {
UUID : view . UUID ,
Name : view . Name ,
CreatedAt : view . CreatedAt ,
CreatedBy : view . CreatedBy ,
UpdatedAt : view . UpdatedAt ,
UpdatedBy : view . UpdatedBy ,
Tags : strings . Split ( view . Tags , "," ) ,
SourcePage : view . SourcePage ,
CompositeQuery : & compositeQuery ,
ExtraData : view . ExtraData ,
} )
}
return savedViews , nil
}
2025-03-12 17:18:11 +05:30
func CreateView ( ctx context . Context , orgID string , view v3 . SavedView ) ( string , error ) {
2023-08-25 09:22:46 +05:30
data , err := json . Marshal ( view . CompositeQuery )
2023-03-07 00:26:25 +05:30
if err != nil {
2023-08-25 09:22:46 +05:30
return "" , fmt . Errorf ( "error in marshalling explorer query data: %s" , err . Error ( ) )
2023-03-07 00:26:25 +05:30
}
2023-08-25 09:22:46 +05:30
uuid_ := view . UUID
2023-03-07 00:26:25 +05:30
if uuid_ == "" {
uuid_ = uuid . New ( ) . String ( )
}
createdAt := time . Now ( )
updatedAt := time . Now ( )
2025-02-17 18:16:41 +05:30
claims , ok := authtypes . ClaimsFromContext ( ctx )
if ! ok {
return "" , fmt . Errorf ( "error in getting email from context" )
2023-08-25 09:22:46 +05:30
}
2025-02-17 18:16:41 +05:30
createBy := claims . Email
updatedBy := claims . Email
2023-08-25 09:22:46 +05:30
2025-03-12 17:18:11 +05:30
dbView := types . SavedView {
TimeAuditable : types . TimeAuditable {
CreatedAt : createdAt ,
UpdatedAt : updatedAt ,
} ,
UserAuditable : types . UserAuditable {
CreatedBy : createBy ,
UpdatedBy : updatedBy ,
} ,
OrgID : orgID ,
UUID : uuid_ ,
Name : view . Name ,
Category : view . Category ,
SourcePage : view . SourcePage ,
Tags : strings . Join ( view . Tags , "," ) ,
Data : string ( data ) ,
ExtraData : view . ExtraData ,
}
2025-03-24 14:54:20 +05:30
_ , err = store . BunDB ( ) . NewInsert ( ) . Model ( & dbView ) . Exec ( ctx )
2023-03-07 00:26:25 +05:30
if err != nil {
2023-08-25 09:22:46 +05:30
return "" , fmt . Errorf ( "error in creating saved view: %s" , err . Error ( ) )
2023-03-07 00:26:25 +05:30
}
return uuid_ , nil
}
2025-03-12 17:18:11 +05:30
func GetView ( ctx context . Context , orgID string , uuid_ string ) ( * v3 . SavedView , error ) {
var view types . SavedView
2025-03-24 14:54:20 +05:30
err := store . BunDB ( ) . NewSelect ( ) . Model ( & view ) . Where ( "org_id = ? AND uuid = ?" , orgID , uuid_ ) . Scan ( ctx )
2023-03-07 00:26:25 +05:30
if err != nil {
2023-08-25 09:22:46 +05:30
return nil , fmt . Errorf ( "error in getting saved view: %s" , err . Error ( ) )
2023-03-07 00:26:25 +05:30
}
var compositeQuery v3 . CompositeQuery
2023-08-25 09:22:46 +05:30
err = json . Unmarshal ( [ ] byte ( view . Data ) , & compositeQuery )
2023-03-07 00:26:25 +05:30
if err != nil {
2023-08-25 09:22:46 +05:30
return nil , fmt . Errorf ( "error in unmarshalling explorer query data: %s" , err . Error ( ) )
2023-03-07 00:26:25 +05:30
}
2023-08-25 09:22:46 +05:30
return & v3 . SavedView {
UUID : view . UUID ,
Name : view . Name ,
Category : view . Category ,
CreatedAt : view . CreatedAt ,
CreatedBy : view . CreatedBy ,
UpdatedAt : view . UpdatedAt ,
UpdatedBy : view . UpdatedBy ,
SourcePage : view . SourcePage ,
Tags : strings . Split ( view . Tags , "," ) ,
2023-03-07 00:26:25 +05:30
CompositeQuery : & compositeQuery ,
2023-08-25 09:22:46 +05:30
ExtraData : view . ExtraData ,
2023-03-07 00:26:25 +05:30
} , nil
}
2025-03-12 17:18:11 +05:30
func UpdateView ( ctx context . Context , orgID string , uuid_ string , view v3 . SavedView ) error {
2023-08-25 09:22:46 +05:30
data , err := json . Marshal ( view . CompositeQuery )
2023-03-07 00:26:25 +05:30
if err != nil {
2023-08-25 09:22:46 +05:30
return fmt . Errorf ( "error in marshalling explorer query data: %s" , err . Error ( ) )
}
2025-02-17 18:16:41 +05:30
claims , ok := authtypes . ClaimsFromContext ( ctx )
if ! ok {
return fmt . Errorf ( "error in getting email from context" )
2023-03-07 00:26:25 +05:30
}
updatedAt := time . Now ( )
2025-02-17 18:16:41 +05:30
updatedBy := claims . Email
2023-03-07 00:26:25 +05:30
2025-03-24 14:54:20 +05:30
_ , err = store . BunDB ( ) . NewUpdate ( ) .
2025-03-12 17:18:11 +05:30
Model ( & types . SavedView { } ) .
Set ( "updated_at = ?, updated_by = ?, name = ?, category = ?, source_page = ?, tags = ?, data = ?, extra_data = ?" ,
updatedAt , updatedBy , view . Name , view . Category , view . SourcePage , strings . Join ( view . Tags , "," ) , data , view . ExtraData ) .
Where ( "uuid = ?" , uuid_ ) .
Where ( "org_id = ?" , orgID ) .
Exec ( ctx )
2023-03-07 00:26:25 +05:30
if err != nil {
2023-08-25 09:22:46 +05:30
return fmt . Errorf ( "error in updating saved view: %s" , err . Error ( ) )
2023-03-07 00:26:25 +05:30
}
return nil
}
2025-03-12 17:18:11 +05:30
func DeleteView ( ctx context . Context , orgID string , uuid_ string ) error {
2025-03-24 14:54:20 +05:30
_ , err := store . BunDB ( ) . NewDelete ( ) .
2025-03-12 17:18:11 +05:30
Model ( & types . SavedView { } ) .
Where ( "uuid = ?" , uuid_ ) .
Where ( "org_id = ?" , orgID ) .
Exec ( ctx )
2023-03-07 00:26:25 +05:30
if err != nil {
2023-08-25 09:22:46 +05:30
return fmt . Errorf ( "error in deleting explorer query: %s" , err . Error ( ) )
2023-03-07 00:26:25 +05:30
}
return nil
}
2024-09-14 13:23:49 +05:30
func GetSavedViewsInfo ( ctx context . Context ) ( * model . SavedViewsInfo , error ) {
savedViewsInfo := model . SavedViewsInfo { }
2025-03-12 17:18:11 +05:30
// get single org ID from db
var orgIDs [ ] string
2025-03-24 14:54:20 +05:30
err := store . BunDB ( ) . NewSelect ( ) . Model ( ( * types . Organization ) ( nil ) ) . Column ( "id" ) . Scan ( ctx , & orgIDs )
2025-03-12 17:18:11 +05:30
if err != nil {
return nil , fmt . Errorf ( "error in getting org IDs: %s" , err . Error ( ) )
}
if len ( orgIDs ) != 1 {
zap . S ( ) . Warn ( "GetSavedViewsInfo: Zero or multiple org IDs found in the database" , zap . Int ( "orgIDs" , len ( orgIDs ) ) )
return & savedViewsInfo , nil
}
savedViews , err := GetViews ( ctx , orgIDs [ 0 ] )
2024-09-14 13:23:49 +05:30
if err != nil {
zap . S ( ) . Debug ( "Error in fetching saved views info: " , err )
return & savedViewsInfo , err
}
savedViewsInfo . TotalSavedViews = len ( savedViews )
for _ , view := range savedViews {
if view . SourcePage == "traces" {
savedViewsInfo . TracesSavedViews += 1
} else if view . SourcePage == "logs" {
savedViewsInfo . LogsSavedViews += 1
2024-09-20 18:02:33 +05:30
for _ , query := range view . CompositeQuery . BuilderQueries {
if query . Filters != nil {
for _ , item := range query . Filters . Items {
if slices . Contains ( [ ] string { "contains" , "ncontains" , "like" , "nlike" } , string ( item . Operator ) ) {
if item . Key . Key != "body" {
savedViewsInfo . LogsSavedViewWithContainsOp += 1
}
}
}
}
}
2024-09-14 13:23:49 +05:30
}
}
return & savedViewsInfo , nil
}