fixes
Build and Publish / Metadata (push) Successful in 2s
Build and Publish / BuildAndDeployAmd64 (push) Failing after 4s

This commit is contained in:
mats committed 2026-09-20 09:52:49 +02:00
1 parent f30adf05af
commit 8824af8699
29 files changed
+1201 -115

No files matched your search

+19 -4
View File
@@ -18,6 +18,7 @@ import (
"git.tornberg.me/go-otel/internal/prometheus"
"git.tornberg.me/go-otel/internal/sourcemaps"
"git.tornberg.me/go-otel/internal/storage"
"git.tornberg.me/go-otel/internal/uaclass"
"git.tornberg.me/go-otel/internal/websocket"
"go.opentelemetry.io/collector/consumer"
@@ -163,8 +164,9 @@ func (c *Collector) ListIssues(limit int) []issues.Issue {
// ListIssuesFiltered returns a filtered page of deduplicated issues.
func (c *Collector) ListIssuesFiltered(opts issues.ListOptions) issues.ListPage {
page := c.issues.ListFiltered(opts)
if c.sourceMaps != nil {
for i := range page.Issues {
for i := range page.Issues {
classifyIssue(&page.Issues[i])
if c.sourceMaps != nil {
resolveIssue(&page.Issues[i], c.sourceMaps)
}
}
@@ -174,8 +176,11 @@ func (c *Collector) ListIssuesFiltered(opts issues.ListOptions) issues.ListPage
// GetIssue returns a single issue by id.
func (c *Collector) GetIssue(id string) (issues.Issue, bool) {
issue, ok := c.issues.Get(id)
if ok && c.sourceMaps != nil {
resolveIssue(&issue, c.sourceMaps)
if ok {
classifyIssue(&issue)
if c.sourceMaps != nil {
resolveIssue(&issue, c.sourceMaps)
}
}
return issue, ok
}
@@ -194,6 +199,16 @@ func resolveIssue(issue *issues.Issue, resolver *sourcemaps.Resolver) {
}
}
// classifyIssue sets each sample's UAClass from its User-Agent. Samples with
// no UA (backend logs, most spans) stay unclassified rather than "none".
func classifyIssue(issue *issues.Issue) {
for i := range issue.Samples {
if ua := issue.Samples[i].UserAgent; ua != "" {
issue.Samples[i].UAClass = uaclass.Of(ua)
}
}
}
// SetIssueStatus updates the triage state of an issue.
func (c *Collector) SetIssueStatus(id, status string) (issues.Issue, bool) {
return c.issues.SetStatus(id, status)
+30
View File
@@ -175,6 +175,8 @@ func (c *Collector) HandleLogs(w http.ResponseWriter, r *http.Request) {
return
}
stampFrontendClient(logs, r)
if err := c.ConsumeLogs(context.Background(), logs); err != nil {
log.Printf("failed to consume logs: %v", err)
http.Error(w, "failed to consume logs", http.StatusInternalServerError)
@@ -990,3 +992,31 @@ func (c *Collector) HandleNeedleClassify(w http.ResponseWriter, r *http.Request)
w.WriteHeader(resp.StatusCode)
_, _ = io.Copy(w, resp.Body)
}
// stampFrontendClient fills in client.address and user_agent.original on
// browser-originated log records (source=frontend) from the ingest request,
// since the browser cannot know its own public IP. Values the SDK already
// sent are kept, and backend services are left alone.
func stampFrontendClient(logs plog.Logs, r *http.Request) {
ip := strings.TrimSpace(clientIP(r))
ua := r.Header.Get("User-Agent")
rls := logs.ResourceLogs()
for i := 0; i < rls.Len(); i++ {
sls := rls.At(i).ScopeLogs()
for j := 0; j < sls.Len(); j++ {
recs := sls.At(j).LogRecords()
for k := 0; k < recs.Len(); k++ {
a := recs.At(k).Attributes()
if v, ok := a.Get("source"); !ok || v.Str() != "frontend" {
continue
}
if _, ok := a.Get("client.address"); !ok && ip != "" {
a.PutStr("client.address", ip)
}
if _, ok := a.Get("browser.userAgent"); !ok && ua != "" {
a.PutStr("user_agent.original", ua)
}
}
}
}
}