feat: propagate alert forwarding trace ids
This commit is contained in:
@@ -2,6 +2,7 @@ package ingest
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
@@ -14,7 +15,10 @@ import (
|
||||
"git.apinb.com/ops/logs/internal/config"
|
||||
)
|
||||
|
||||
const alertResponseBodyLimit = 1 << 20
|
||||
const (
|
||||
alertResponseBodyLimit = 1 << 20
|
||||
maxAlertTraceIDLength = 96
|
||||
)
|
||||
|
||||
var errAlertForwardDisabled = errors.New("Alert 转发未启用或 base_url 为空")
|
||||
|
||||
@@ -36,6 +40,7 @@ type AlertReceiveBody struct {
|
||||
PolicyID uint `json:"policy_id"`
|
||||
State string `json:"state,omitempty"`
|
||||
SourceEventKey string `json:"source_event_key"`
|
||||
TraceID string `json:"trace_id"`
|
||||
OccurredAt time.Time `json:"occurred_at"`
|
||||
RawData json.RawMessage `json:"raw_data"`
|
||||
}
|
||||
@@ -70,11 +75,12 @@ func forwardAlert(body AlertReceiveBody) error {
|
||||
if body.PolicyID == 0 && cfg.DefaultPolicyID > 0 {
|
||||
body.PolicyID = cfg.DefaultPolicyID
|
||||
}
|
||||
body.TraceID = ensureAlertTraceID(body.TraceID, body.SourceEventKey)
|
||||
raw, err := json.Marshal(body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result, err := postAlertPayload(cfg, "/Alert/v1/alerts/receive", raw)
|
||||
result, err := postAlertPayload(cfg, "/Alert/v1/alerts/receive", raw, body.TraceID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -101,12 +107,13 @@ func forwardAlert(body AlertReceiveBody) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func postAlertPayload(cfg *config.AlertForwardConf, path string, payload []byte) (*alertForwardResponse, error) {
|
||||
func postAlertPayload(cfg *config.AlertForwardConf, path string, payload []byte, traceID string) (*alertForwardResponse, error) {
|
||||
req, err := http.NewRequest(http.MethodPost, cfg.BaseURL+path, bytes.NewReader(payload))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("创建 Alert 转发请求失败:%w", err)
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("X-Trace-Id", traceID)
|
||||
if cfg.InternalKey != "" {
|
||||
req.Header.Set("X-Internal-Key", cfg.InternalKey)
|
||||
}
|
||||
@@ -173,9 +180,19 @@ func buildRawEventIngestBody(body AlertReceiveBody, parseStatus string) RawEvent
|
||||
Annotations: annotations,
|
||||
ParseStatus: parseStatus,
|
||||
RawPayload: body.RawData,
|
||||
TraceID: ensureAlertTraceID(body.TraceID, body.SourceEventKey),
|
||||
}
|
||||
}
|
||||
|
||||
func ensureAlertTraceID(traceID, sourceEventKey string) string {
|
||||
traceID = strings.TrimSpace(traceID)
|
||||
if traceID != "" && len(traceID) <= maxAlertTraceIDLength {
|
||||
return traceID
|
||||
}
|
||||
sum := sha256.Sum256([]byte(strings.TrimSpace(sourceEventKey)))
|
||||
return hex.EncodeToString(sum[:16])
|
||||
}
|
||||
|
||||
func validFingerprint(value string) bool {
|
||||
if len(value) != 64 {
|
||||
return false
|
||||
|
||||
@@ -25,6 +25,7 @@ const (
|
||||
)
|
||||
|
||||
func enqueueAlertWithDB(db *gorm.DB, logEventID uint, body AlertReceiveBody) (uint, error) {
|
||||
body.TraceID = ensureAlertTraceID(body.TraceID, body.SourceEventKey)
|
||||
payload, err := json.Marshal(body)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@@ -193,11 +194,12 @@ func forwardRawEvent(body RawEventIngestBody) error {
|
||||
if len(body.RawPayload) == 0 {
|
||||
return fmt.Errorf("raw_payload 不能为空")
|
||||
}
|
||||
body.TraceID = ensureAlertTraceID(body.TraceID, body.SourceEventKey)
|
||||
raw, err := json.Marshal(body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result, err := postAlertPayload(cfg, "/Alert/v1/raw-events/ingest", raw)
|
||||
result, err := postAlertPayload(cfg, "/Alert/v1/raw-events/ingest", raw, body.TraceID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -53,9 +53,10 @@ func BuildReplayRawEventPayload(ev models.LogEvent) (RawEventIngestBody, error)
|
||||
labels["resource_uid"] = resourceUID
|
||||
labels["resource_category"] = category
|
||||
labels["service_identity"] = identity
|
||||
sourceEventKey := fmt.Sprintf("logs:replay:%d:%d", ev.ID, now.UnixNano())
|
||||
return RawEventIngestBody{
|
||||
SourceType: sourceType,
|
||||
SourceEventKey: fmt.Sprintf("logs:replay:%d:%d", ev.ID, now.UnixNano()),
|
||||
SourceEventKey: sourceEventKey,
|
||||
State: "firing",
|
||||
ResourceUID: resourceUID,
|
||||
EventTime: now,
|
||||
@@ -69,6 +70,7 @@ func BuildReplayRawEventPayload(ev models.LogEvent) (RawEventIngestBody, error)
|
||||
},
|
||||
ParseStatus: "parsed",
|
||||
RawPayload: rawBytes,
|
||||
TraceID: ensureAlertTraceID("", sourceEventKey),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user