Files
cybertron-log-enricher/service/ErrorProcessor.go
2024-10-11 12:20:01 +05:30

142 lines
3.9 KiB
Go

package service
import (
"encoding/json"
"fmt"
"log-enricher/models/es"
dbPackage "log-enricher/pkg/db"
"log-enricher/pkg/encoder"
"log-enricher/pkg/log"
"log-enricher/pkg/symbolicator"
"log-enricher/pkg/utils"
"path"
"strings"
"time"
)
type ErrorProcessor struct {
logger *log.Logger
elasticSearchClient *dbPackage.ElasticSearchClient
sourceMapFetcher *SourceMapService
}
type Frame struct {
Filename string `json:"filename"`
Function string `json:"function"`
InApp bool `json:"in_app"`
Lineno int `json:"lineno"`
Colno int `json:"colno"`
SourceMapPath string `json:"source_map_path,omitempty"`
}
type Stacktrace struct {
Frames []Frame `json:"frames"`
}
type MechanismData struct {
Function string `json:"function"`
Handler string `json:"handler"`
Target string `json:"target"`
}
type Mechanism struct {
Type string `json:"type"`
Handled bool `json:"handled"`
Data MechanismData `json:"data"`
}
type Extra struct {
ReleaseId string `json:"release_id"`
}
type Exception struct {
Type string `json:"type"`
Value string `json:"value"`
Stacktrace Stacktrace `json:"stacktrace"`
Mechanism Mechanism `json:"mechanism"`
ProjectId string `json:"project_id,omitempty"`
ReleaseId string `json:"release_id,omitempty"`
Breadcrumbs interface{} `json:"breadcrumbs,omitempty"`
Extra interface{} `json:"extra,omitempty"`
Request interface{} `json:"request,omitempty"`
}
func NewErrorProcessor(logger *log.Logger, elasticSearchClient *dbPackage.ElasticSearchClient, sourceMapFetcherService *SourceMapService) *ErrorProcessor {
return &ErrorProcessor{
logger: logger,
elasticSearchClient: elasticSearchClient,
sourceMapFetcher: sourceMapFetcherService,
}
}
func extractFilename(url string) string {
// Remove any trailing characters you don't want (in case there are any)
url = strings.Trim(url, `"`)
// Extract the base (filename) from the URL path
filename := path.Base(url)
return filename + ".map"
}
func (ep *ErrorProcessor) ProcessError(error []byte) {
fmt.Println("got error in consumer processing the same...")
var payload Exception
err := json.Unmarshal(error, &payload)
if err != nil {
println("unable to unmarshal exception")
return
}
extraMap := payload.Extra.(map[string]interface{})
releaseId, ok := extraMap["release_id"].(string)
if !ok {
println("release id not found")
return
}
//getting source map path
for i, frame := range payload.Stacktrace.Frames {
fileName := extractFilename(frame.Filename)
projectId := payload.ProjectId
frame := &payload.Stacktrace.Frames[i]
//todo make release dynamic
sourceMapPath, err := ep.sourceMapFetcher.GetSourceMap(fileName, projectId, "release-1")
if err != nil {
fmt.Printf("error occured in fetching source map")
}
frame.SourceMapPath = sourceMapPath
}
var frames, _ = json.Marshal(&payload.Stacktrace)
command := &symbolicator.Command{
Cmd: "bins/source-map",
Args: []string{string(frames)},
}
output, err := symbolicator.SymbolicatorClient(command)
if err != nil {
fmt.Printf("error occured in symbolicator client %s", err)
return
}
//make md5 hash of error
hash := encoder.Md5Encode(string(error))
//creating es document
println("processed document successfully saving it to elasticsearch", hash)
errorDocument := &es.ErrorDocument{
Error: payload.Value,
Title: payload.Type,
StackTrace: utils.Reverse(output.Frames),
SignificantStack: output.Frames[len(output.Frames)-1].Token,
ErrorHash: hash,
ProjectId: payload.ProjectId,
ReleaseVersion: releaseId,
CreatedAt: time.Now().Unix(),
Breadcrumbs: payload.Breadcrumbs,
Extra: payload.Extra,
Request: payload.Request,
}
ep.elasticSearchClient.IndexDocument(errorDocument)
}