55 "context"
66 "encoding/json"
77 "fmt"
8- "log"
8+ "log/slog "
99 "math"
1010 "net/http"
1111 "slices"
@@ -184,7 +184,7 @@ func shouldNotify(msg *alertMsg, dest notifyDest) bool {
184184 if strings .HasPrefix (msg .uniqueId , "UnvotedGovernanceProposal" ) {
185185 // Check if it has been 6 hours since the last (re-)send
186186 if whichMap [msg .uniqueId ].SentTime .Before (time .Now ().Add (- 1 * time .Duration (td .GovernanceAlertsReminderInterval ) * time .Hour )) {
187- l (fmt .Sprintf ("🔄 RE-SENDING ALERT on %s (%s) - notifying %s" , msg .chain , msg .message , service ))
187+ l (slog . LevelInfo , fmt .Sprintf ("🔄 RE-SENDING ALERT on %s (%s) - notifying %s" , msg .chain , msg .message , service ))
188188 cache := alertMsgCache {
189189 Message : msg .message ,
190190 SentTime : time .Now (),
@@ -197,11 +197,11 @@ func shouldNotify(msg *alertMsg, dest notifyDest) bool {
197197 case ! whichMap [msg .uniqueId ].SentTime .IsZero () && msg .resolved :
198198 // alarm is cleared
199199 delete (whichMap , msg .uniqueId )
200- l (fmt .Sprintf ("💜 Resolved alarm on %s (%s) - notifying %s" , msg .chain , msg .message , service ))
200+ l (slog . LevelInfo , fmt .Sprintf ("💜 Resolved alarm on %s (%s) - notifying %s" , msg .chain , msg .message , service ))
201201 return true
202202 case msg .resolved :
203203 // it looks like we got a duplicate resolution or suppressed it. Note it and move on:
204- l (fmt .Sprintf ("😕 Not clearing alarm on %s (%s) - no corresponding alert %s" , msg .chain , msg .message , service ))
204+ l (slog . LevelWarn , fmt .Sprintf ("😕 Not clearing alarm on %s (%s) - no corresponding alert %s" , msg .chain , msg .message , service ))
205205 return false
206206 }
207207
@@ -212,7 +212,7 @@ func shouldNotify(msg *alertMsg, dest notifyDest) bool {
212212
213213 // for pagerduty we perform some basic flap detection
214214 if dest == pd && msg .pd && alarms.flappingAlarms [msg.chain ][msg.uniqueId ].SentTime .After (time .Now ().Add (- 5 * time .Minute )) {
215- l ("🛑 flapping detected - suppressing pagerduty notification:" , msg .chain , msg .message )
215+ l (slog . LevelWarn , "🛑 flapping detected - suppressing pagerduty notification:" , msg .chain , msg .message )
216216 return false
217217 } else if dest == pd && msg .pd {
218218 cache := alertMsgCache {
@@ -222,7 +222,7 @@ func shouldNotify(msg *alertMsg, dest notifyDest) bool {
222222 alarms.flappingAlarms [msg.chain ][msg.uniqueId ] = cache
223223 }
224224
225- l (fmt .Sprintf ("🚨 ALERT new alarm on %s (%s) - notifying %s" , msg .chain , msg .message , service ))
225+ l (slog . LevelInfo , fmt .Sprintf ("🚨 ALERT new alarm on %s (%s) - notifying %s" , msg .chain , msg .message , service ))
226226 cache := alertMsgCache {
227227 Message : msg .message ,
228228 SentTime : time .Now (),
@@ -301,27 +301,27 @@ func notifyDiscord(msg *alertMsg) (err error) {
301301 client := & http.Client {}
302302 data , err := json .MarshalIndent (discPost , "" , " " )
303303 if err != nil {
304- l ("⚠️ Could not notify discord!" , err )
304+ l (slog . LevelWarn , "⚠️ Could not notify discord!" , err )
305305 return err
306306 }
307307
308308 req , err := http .NewRequest ("POST" , msg .discHook , bytes .NewBuffer (data ))
309309 if err != nil {
310- l ("⚠️ Could not notify discord!" , err )
310+ l (slog . LevelWarn , "⚠️ Could not notify discord!" , err )
311311 return err
312312 }
313313 req .Header .Set ("Content-Type" , "application/json" )
314314
315315 resp , err := client .Do (req )
316316 if err != nil {
317- l ("⚠️ Could not notify discord!" , err )
317+ l (slog . LevelWarn , "⚠️ Could not notify discord!" , err )
318318 return err
319319 }
320320 _ = resp .Body .Close ()
321321
322322 if resp .StatusCode != 204 {
323- log . Println ( resp )
324- l ("⚠️ Could not notify discord! Returned" , resp .StatusCode )
323+ slog . Warn ( "discord webhook returned non-success response" , "status" , resp . StatusCode )
324+ l (slog . LevelWarn , "⚠️ Could not notify discord! Returned" , resp .StatusCode )
325325 return err
326326 }
327327 return nil
@@ -364,7 +364,7 @@ func notifyTg(msg *alertMsg) (err error) {
364364 }
365365 bot , err := tgbotapi .NewBotAPI (msg .tgKey )
366366 if err != nil {
367- l ("notify telegram:" , err )
367+ l (slog . LevelWarn , "notify telegram:" , err )
368368 return
369369 }
370370
@@ -376,7 +376,7 @@ func notifyTg(msg *alertMsg) (err error) {
376376 mc := tgbotapi .NewMessageToChannel (msg .tgChannel , fmt .Sprintf ("%s: %s: %s" , msg .chain , prefix , msg .message ))
377377 _ , err = bot .Send (mc )
378378 if err != nil {
379- l ("telegram send:" , err )
379+ l (slog . LevelWarn , "telegram send:" , err )
380380 }
381381 return err
382382}
@@ -390,7 +390,7 @@ func notifyPagerduty(msg *alertMsg) (err error) {
390390 }
391391 // key from the example, don't spam their api
392392 if msg .key == "aaaaaaaaaaaabbbbbbbbbbbbbcccccccccccc" {
393- l ("invalid pagerduty key" )
393+ l (slog . LevelWarn , "invalid pagerduty key" )
394394 return
395395 }
396396 action := "trigger"
@@ -485,27 +485,27 @@ func notifyWebhook(msg *alertMsg) (err error) {
485485
486486 data , err := json .Marshal (payload )
487487 if err != nil {
488- l ("⚠️ Could not marshal webhook payload!" , err )
488+ l (slog . LevelWarn , "⚠️ Could not marshal webhook payload!" , err )
489489 return err
490490 }
491491
492492 req , err := http .NewRequest ("POST" , msg .whURL , bytes .NewBuffer (data ))
493493 if err != nil {
494- l ("⚠️ Could not create webhook request!" , err )
494+ l (slog . LevelWarn , "⚠️ Could not create webhook request!" , err )
495495 return err
496496 }
497497 req .Header .Set ("Content-Type" , "application/json" )
498498
499499 client := & http.Client {Timeout : 30 * time .Second }
500500 resp , err := client .Do (req )
501501 if err != nil {
502- l ("⚠️ Could not send webhook!" , err )
502+ l (slog . LevelWarn , "⚠️ Could not send webhook!" , err )
503503 return err
504504 }
505505 _ = resp .Body .Close ()
506506
507507 if resp .StatusCode < 200 || resp .StatusCode >= 300 {
508- l ("⚠️ Webhook returned non-success status:" , resp .StatusCode )
508+ l (slog . LevelWarn , "⚠️ Webhook returned non-success status:" , resp .StatusCode )
509509 return fmt .Errorf ("webhook returned status %d for %s" , resp .StatusCode , msg .chain )
510510 }
511511
@@ -660,7 +660,7 @@ func evaluateNoRPCEndpointsAlert(cc *ChainConfig, noNodesSec *int) (bool, bool)
660660 * noNodesSec += 2
661661 if * noNodesSec <= 60 * td .NodeDownMin {
662662 if * noNodesSec % 20 == 0 {
663- l (fmt .Sprintf ("no nodes available on %s for %d seconds, deferring alarm" , cc .ChainId , * noNodesSec ))
663+ l (slog . LevelInfo , fmt .Sprintf ("no nodes available on %s for %d seconds, deferring alarm" , cc .ChainId , * noNodesSec ))
664664 }
665665 } else {
666666 if ! alarms .exist (cc .name , alertID ) {
@@ -1006,12 +1006,14 @@ func evaluateUnclaimedRewardsAlert(cc *ChainConfig) (bool, bool) {
10061006 return alert , resolved
10071007 }
10081008
1009+ convertedToDisplay := false
10091010 if cc .denomMetadata != nil {
10101011 convertedCoins , err := utils .ConvertDecCoinToDisplayUnit (nativeCoins , * cc .denomMetadata )
10111012 if err == nil {
10121013 nativeCoins = * convertedCoins
1014+ convertedToDisplay = true
10131015 } else {
1014- l (fmt .Errorf ("cannot convert rewards/commission to display unit for %s, err: %w" , cc .name , err ))
1016+ l (slog . LevelDebug , fmt .Errorf ("cannot convert rewards/commission to display unit for %s, err: %w" , cc .name , err ))
10151017 }
10161018 }
10171019
@@ -1024,26 +1026,17 @@ func evaluateUnclaimedRewardsAlert(cc *ChainConfig) (bool, bool) {
10241026 return alert , resolved
10251027 }
10261028
1027- if err := github_com_cosmos_cosmos_sdk_types .ValidateDenom (targetDenom ); err != nil {
1028- fallback := ""
1029- if len (nativeCoins ) > 0 {
1030- if errFallback := github_com_cosmos_cosmos_sdk_types .ValidateDenom (nativeCoins [0 ].Denom ); errFallback == nil {
1031- fallback = nativeCoins [0 ].Denom
1032- }
1033- }
1034- if fallback == "" {
1035- l (fmt .Errorf ("invalid target denom %q for %s: %w" , targetDenom , cc .name , err ))
1036- return alert , resolved
1037- }
1038- l (fmt .Errorf ("invalid target denom %q for %s: %w; falling back to %q" , targetDenom , cc .name , err , fallback ))
1039- targetDenom = fallback
1029+ // coinPrice is for the chain display token. If metadata exists but conversion to display
1030+ // failed, the amount may still be in base units (e.g. uom), which would misprice by 10^exp.
1031+ // Skip this alert evaluation rather than raising a false amount-based alert.
1032+ if cc .denomMetadata != nil && ! convertedToDisplay {
1033+ l (slog .LevelDebug , fmt .Errorf ("skipping unclaimed rewards pricing for %s because rewards are not confirmed in display units" , cc .name ))
1034+ return alert , resolved
10401035 }
10411036
1042- totalRewards := github_com_cosmos_cosmos_sdk_types .NewDecCoinFromDec (targetDenom , totalAmount )
1043-
10441037 coinPrice , err := td .coinMarketCapClient .GetPrice (td .ctx , cc .Slug )
1045- if err == nil {
1046- totalRewardsConverted := totalRewards . Amount .MustFloat64 () * coinPrice .Price
1038+ if err == nil && convertedToDisplay {
1039+ totalRewardsConverted := totalAmount .MustFloat64 () * coinPrice .Price
10471040 threshold := floatVal (cc .Alerts .UnclaimedRewardsThreshold )
10481041
10491042 alertID := fmt .Sprintf ("UnclaimedRewards_%s" , cc .ValAddress )
0 commit comments