@@ -20,6 +20,7 @@ import (
20
20
"github.com/bitly/nsq/internal/protocol"
21
21
"github.com/bitly/nsq/internal/version"
22
22
"github.com/julienschmidt/httprouter"
23
+ "github.com/hashicorp/serf/serf"
23
24
)
24
25
25
26
type httpServer struct {
@@ -113,6 +114,10 @@ func (s *httpServer) pingHandler(w http.ResponseWriter, req *http.Request, ps ht
113
114
if ! s .ctx .nsqd .IsHealthy () {
114
115
code = 500
115
116
}
117
+ if s .ctx .nsqd .serf != nil && (s .ctx .nsqd .serf .State () == serf .SerfAlive || len (s .ctx .nsqd .serf .Members ()) < 2 ) {
118
+ code = 500
119
+ health = "NOK - gossip unhealthy"
120
+ }
116
121
w .Header ().Set ("Content-Length" , strconv .Itoa (len (health )))
117
122
w .WriteHeader (code )
118
123
io .WriteString (w , health )
@@ -167,6 +172,10 @@ func (s *httpServer) getTopicFromQuery(req *http.Request) (url.Values, *Topic, e
167
172
}
168
173
169
174
func (s * httpServer ) doLookup (w http.ResponseWriter , req * http.Request , ps httprouter.Params ) (interface {}, error ) {
175
+ if s .ctx .nsqd .serf == nil || s .ctx .nsqd .serf .State () != serf .SerfAlive {
176
+ return nil , http_api.Err {400 , "GOSSIP_NOT_ENABLED" }
177
+ }
178
+
170
179
reqParams , err := http_api .NewReqParams (req )
171
180
if err != nil {
172
181
return nil , http_api.Err {400 , "INVALID_REQUEST" }
@@ -484,8 +493,13 @@ func (s *httpServer) doStats(w http.ResponseWriter, req *http.Request, ps httpro
484
493
startTime := s .ctx .nsqd .GetStartTime ()
485
494
uptime := time .Since (startTime )
486
495
496
+ var serfStats map [string ]string
497
+ if s .ctx .nsqd .serf != nil {
498
+ serfStats = s .ctx .nsqd .serf .Stats ()
499
+ }
500
+
487
501
if ! jsonFormat {
488
- return s .printStats (stats , health , startTime , uptime ), nil
502
+ return s .printStats (stats , health , startTime , uptime , serfStats ), nil
489
503
}
490
504
491
505
return struct {
@@ -496,56 +510,55 @@ func (s *httpServer) doStats(w http.ResponseWriter, req *http.Request, ps httpro
496
510
}{version .Binary , health , startTime .Unix (), stats }, nil
497
511
}
498
512
499
- func (s * httpServer ) printStats (stats []TopicStats , health string , startTime time.Time , uptime time.Duration ) []byte {
500
- var buf bytes.Buffer
501
- w := & buf
513
+ func (s * httpServer ) printStats (stats []TopicStats , health string , startTime time.Time , uptime time.Duration , gossip map [string ]string ) []byte {
514
+ w := & bytes.Buffer {}
502
515
now := time .Now ()
503
- io . WriteString (w , fmt . Sprintf ( "%s\n " , version .String ("nsqd" ) ))
504
- io . WriteString (w , fmt . Sprintf ( "start_time %v\n " , startTime .Format (time .RFC3339 ) ))
505
- io . WriteString (w , fmt . Sprintf ( "uptime %s\n " , uptime ) )
516
+ fmt . Fprintf (w , "%s\n " , version .String ("nsqd" ))
517
+ fmt . Fprintf (w , "start_time %v\n " , startTime .Format (time .RFC3339 ))
518
+ fmt . Fprintf (w , "uptime %s\n " , uptime )
506
519
if len (stats ) == 0 {
507
- io .WriteString (w , "\n NO_TOPICS\n " )
508
- return buf .Bytes ()
520
+ w .WriteString ("\n NO_TOPICS\n " )
521
+ return w .Bytes ()
509
522
}
510
- io . WriteString (w , fmt . Sprintf ( "\n Health: %s\n " , health ) )
523
+ fmt . Fprintf (w , "\n Health: %s\n " , health )
511
524
for _ , t := range stats {
512
525
var pausedPrefix string
513
526
if t .Paused {
514
527
pausedPrefix = "*P "
515
528
} else {
516
529
pausedPrefix = " "
517
530
}
518
- io . WriteString (w , fmt . Sprintf ( "\n %s[%-15s] depth: %-5d be-depth: %-5d msgs: %-8d e2e%%: %s\n " ,
531
+ fmt . Fprintf (w , "\n %s[%-15s] depth: %-5d be-depth: %-5d msgs: %-8d e2e%%: %s\n " ,
519
532
pausedPrefix ,
520
533
t .TopicName ,
521
534
t .Depth ,
522
535
t .BackendDepth ,
523
536
t .MessageCount ,
524
- t .E2eProcessingLatency ))
537
+ t .E2eProcessingLatency )
525
538
for _ , c := range t .Channels {
526
539
if c .Paused {
527
540
pausedPrefix = " *P "
528
541
} else {
529
542
pausedPrefix = " "
530
543
}
531
- io . WriteString (w ,
532
- fmt . Sprintf ( "%s[%-25s] depth: %-5d be-depth: %-5d inflt: %-4d def: %-4d re-q: %-5d timeout: %-5d msgs: %-8d e2e%%: %s\n " ,
533
- pausedPrefix ,
534
- c .ChannelName ,
535
- c .Depth ,
536
- c .BackendDepth ,
537
- c .InFlightCount ,
538
- c .DeferredCount ,
539
- c .RequeueCount ,
540
- c .TimeoutCount ,
541
- c .MessageCount ,
542
- c .E2eProcessingLatency ) )
544
+ fmt . Fprintf (w ,
545
+ "%s[%-25s] depth: %-5d be-depth: %-5d inflt: %-4d def: %-4d re-q: %-5d timeout: %-5d msgs: %-8d e2e%%: %s\n " ,
546
+ pausedPrefix ,
547
+ c .ChannelName ,
548
+ c .Depth ,
549
+ c .BackendDepth ,
550
+ c .InFlightCount ,
551
+ c .DeferredCount ,
552
+ c .RequeueCount ,
553
+ c .TimeoutCount ,
554
+ c .MessageCount ,
555
+ c .E2eProcessingLatency )
543
556
for _ , client := range c .Clients {
544
557
connectTime := time .Unix (client .ConnectTime , 0 )
545
558
// truncate to the second
546
559
duration := time .Duration (int64 (now .Sub (connectTime ).Seconds ())) * time .Second
547
560
_ , port , _ := net .SplitHostPort (client .RemoteAddress )
548
- io . WriteString (w , fmt . Sprintf ( " [%s %-21s] state: %d inflt: %-4d rdy: %-4d fin: %-8d re-q: %-8d msgs: %-8d connected: %s\n " ,
561
+ fmt . Fprintf (w , " [%s %-21s] state: %d inflt: %-4d rdy: %-4d fin: %-8d re-q: %-8d msgs: %-8d connected: %s\n " ,
549
562
client .Version ,
550
563
fmt .Sprintf ("%s:%s" , client .Name , port ),
551
564
client .State ,
@@ -555,11 +568,19 @@ func (s *httpServer) printStats(stats []TopicStats, health string, startTime tim
555
568
client .RequeueCount ,
556
569
client .MessageCount ,
557
570
duration ,
558
- ))
571
+ )
559
572
}
560
573
}
561
574
}
562
- return buf .Bytes ()
575
+
576
+ if gossip != nil {
577
+ fmt .Fprintf (w , "\n Gossip:\n " )
578
+ for k , v := range gossip {
579
+ fmt .Fprintf (w , " %s: %s\n " , k , v )
580
+ }
581
+ }
582
+
583
+ return w .Bytes ()
563
584
}
564
585
565
586
func (s * httpServer ) doConfig (w http.ResponseWriter , req * http.Request , ps httprouter.Params ) (interface {}, error ) {
0 commit comments