Skip to main content
Glama
detector.go4.14 kB
package logs import ( "regexp" "strings" "github.com/standardbeagle/brummer/pkg/events" ) type EventDetector struct { eventBus *events.EventBus errorPatterns []*regexp.Regexp buildPatterns []*regexp.Regexp testPatterns []*regexp.Regexp } func NewEventDetector(eventBus *events.EventBus) *EventDetector { return &EventDetector{ eventBus: eventBus, errorPatterns: []*regexp.Regexp{ regexp.MustCompile(`(?i)error:`), regexp.MustCompile(`(?i)failed to`), regexp.MustCompile(`(?i)cannot find`), regexp.MustCompile(`(?i)undefined`), regexp.MustCompile(`(?i)exception:`), regexp.MustCompile(`(?i)fatal:`), regexp.MustCompile(`(?i)panic:`), }, buildPatterns: []*regexp.Regexp{ regexp.MustCompile(`(?i)build (completed|succeeded|failed)`), regexp.MustCompile(`(?i)compilation (completed|succeeded|failed)`), regexp.MustCompile(`(?i)webpack.*built`), regexp.MustCompile(`(?i)bundle.*generated`), regexp.MustCompile(`(?i)compiled successfully`), regexp.MustCompile(`(?i)build error`), }, testPatterns: []*regexp.Regexp{ regexp.MustCompile(`(?i)(\d+) (test|tests?) (passed|failed)`), regexp.MustCompile(`(?i)✓|✗|✔|✘`), regexp.MustCompile(`(?i)PASS:|FAIL:`), regexp.MustCompile(`(?i)test suite (passed|failed)`), regexp.MustCompile(`(?i)(\d+) passing`), regexp.MustCompile(`(?i)(\d+) failing`), }, } } func (d *EventDetector) ProcessLogLine(processID, processName, content string, isError bool) { lower := strings.ToLower(content) if d.isError(content, isError) { d.eventBus.Publish(events.Event{ Type: events.ErrorDetected, ProcessID: processID, Data: map[string]interface{}{ "processName": processName, "content": content, "severity": d.getErrorSeverity(content), }, }) } if d.isBuildEvent(content) { d.eventBus.Publish(events.Event{ Type: events.BuildEvent, ProcessID: processID, Data: map[string]interface{}{ "processName": processName, "content": content, "success": strings.Contains(lower, "success") || strings.Contains(lower, "completed"), }, }) } if testResult := d.detectTestResult(content); testResult != nil { eventType := events.TestPassed if testResult["failed"].(bool) { eventType = events.TestFailed } d.eventBus.Publish(events.Event{ Type: eventType, ProcessID: processID, Data: map[string]interface{}{ "processName": processName, "content": content, "details": testResult, }, }) } } func (d *EventDetector) isError(content string, isError bool) bool { if isError { return true } for _, pattern := range d.errorPatterns { if pattern.MatchString(content) { return true } } return false } func (d *EventDetector) getErrorSeverity(content string) string { lower := strings.ToLower(content) if strings.Contains(lower, "fatal") || strings.Contains(lower, "panic") { return "critical" } if strings.Contains(lower, "error") || strings.Contains(lower, "failed") { return "error" } if strings.Contains(lower, "warning") || strings.Contains(lower, "warn") { return "warning" } return "info" } func (d *EventDetector) isBuildEvent(content string) bool { for _, pattern := range d.buildPatterns { if pattern.MatchString(content) { return true } } return false } func (d *EventDetector) detectTestResult(content string) map[string]interface{} { for _, pattern := range d.testPatterns { if matches := pattern.FindStringSubmatch(content); matches != nil { lower := strings.ToLower(content) failed := strings.Contains(lower, "fail") || strings.Contains(lower, "✗") || strings.Contains(lower, "✘") result := map[string]interface{}{ "failed": failed, "line": content, } passMatch := regexp.MustCompile(`(\d+)\s*(passing|passed|✓)`).FindStringSubmatch(content) if passMatch != nil { result["passed"] = passMatch[1] } failMatch := regexp.MustCompile(`(\d+)\s*(failing|failed|✗)`).FindStringSubmatch(content) if failMatch != nil { result["failed_count"] = failMatch[1] } return result } } return nil }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/standardbeagle/brummer'

If you have feedback or need assistance with the MCP directory API, please join our Discord server