diff --git a/apps/private-location/go.mod b/apps/private-location/go.mod index 6b3f66af..ad5d31c6 100644 --- a/apps/private-location/go.mod +++ b/apps/private-location/go.mod @@ -11,7 +11,6 @@ require ( github.com/joho/godotenv v1.5.1 github.com/mattn/go-sqlite3 v1.14.22 github.com/openstatushq/openstatus/apps/checker v0.0.0-20251012205355-e366f661c23e - github.com/rs/zerolog v1.34.0 github.com/stretchr/testify v1.11.1 github.com/tursodatabase/libsql-client-go v0.0.0-20240902231107-85af5b9d094d go.opentelemetry.io/contrib/bridges/otelslog v0.14.0 @@ -36,6 +35,7 @@ require ( github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/rs/zerolog v1.34.0 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.opentelemetry.io/otel/metric v1.39.0 // indirect go.opentelemetry.io/otel/trace v1.39.0 // indirect diff --git a/apps/private-location/internal/server/ingest_common.go b/apps/private-location/internal/server/ingest_common.go index c755c42f..8b4e3c5f 100644 --- a/apps/private-location/internal/server/ingest_common.go +++ b/apps/private-location/internal/server/ingest_common.go @@ -5,7 +5,6 @@ import ( "time" "github.com/openstatushq/openstatus/apps/private-location/internal/database" - "github.com/rs/zerolog/log" ) // ingestContext holds common data needed for ingestion @@ -19,14 +18,26 @@ func (h *privateLocationHandler) getIngestContext(ctx context.Context, token str var monitor database.Monitor err := h.db.Get(&monitor, "SELECT monitor.id, monitor.workspace_id, monitor.url, monitor.method, monitor.assertions FROM monitor JOIN private_location_to_monitor a ON monitor.id = a.monitor_id JOIN private_location b ON a.private_location_id = b.id WHERE b.token = ? AND monitor.deleted_at IS NULL and monitor.id = ?", token, monitorID) if err != nil { - log.Ctx(ctx).Error().Err(err).Msg("failed to get monitor") + if holder := GetEvent(ctx); holder != nil { + holder.Event["error"] = map[string]any{ + "message": err.Error(), + "source": "database", + "type": "monitor_lookup", + } + } return nil, err } var region database.PrivateLocation err = h.db.Get(®ion, "SELECT private_location.id FROM private_location join private_location_to_monitor a ON private_location.id = a.private_location_id WHERE a.monitor_id = ? AND private_location.token = ?", monitor.ID, token) if err != nil { - log.Ctx(ctx).Error().Err(err).Msg("failed to get private location") + if holder := GetEvent(ctx); holder != nil { + holder.Event["error"] = map[string]any{ + "message": err.Error(), + "source": "database", + "type": "private_location_lookup", + } + } return nil, err } @@ -38,15 +49,35 @@ func (h *privateLocationHandler) getIngestContext(ctx context.Context, token str // sendEventAndUpdateLastSeen sends the event to Tinybird and updates the last_seen_at timestamp func (h *privateLocationHandler) sendEventAndUpdateLastSeen(ctx context.Context, data any, dataSourceName string, regionID int) { - if err := h.TbClient.SendEvent(ctx, data, dataSourceName); err != nil { - log.Ctx(ctx).Error().Err(err).Msg("failed to send event to tinybird") + start := time.Now() + err := h.TbClient.SendEvent(ctx, data, dataSourceName) + duration := time.Since(start).Milliseconds() + + // Enrich wide event with Tinybird operation context + if holder := GetEvent(ctx); holder != nil { + holder.Event["tinybird"] = map[string]any{ + "datasource": dataSourceName, + "duration_ms": duration, + "success": err == nil, + } + if err != nil { + holder.Event["error"] = map[string]any{ + "message": err.Error(), + "source": "tinybird", + } + } } - _, err := h.db.NamedExec("UPDATE private_location SET last_seen_at = :last_seen_at WHERE id = :id", map[string]any{ + _, dbErr := h.db.NamedExec("UPDATE private_location SET last_seen_at = :last_seen_at WHERE id = :id", map[string]any{ "last_seen_at": time.Now().Unix(), "id": regionID, }) - if err != nil { - log.Ctx(ctx).Error().Err(err).Msg("failed to update private location") + if dbErr != nil { + if holder := GetEvent(ctx); holder != nil { + holder.Event["db_update_error"] = map[string]any{ + "message": dbErr.Error(), + "type": "last_seen_update", + } + } } } diff --git a/apps/private-location/internal/server/ingest_dns.go b/apps/private-location/internal/server/ingest_dns.go index 8a5ee838..46831cf7 100644 --- a/apps/private-location/internal/server/ingest_dns.go +++ b/apps/private-location/internal/server/ingest_dns.go @@ -44,9 +44,13 @@ func (h *privateLocationHandler) IngestDNS(ctx context.Context, req *connect.Req return nil, connect.NewError(connect.CodeInternal, err) } - if holder, ok := ctx.Value(eventKey).(*EventHolder); ok && holder != nil { + // Enrich wide event with business context + if holder := GetEvent(ctx); holder != nil { holder.Event["private_location"] = map[string]any{ - "monitor_id": req.Msg.MonitorId, + "monitor_id": req.Msg.MonitorId, + "workspace_id": ic.Monitor.WorkspaceID, + "region_id": ic.Region.ID, + "datasource": tinybird.DatasourceDNS, } } diff --git a/apps/private-location/internal/server/ingest_http.go b/apps/private-location/internal/server/ingest_http.go index 98f21b7c..aabbbecc 100644 --- a/apps/private-location/internal/server/ingest_http.go +++ b/apps/private-location/internal/server/ingest_http.go @@ -35,12 +35,6 @@ type PingData struct { } func (h *privateLocationHandler) IngestHTTP(ctx context.Context, req *connect.Request[private_locationv1.IngestHTTPRequest]) (*connect.Response[private_locationv1.IngestHTTPResponse], error) { - if holder, ok := ctx.Value(eventKey).(*EventHolder); ok && holder != nil { - holder.Event["private_location"] = map[string]any{ - "monitor_id": req.Msg.MonitorId, - } - } - token := req.Header().Get("openstatus-token") if token == "" { return nil, connect.NewError(connect.CodeUnauthenticated, ErrMissingToken) @@ -55,6 +49,16 @@ func (h *privateLocationHandler) IngestHTTP(ctx context.Context, req *connect.Re return nil, connect.NewError(connect.CodeInternal, err) } + // Enrich wide event with business context + if holder := GetEvent(ctx); holder != nil { + holder.Event["private_location"] = map[string]any{ + "monitor_id": req.Msg.MonitorId, + "workspace_id": ic.Monitor.WorkspaceID, + "region_id": ic.Region.ID, + "datasource": tinybird.DatasourceHTTP, + } + } + data := PingData{ ID: req.Msg.Id, Latency: req.Msg.Latency, diff --git a/apps/private-location/internal/server/ingest_tcp.go b/apps/private-location/internal/server/ingest_tcp.go index ea2a03b1..32e67f76 100644 --- a/apps/private-location/internal/server/ingest_tcp.go +++ b/apps/private-location/internal/server/ingest_tcp.go @@ -43,9 +43,13 @@ func (h *privateLocationHandler) IngestTCP(ctx context.Context, req *connect.Req return nil, connect.NewError(connect.CodeInternal, err) } - if holder, ok := ctx.Value(eventKey).(*EventHolder); ok && holder != nil { + // Enrich wide event with business context + if holder := GetEvent(ctx); holder != nil { holder.Event["private_location"] = map[string]any{ - "monitor_id": req.Msg.MonitorId, + "monitor_id": req.Msg.MonitorId, + "workspace_id": ic.Monitor.WorkspaceID, + "region_id": ic.Region.ID, + "datasource": tinybird.DatasourceTCP, } } diff --git a/apps/private-location/internal/server/monitors.go b/apps/private-location/internal/server/monitors.go index 6fdff933..5a2cee08 100644 --- a/apps/private-location/internal/server/monitors.go +++ b/apps/private-location/internal/server/monitors.go @@ -10,7 +10,6 @@ import ( "github.com/openstatushq/openstatus/apps/private-location/internal/database" "github.com/openstatushq/openstatus/apps/private-location/internal/models" private_locationv1 "github.com/openstatushq/openstatus/apps/private-location/proto/private_location/v1" - "github.com/rs/zerolog/log" ) // Converts models.NumberComparator to proto NumberComparator @@ -69,8 +68,23 @@ func convertRecordComparator(m models.RecordComparator) private_locationv1.Recor } } +// addParseError records a parsing error in the wide event context +func addParseError(ctx context.Context, errorType string, err error) { + if holder := GetEvent(ctx); holder != nil { + errors, ok := holder.Event["parse_errors"].([]map[string]any) + if !ok { + errors = []map[string]any{} + } + errors = append(errors, map[string]any{ + "type": errorType, + "message": err.Error(), + }) + holder.Event["parse_errors"] = errors + } +} + // Helper to parse assertions -func ParseAssertions(assertions sql.NullString) ( +func ParseAssertions(ctx context.Context, assertions sql.NullString) ( statusAssertions []*private_locationv1.StatusCodeAssertion, headerAssertions []*private_locationv1.HeaderAssertion, bodyAssertions []*private_locationv1.BodyAssertion, @@ -80,20 +94,20 @@ func ParseAssertions(assertions sql.NullString) ( } var rawAssertions []json.RawMessage if err := json.Unmarshal([]byte(assertions.String), &rawAssertions); err != nil { - log.Error().Err(err).Msg("failed to unmarshal assertions") + addParseError(ctx, "assertions_unmarshal", err) return } for _, a := range rawAssertions { var assert models.Assertion if err := json.Unmarshal(a, &assert); err != nil { - log.Error().Err(err).Msg("failed to unmarshal assertion") + addParseError(ctx, "assertion_unmarshal", err) continue } switch assert.AssertionType { case models.AssertionStatus: var target models.StatusTarget if err := json.Unmarshal(a, &target); err != nil { - log.Error().Err(err).Msg("failed to unmarshal status target") + addParseError(ctx, "status_target_unmarshal", err) continue } statusAssertions = append(statusAssertions, &private_locationv1.StatusCodeAssertion{ @@ -103,7 +117,7 @@ func ParseAssertions(assertions sql.NullString) ( case models.AssertionHeader: var target models.HeaderTarget if err := json.Unmarshal(a, &target); err != nil { - log.Error().Err(err).Msg("failed to unmarshal header target") + addParseError(ctx, "header_target_unmarshal", err) continue } headerAssertions = append(headerAssertions, &private_locationv1.HeaderAssertion{ @@ -114,7 +128,7 @@ func ParseAssertions(assertions sql.NullString) ( case models.AssertionTextBody: var target models.BodyString if err := json.Unmarshal(a, &target); err != nil { - log.Error().Err(err).Msg("failed to unmarshal body target") + addParseError(ctx, "body_target_unmarshal", err) continue } bodyAssertions = append(bodyAssertions, &private_locationv1.BodyAssertion{ @@ -127,32 +141,32 @@ func ParseAssertions(assertions sql.NullString) ( } // Helper to parse DNS record assertions -func ParseRecordAssertions(assertions sql.NullString) []*private_locationv1.RecordAssertion { +func ParseRecordAssertions(ctx context.Context, assertions sql.NullString) []*private_locationv1.RecordAssertion { if !assertions.Valid { return nil } var rawAssertions []json.RawMessage if err := json.Unmarshal([]byte(assertions.String), &rawAssertions); err != nil { - log.Error().Err(err).Msg("failed to unmarshal assertions") + addParseError(ctx, "record_assertions_unmarshal", err) return nil } var recordAssertions []*private_locationv1.RecordAssertion for _, a := range rawAssertions { var assert models.Assertion if err := json.Unmarshal(a, &assert); err != nil { - log.Error().Err(err).Msg("failed to unmarshal assertion") + addParseError(ctx, "record_assertion_unmarshal", err) continue } if assert.AssertionType == models.AssertionDnsRecord { var target models.RecordTarget if err := json.Unmarshal(a, &target); err != nil { - log.Error().Err(err).Msg("failed to unmarshal record target") + addParseError(ctx, "record_target_unmarshal", err) continue } recordAssertions = append(recordAssertions, &private_locationv1.RecordAssertion{ Record: target.Key, Comparator: convertRecordComparator(target.Comparator), - Target: target.Target, + Target: target.Target, }) } } @@ -183,11 +197,11 @@ func (h *privateLocationHandler) Monitors(ctx context.Context, req *connect.Requ case database.JobTypeHTTP: var headers []*private_locationv1.Headers if err := json.Unmarshal([]byte(monitor.Headers), &headers); err != nil { - log.Ctx(ctx).Error().Err(err).Msg("unable to unmarshal headers") + addParseError(ctx, "headers_unmarshal", err) headers = nil } - statusAssertions, headerAssertions, bodyAssertions := ParseAssertions(monitor.Assertions) + statusAssertions, headerAssertions, bodyAssertions := ParseAssertions(ctx, monitor.Assertions) httpMonitors = append(httpMonitors, &private_locationv1.HTTPMonitor{ Url: monitor.URL, @@ -216,7 +230,7 @@ func (h *privateLocationHandler) Monitors(ctx context.Context, req *connect.Requ }) case database.JobTypeDNS: - recordAssertions := ParseRecordAssertions(monitor.Assertions) + recordAssertions := ParseRecordAssertions(ctx, monitor.Assertions) dnsMonitors = append(dnsMonitors, &private_locationv1.DNSMonitor{ Id: strconv.Itoa(monitor.ID), Uri: monitor.URL, @@ -229,13 +243,15 @@ func (h *privateLocationHandler) Monitors(ctx context.Context, req *connect.Requ } } - - event := ctx.Value("event") - if eventMap, ok := event.(map[string]any); ok && eventMap != nil { - eventMap["private_location"] = map[string]any{ - "workspace_id": workspaceId, + // Enrich wide event with monitor counts + if holder := GetEvent(ctx); holder != nil { + holder.Event["private_location"] = map[string]any{ + "workspace_id": workspaceId, + "http_monitors": len(httpMonitors), + "tcp_monitors": len(tcpMonitors), + "dns_monitors": len(dnsMonitors), + "total_monitors": len(monitors), } - ctx = context.WithValue(ctx, "event", eventMap) } return connect.NewResponse(&private_locationv1.MonitorsResponse{ diff --git a/apps/private-location/internal/server/monitors_test.go b/apps/private-location/internal/server/monitors_test.go index ce39d87b..258d52e5 100644 --- a/apps/private-location/internal/server/monitors_test.go +++ b/apps/private-location/internal/server/monitors_test.go @@ -18,7 +18,7 @@ func TestParseAssertions_TextBodyContains(t *testing.T) { Valid: true, } - _, _, bodyAssertions := server.ParseAssertions(assertions) + _, _, bodyAssertions := server.ParseAssertions(context.Background(), assertions) if len(bodyAssertions) != 1 { t.Fatalf("expected 1 body assertion, got %d", len(bodyAssertions)) @@ -42,7 +42,7 @@ func TestParseAssertions_HttpStatusEquals(t *testing.T) { Valid: true, } - statusAssertion, _, _ := server.ParseAssertions(assertions) + statusAssertion, _, _ := server.ParseAssertions(context.Background(), assertions) if len(statusAssertion) != 1 { t.Fatalf("expected 1 body assertion, got %d", len(statusAssertion)) @@ -64,7 +64,7 @@ func TestParseAssertions_InvalidJSON(t *testing.T) { Valid: true, } - statusAssertions, headerAssertions, bodyAssertions := server.ParseAssertions(assertions) + statusAssertions, headerAssertions, bodyAssertions := server.ParseAssertions(context.Background(), assertions) if len(statusAssertions) != 0 || len(headerAssertions) != 0 || len(bodyAssertions) != 0 { t.Errorf("expected empty assertions for invalid JSON, got status=%d, header=%d, body=%d", @@ -78,7 +78,7 @@ func TestParseAssertions_NullString(t *testing.T) { Valid: false, } - statusAssertions, headerAssertions, bodyAssertions := server.ParseAssertions(assertions) + statusAssertions, headerAssertions, bodyAssertions := server.ParseAssertions(context.Background(), assertions) if len(statusAssertions) != 0 || len(headerAssertions) != 0 || len(bodyAssertions) != 0 { t.Errorf("expected empty assertions for null string, got status=%d, header=%d, body=%d", @@ -93,7 +93,7 @@ func TestParseAssertions_HeaderAssertion(t *testing.T) { Valid: true, } - _, headerAssertions, _ := server.ParseAssertions(assertions) + _, headerAssertions, _ := server.ParseAssertions(context.Background(), assertions) if len(headerAssertions) != 1 { t.Fatalf("expected 1 header assertion, got %d", len(headerAssertions)) @@ -122,7 +122,7 @@ func TestParseAssertions_MultipleAssertions(t *testing.T) { Valid: true, } - statusAssertions, headerAssertions, bodyAssertions := server.ParseAssertions(assertions) + statusAssertions, headerAssertions, bodyAssertions := server.ParseAssertions(context.Background(), assertions) if len(statusAssertions) != 1 { t.Errorf("expected 1 status assertion, got %d", len(statusAssertions)) @@ -280,7 +280,7 @@ func TestParseRecordAssertions_DnsRecordContains(t *testing.T) { Valid: true, } - recordAssertions := server.ParseRecordAssertions(assertions) + recordAssertions := server.ParseRecordAssertions(context.Background(), assertions) if len(recordAssertions) != 1 { t.Fatalf("expected 1 record assertion, got %d", len(recordAssertions)) @@ -305,7 +305,7 @@ func TestParseRecordAssertions_DnsRecordEquals(t *testing.T) { Valid: true, } - recordAssertions := server.ParseRecordAssertions(assertions) + recordAssertions := server.ParseRecordAssertions(context.Background(), assertions) if len(recordAssertions) != 1 { t.Fatalf("expected 1 record assertion, got %d", len(recordAssertions)) @@ -334,7 +334,7 @@ func TestParseRecordAssertions_MultipleRecordTypes(t *testing.T) { Valid: true, } - recordAssertions := server.ParseRecordAssertions(assertions) + recordAssertions := server.ParseRecordAssertions(context.Background(), assertions) if len(recordAssertions) != 3 { t.Fatalf("expected 3 record assertions, got %d", len(recordAssertions)) @@ -371,7 +371,7 @@ func TestParseRecordAssertions_InvalidJSON(t *testing.T) { Valid: true, } - recordAssertions := server.ParseRecordAssertions(assertions) + recordAssertions := server.ParseRecordAssertions(context.Background(), assertions) if len(recordAssertions) != 0 { t.Errorf("expected empty assertions for invalid JSON, got %d", len(recordAssertions)) @@ -384,7 +384,7 @@ func TestParseRecordAssertions_NullString(t *testing.T) { Valid: false, } - recordAssertions := server.ParseRecordAssertions(assertions) + recordAssertions := server.ParseRecordAssertions(context.Background(), assertions) if recordAssertions != nil { t.Errorf("expected nil for null string, got %v", recordAssertions) @@ -403,7 +403,7 @@ func TestParseRecordAssertions_MixedAssertionTypes(t *testing.T) { Valid: true, } - recordAssertions := server.ParseRecordAssertions(assertions) + recordAssertions := server.ParseRecordAssertions(context.Background(), assertions) if len(recordAssertions) != 1 { t.Fatalf("expected 1 record assertion (only dnsRecord), got %d", len(recordAssertions)) @@ -455,7 +455,7 @@ func TestParseRecordAssertions_EmptyArray(t *testing.T) { Valid: true, } - recordAssertions := server.ParseRecordAssertions(assertions) + recordAssertions := server.ParseRecordAssertions(context.Background(), assertions) if len(recordAssertions) != 0 { t.Errorf("expected empty slice for empty JSON array, got %d", len(recordAssertions)) @@ -469,7 +469,7 @@ func TestParseRecordAssertions_UnknownComparator(t *testing.T) { Valid: true, } - recordAssertions := server.ParseRecordAssertions(assertions) + recordAssertions := server.ParseRecordAssertions(context.Background(), assertions) if len(recordAssertions) != 1 { t.Fatalf("expected 1 record assertion, got %d", len(recordAssertions)) @@ -488,7 +488,7 @@ func TestParseRecordAssertions_UnknownRecordType(t *testing.T) { Valid: true, } - recordAssertions := server.ParseRecordAssertions(assertions) + recordAssertions := server.ParseRecordAssertions(context.Background(), assertions) if len(recordAssertions) != 1 { t.Fatalf("expected 1 record assertion, got %d", len(recordAssertions)) @@ -509,7 +509,7 @@ func TestParseRecordAssertions_MissingRequiredFields(t *testing.T) { Valid: true, } - recordAssertions := server.ParseRecordAssertions(assertions) + recordAssertions := server.ParseRecordAssertions(context.Background(), assertions) if len(recordAssertions) != 1 { t.Fatalf("expected 1 record assertion, got %d", len(recordAssertions)) @@ -527,7 +527,7 @@ func TestParseRecordAssertions_MissingRequiredFields(t *testing.T) { Valid: true, } - recordAssertions2 := server.ParseRecordAssertions(assertions2) + recordAssertions2 := server.ParseRecordAssertions(context.Background(), assertions2) if len(recordAssertions2) != 1 { t.Fatalf("expected 1 record assertion, got %d", len(recordAssertions2)) @@ -545,7 +545,7 @@ func TestParseRecordAssertions_MissingRequiredFields(t *testing.T) { Valid: true, } - recordAssertions3 := server.ParseRecordAssertions(assertions3) + recordAssertions3 := server.ParseRecordAssertions(context.Background(), assertions3) if len(recordAssertions3) != 1 { t.Fatalf("expected 1 record assertion, got %d", len(recordAssertions3)) diff --git a/apps/private-location/internal/server/routes.go b/apps/private-location/internal/server/routes.go index df1645d5..6f71a312 100644 --- a/apps/private-location/internal/server/routes.go +++ b/apps/private-location/internal/server/routes.go @@ -70,6 +70,10 @@ func Logger() func(next http.Handler) http.Handler { "url": fullURL, "user_agent": r.Header.Get("User-Agent"), "content_type": r.Header.Get("Content-Type"), + "service": map[string]any{ + "name": "openstatus-private-location", + "instance_id": instanceID, + }, }, } @@ -165,11 +169,21 @@ func (s *Server) RegisterRoutes() http.Handler { func (s *Server) healthHandler(w http.ResponseWriter, r *http.Request) { status := "ok" httpStatus := http.StatusOK + dbOK := true // Check database connection if err := s.db.PingContext(r.Context()); err != nil { status = "degraded" httpStatus = http.StatusServiceUnavailable + dbOK = false + } + + // Enrich wide event with health check context + if holder := GetEvent(r.Context()); holder != nil { + holder.Event["health_check"] = map[string]any{ + "status": status, + "db_ping": dbOK, + } } render.Status(r, httpStatus) diff --git a/apps/private-location/internal/server/server.go b/apps/private-location/internal/server/server.go index b561f0a2..c0a9bd88 100644 --- a/apps/private-location/internal/server/server.go +++ b/apps/private-location/internal/server/server.go @@ -9,6 +9,7 @@ import ( "strconv" "time" + "github.com/google/uuid" "github.com/jmoiron/sqlx" _ "github.com/joho/godotenv/autoload" "go.opentelemetry.io/contrib/bridges/otelslog" @@ -22,6 +23,7 @@ import ( "github.com/openstatushq/openstatus/apps/private-location/internal/database" ) + type Server struct { port int db *sqlx.DB @@ -29,6 +31,9 @@ type Server struct { logProvider *sdklog.LoggerProvider } +// instanceID is generated once at startup +var instanceID = uuid.New().String() + // NewServer returns an HTTP server and a cleanup function to shutdown the log provider. func NewServer() (*http.Server, func(context.Context)) { portStr := os.Getenv("PORT") @@ -59,6 +64,14 @@ func NewServer() (*http.Server, func(context.Context)) { WriteTimeout: 30 * time.Second, } + // Startup logging + slog.Info("server starting", + "port", port, + "instance_id", instanceID, + "axiom_configured", os.Getenv("AXIOM_TOKEN") != "", + "tinybird_configured", os.Getenv("TINYBIRD_TOKEN") != "", + ) + // Return cleanup function for graceful shutdown cleanup := func(ctx context.Context) { if logProvider != nil { @@ -82,11 +95,14 @@ func setupLogger() (*slog.Logger, *sdklog.LoggerProvider) { return logger, nil } + environment := env("ENVIRONMENT", "production") + res := resource.NewWithAttributes( semconv.SchemaURL, semconv.ServiceNameKey.String("openstatus-private-location"), - semconv.ServiceVersionKey.String("1.0.0"), - attribute.String("environment", "production"), + attribute.String("environment", environment), + + attribute.String("instance_id", instanceID), ) // Set up OTLP log exporter for Axiom diff --git a/apps/private-location/internal/tinybird/client.go b/apps/private-location/internal/tinybird/client.go index 0d289a56..ded95935 100644 --- a/apps/private-location/internal/tinybird/client.go +++ b/apps/private-location/internal/tinybird/client.go @@ -8,8 +8,6 @@ import ( "net/http" "net/url" "os" - - "github.com/rs/zerolog/log" ) // Datasource names for Tinybird events @@ -49,7 +47,6 @@ func NewClient(httpClient *http.Client, apiKey string) Client { func (c client) SendEvent(ctx context.Context, event any, dataSourceName string) error { requestURL, err := url.Parse(c.baseURL) if err != nil { - log.Ctx(ctx).Error().Err(err).Msg("unable to parse url") return fmt.Errorf("unable to parse url: %w", err) } @@ -59,26 +56,22 @@ func (c client) SendEvent(ctx context.Context, event any, dataSourceName string) var payload bytes.Buffer if err := json.NewEncoder(&payload).Encode(event); err != nil { - log.Ctx(ctx).Error().Err(err).Msg("unable to encode payload") return fmt.Errorf("unable to encode payload: %w", err) } req, err := http.NewRequestWithContext(ctx, http.MethodPost, requestURL.String(), bytes.NewReader(payload.Bytes())) if err != nil { - log.Ctx(ctx).Error().Err(err).Msg("unable to create request") return fmt.Errorf("unable to create request: %w", err) } req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", c.apiKey)) resp, err := c.httpClient.Do(req) if err != nil { - log.Ctx(ctx).Error().Err(err).Msg("unable to send request") return fmt.Errorf("unable to send request: %w", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusAccepted { - log.Ctx(ctx).Error().Str("status", resp.Status).Msg("unexpected status code") return fmt.Errorf("unexpected status code: %d", resp.StatusCode) }