@@ -67,6 +67,9 @@ import (
67
67
68
68
// ActorSystem defines the contract of an actor system
69
69
type ActorSystem interface {
70
+ // Metric returns the actor system metric.
71
+ // The metric does not include any cluster data
72
+ Metric (ctx context.Context ) * Metric
70
73
// Name returns the actor system name
71
74
Name () string
72
75
// Actors returns the list of Actors that are alive on a given running node.
@@ -286,6 +289,9 @@ type actorSystem struct {
286
289
rebalancing * atomic.Bool
287
290
rebalanceLocker * sync.Mutex
288
291
shutdownHooks []ShutdownHook
292
+
293
+ actorsCounter * atomic.Uint64
294
+ deadlettersCounter * atomic.Uint64
289
295
}
290
296
291
297
var (
@@ -332,6 +338,8 @@ func NewActorSystem(name string, opts ...Option) (ActorSystem, error) {
332
338
shutdownHooks : make ([]ShutdownHook , 0 ),
333
339
nodesInprocess : goset .NewSet [string ](),
334
340
rebalanceLocker : & sync.Mutex {},
341
+ actorsCounter : atomic .NewUint64 (0 ),
342
+ deadlettersCounter : atomic .NewUint64 (0 ),
335
343
}
336
344
337
345
system .started .Store (false )
@@ -456,6 +464,20 @@ func (x *actorSystem) Stop(ctx context.Context) error {
456
464
return x .shutdown (ctx )
457
465
}
458
466
467
+ // Metrics returns the actor system metrics.
468
+ // The metrics does not include any cluster data
469
+ func (x * actorSystem ) Metric (ctx context.Context ) * Metric {
470
+ if x .started .Load () {
471
+ x .getSetDeadlettersCount (ctx )
472
+ return & Metric {
473
+ deadlettersCount : int64 (x .deadlettersCounter .Load ()),
474
+ actorsCount : int64 (x .actorsCounter .Load ()),
475
+ uptime : x .Uptime (),
476
+ }
477
+ }
478
+ return nil
479
+ }
480
+
459
481
// Running returns true when the actor system is running
460
482
func (x * actorSystem ) Running () bool {
461
483
return x .started .Load ()
@@ -597,7 +619,7 @@ func (x *actorSystem) InCluster() bool {
597
619
// NumActors returns the total number of active actors on a given running node.
598
620
// This does not account for the total number of actors in the cluster
599
621
func (x * actorSystem ) NumActors () uint64 {
600
- return uint64 ( len ( x . Actors ()) )
622
+ return x . actorsCounter . Load ( )
601
623
}
602
624
603
625
// Spawn creates or returns the instance of a given actor in the system
@@ -625,6 +647,7 @@ func (x *actorSystem) Spawn(ctx context.Context, name string, actor Actor, opts
625
647
return nil , err
626
648
}
627
649
650
+ x .actorsCounter .Inc ()
628
651
// add the given actor to the tree and supervise it
629
652
_ = x .actors .AddNode (x .userGuardian , pid )
630
653
x .actors .AddWatcher (pid , x .janitor )
@@ -661,6 +684,7 @@ func (x *actorSystem) SpawnNamedFromFunc(ctx context.Context, name string, recei
661
684
return nil , err
662
685
}
663
686
687
+ x .actorsCounter .Inc ()
664
688
_ = x .actors .AddNode (x .userGuardian , pid )
665
689
x .actors .AddWatcher (pid , x .janitor )
666
690
x .broadcastActor (pid )
@@ -691,8 +715,8 @@ func (x *actorSystem) Kill(ctx context.Context, name string) error {
691
715
pidNode , exist := x .actors .GetNode (actorAddress .String ())
692
716
if exist {
693
717
pid := pidNode .GetValue ()
694
- // stop the given actor. No need to record error in the span context
695
- // because the shutdown method is taking care of that
718
+ // decrement the actors count since we are stopping the actor
719
+ x . actorsCounter . Dec ()
696
720
return pid .Shutdown (ctx )
697
721
}
698
722
@@ -1226,7 +1250,7 @@ func (x *actorSystem) handleRemoteTell(ctx context.Context, to *PID, message pro
1226
1250
return Tell (ctx , to , message )
1227
1251
}
1228
1252
1229
- // getRootGuardian returns the system root guardian
1253
+ // getRootGuardian returns the system rootGuardian guardian
1230
1254
func (x * actorSystem ) getRootGuardian () * PID {
1231
1255
x .locker .Lock ()
1232
1256
rootGuardian := x .rootGuardian
@@ -1779,16 +1803,16 @@ func (x *actorSystem) setHostPort() error {
1779
1803
return nil
1780
1804
}
1781
1805
1782
- // spawnRootGuardian creates the root guardian
1806
+ // spawnRootGuardian creates the rootGuardian guardian
1783
1807
func (x * actorSystem ) spawnRootGuardian (ctx context.Context ) error {
1784
1808
var err error
1785
1809
actorName := x .reservedName (rootGuardianType )
1786
1810
x .rootGuardian , err = x .configPID (ctx , actorName , newRootGuardian ())
1787
1811
if err != nil {
1788
- return fmt .Errorf ("actor=%s failed to start root guardian: %w" , actorName , err )
1812
+ return fmt .Errorf ("actor=%s failed to start rootGuardian guardian: %w" , actorName , err )
1789
1813
}
1790
1814
1791
- // rootGuardian is the root node of the actors tree
1815
+ // rootGuardian is the rootGuardian node of the actors tree
1792
1816
_ = x .actors .AddNode (NoSender , x .rootGuardian )
1793
1817
return nil
1794
1818
}
@@ -1880,7 +1904,7 @@ func (x *actorSystem) spawnRebalancer(ctx context.Context) error {
1880
1904
// spawnDeadletters creates the deadletters synthetic actor
1881
1905
func (x * actorSystem ) spawnDeadletters (ctx context.Context ) error {
1882
1906
var err error
1883
- actorName := x .reservedName (deadletters )
1907
+ actorName := x .reservedName (deadlettersType )
1884
1908
x .deadletters , err = x .configPID (ctx ,
1885
1909
actorName ,
1886
1910
newDeadLetters (),
@@ -1935,6 +1959,25 @@ func (x *actorSystem) cleanupCluster(ctx context.Context, actorNames []string) e
1935
1959
return eg .Wait ()
1936
1960
}
1937
1961
1962
+ // getSetDeadlettersCount gets and sets the deadletter count
1963
+ func (x * actorSystem ) getSetDeadlettersCount (ctx context.Context ) {
1964
+ var (
1965
+ to = x .getDeadletters ()
1966
+ from = x .getSystemGuardian ()
1967
+ message = new (internalpb.GetDeadlettersCount )
1968
+ )
1969
+ if to .IsRunning () {
1970
+ // ask the deadletter actor for the count
1971
+ // using the default ask timeout
1972
+ // note: no need to check for error because this call is internal
1973
+ message , _ := from .Ask (ctx , to , message , DefaultAskTimeout )
1974
+ // cast the response received from the deadletters
1975
+ deadlettersCount := message .(* internalpb.DeadlettersCount )
1976
+ // set the counter
1977
+ x .deadlettersCounter .Store (uint64 (deadlettersCount .GetTotalCount ()))
1978
+ }
1979
+ }
1980
+
1938
1981
func isReservedName (name string ) bool {
1939
1982
return strings .HasPrefix (name , systemNamePrefix )
1940
1983
}
0 commit comments