@@ -15,6 +15,7 @@ package main
1515
1616import (
1717 "bytes"
18+ "cmp"
1819 "context"
1920 "crypto/tls"
2021 "crypto/x509"
@@ -26,6 +27,7 @@ import (
2627 "os"
2728 "os/user"
2829 "path/filepath"
30+ "slices"
2931 "strings"
3032 "time"
3133
@@ -35,6 +37,7 @@ import (
3537 "github.com/pkg/errors"
3638 "github.com/shirou/gopsutil/process"
3739 log "github.com/sirupsen/logrus"
40+ "go.mongodb.org/mongo-driver/bson"
3841 "go.mongodb.org/mongo-driver/bson/primitive"
3942 "go.mongodb.org/mongo-driver/mongo"
4043 "go.mongodb.org/mongo-driver/mongo/options"
@@ -159,6 +162,29 @@ type clusterwideInfo struct {
159162 Chunks []proto.ChunksByCollection
160163}
161164
165+ type mongosInstance struct {
166+ Name string `bson:"_id"`
167+ LastPing time.Time `bson:"ping"`
168+ UpTime int `bson:"up"`
169+ Version string `bson:"mongoVersion"`
170+ }
171+
172+ type mongosInfo struct {
173+ Instances []mongosInstance `bson:"instances"`
174+ }
175+
176+ func (t mongosInfo ) MaxNameLen () int {
177+ if len (t .Instances ) == 0 {
178+ return 0
179+ }
180+
181+ maxInst := slices .MaxFunc (t .Instances , func (a , b mongosInstance ) int {
182+ return cmp .Compare (len (a .Name ), len (b .Name ))
183+ })
184+
185+ return len (maxInst .Name )
186+ }
187+
162188type cliOptions struct {
163189 Host string
164190 User string
@@ -184,6 +210,7 @@ type collectedInfo struct {
184210 RunningOps * opCounters
185211 SecuritySettings * security
186212 HostInfo * hostInfo
213+ MongosInfo * mongosInfo
187214 Errors []string
188215}
189216
@@ -256,14 +283,19 @@ func main() {
256283
257284 ci := & collectedInfo {}
258285
286+ ci .MongosInfo , err = getMongosInfo (ctx , client )
287+ if err != nil {
288+ log .Warnf ("[Warning] cannot get mongos info: %v\n " , err )
289+ }
290+
259291 ci .HostInfo , err = getHostInfo (ctx , client )
260292 if err != nil {
261293 log .Errorf ("Cannot get host info for %q: %s" , opts .Host , err )
262294 os .Exit (cannotGetHostInfo ) //nolint:gocritic
263295 }
264296
265297 if ci .ReplicaMembers , err = util .GetReplicasetMembers (ctx , clientOptions ); err != nil {
266- log .Warnf ("[Error ] cannot get replicaset members: %v\n " , err )
298+ log .Warnf ("[Warning ] cannot get replicaset members: %v\n " , err )
267299 }
268300
269301 log .Debugf ("replicaMembers:\n %+v\n " , ci .ReplicaMembers )
@@ -332,7 +364,12 @@ func formatResults(ci *collectedInfo, format string) ([]byte, error) {
332364 default :
333365 buf = new (bytes.Buffer )
334366
335- t := template .Must (template .New ("replicas" ).Parse (templates .Replicas ))
367+ t := template .Must (template .New ("mongos" ).Parse (templates .MongosInfo ))
368+ if err := t .Execute (buf , ci .MongosInfo ); err != nil {
369+ return nil , errors .Wrap (err , "cannot parse mongos section of the output template" )
370+ }
371+
372+ t = template .Must (template .New ("replicas" ).Parse (templates .Replicas ))
336373 if err := t .Execute (buf , ci .ReplicaMembers ); err != nil {
337374 return nil , errors .Wrap (err , "cannot parse replicas section of the output template" )
338375 }
@@ -454,6 +491,29 @@ func countMongodProcesses() (int, error) {
454491 return count , nil
455492}
456493
494+ func getMongosInfo (ctx context.Context , client * mongo.Client ) (* mongosInfo , error ) {
495+ threshold := time .Now ().Add (- 300 * time .Second )
496+
497+ filter := bson.M {
498+ "ping" : bson.M {
499+ "$gt" : threshold ,
500+ },
501+ }
502+
503+ cursor , err := client .Database ("config" ).Collection ("mongos" ).Find (ctx , filter )
504+ if err != nil {
505+ return nil , fmt .Errorf ("failed to find mongos: %w" , err )
506+ }
507+ defer cursor .Close (ctx )
508+
509+ var instances []mongosInstance
510+ if err := cursor .All (ctx , & instances ); err != nil {
511+ return nil , fmt .Errorf ("failed to decode mongos: %w" , err )
512+ }
513+
514+ return & mongosInfo {Instances : instances }, nil
515+ }
516+
457517func getClusterwideInfo (ctx context.Context , client * mongo.Client ) (* clusterwideInfo , error ) {
458518 var databases databases
459519
0 commit comments