Skip to content

Commit

Permalink
Add account name tag to monitoring endpoints (#6310)
Browse files Browse the repository at this point in the history
This supersedes #5173 since it introduced a redundant field
`LogicalName` on `Account` with the existing field `nameTag`.

The endpoints that are currently covered include:

- /accountz
- /accstatz
- /connz
- /subsz
- /jsz

The following endpoints also contain account metadata, but have not been
implemented yet.

- /routez
- /gatewayz
- /leafz
  • Loading branch information
derekcollison authored Jan 6, 2025
2 parents 4f0878a + 3dc7307 commit c558b24
Show file tree
Hide file tree
Showing 7 changed files with 748 additions and 367 deletions.
24 changes: 17 additions & 7 deletions server/accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ type Account struct {
stats
gwReplyMapping
Name string
LogicalName string
Nkey string
Issuer string
claimJWT string
Expand Down Expand Up @@ -257,10 +256,9 @@ type importMap struct {
// NewAccount creates a new unlimited account with the given name.
func NewAccount(name string) *Account {
a := &Account{
Name: name,
LogicalName: name,
limits: limits{-1, -1, -1, -1, false},
eventIds: nuid.New(),
Name: name,
limits: limits{-1, -1, -1, -1, false},
eventIds: nuid.New(),
}
return a
}
Expand Down Expand Up @@ -462,6 +460,20 @@ func (a *Account) GetName() string {
return name
}

// getNameTag will return the name tag or the account name if not set.
func (a *Account) getNameTag() string {
if a == nil {
return _EMPTY_
}
a.mu.RLock()
nameTag := a.nameTag
if nameTag == _EMPTY_ {
nameTag = a.Name
}
a.mu.RUnlock()
return nameTag
}

// NumConnections returns active number of clients for this account for
// all known servers.
func (a *Account) NumConnections() int {
Expand Down Expand Up @@ -3818,8 +3830,6 @@ func (s *Server) updateAccountClaimsWithRefresh(a *Account, ac *jwt.AccountClaim
func (s *Server) buildInternalAccount(ac *jwt.AccountClaims) *Account {
acc := NewAccount(ac.Subject)
acc.Issuer = ac.Issuer
// Override subject with logical name.
acc.LogicalName = ac.Name
// Set this here since we are placing in s.tmpAccounts below and may be
// referenced by an route RS+, etc.
s.setAccountSublist(acc)
Expand Down
15 changes: 10 additions & 5 deletions server/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -2337,9 +2337,14 @@ func (s *Server) sendAccConnsUpdate(a *Account, subj ...string) {
func (a *Account) statz() *AccountStat {
localConns := a.numLocalConnections()
leafConns := a.numLocalLeafNodes()
// Do not use getNameTag() to avoid a deadlock with `registerWithAccount`.
nameTag := a.nameTag
if nameTag == _EMPTY_ {
nameTag = a.Name
}
return &AccountStat{
Account: a.Name,
Name: a.LogicalName,
Name: nameTag,
Conns: localConns,
LeafNodes: leafConns,
TotalConns: localConns + leafConns,
Expand Down Expand Up @@ -2410,7 +2415,7 @@ func (s *Server) accountConnectEvent(c *client) {
Jwt: c.opts.JWT,
IssuerKey: issuerForClient(c),
Tags: c.tags,
NameTag: c.nameTag,
NameTag: c.acc.getNameTag(),
Kind: c.kindString(),
ClientType: c.clientTypeString(),
MQTTClient: c.getMQTTClientID(),
Expand Down Expand Up @@ -2462,7 +2467,7 @@ func (s *Server) accountDisconnectEvent(c *client, now time.Time, reason string)
Jwt: c.opts.JWT,
IssuerKey: issuerForClient(c),
Tags: c.tags,
NameTag: c.nameTag,
NameTag: c.acc.getNameTag(),
Kind: c.kindString(),
ClientType: c.clientTypeString(),
MQTTClient: c.getMQTTClientID(),
Expand Down Expand Up @@ -2516,7 +2521,7 @@ func (s *Server) sendAuthErrorEvent(c *client) {
Jwt: c.opts.JWT,
IssuerKey: issuerForClient(c),
Tags: c.tags,
NameTag: c.nameTag,
NameTag: c.acc.getNameTag(),
Kind: c.kindString(),
ClientType: c.clientTypeString(),
MQTTClient: c.getMQTTClientID(),
Expand Down Expand Up @@ -2574,7 +2579,7 @@ func (s *Server) sendAccountAuthErrorEvent(c *client, acc *Account, reason strin
Jwt: c.opts.JWT,
IssuerKey: issuerForClient(c),
Tags: c.tags,
NameTag: c.nameTag,
NameTag: c.acc.getNameTag(),
Kind: c.kindString(),
ClientType: c.clientTypeString(),
MQTTClient: c.getMQTTClientID(),
Expand Down
2 changes: 1 addition & 1 deletion server/jwt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4598,7 +4598,7 @@ func TestJWTUserRevocation(t *testing.T) {
t.Fatalf("Expected connection to have failed")
}
m := <-ncChan
require_Len(t, strings.Count(string(m.Data), apub), 2)
require_Len(t, strings.Count(string(m.Data), apub), 3)
require_True(t, strings.Contains(string(m.Data), `"jwt":"eyJ0`))
// try again with old credentials. Expected to fail
if nc1, err := nats.Connect(srv.ClientURL(), nats.UserCredentials(aCreds1)); err == nil {
Expand Down
73 changes: 37 additions & 36 deletions server/monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -415,14 +415,13 @@ func (s *Server) Connz(opts *ConnzOptions) (*Connz, error) {
// Fill in user if auth requested.
if auth {
ci.AuthorizedUser = client.getRawAuthUser()
// Add in account iff not the global account.
if client.acc != nil && (client.acc.Name != globalAccountName) {
ci.Account = client.acc.Name
if name := client.acc.GetName(); name != globalAccountName {
ci.Account = name
}
ci.JWT = client.opts.JWT
ci.IssuerKey = issuerForClient(client)
ci.Tags = client.tags
ci.NameTag = client.nameTag
ci.NameTag = client.acc.getNameTag()
}
client.mu.Unlock()
pconns[i] = ci
Expand Down Expand Up @@ -465,9 +464,11 @@ func (s *Server) Connz(opts *ConnzOptions) (*Connz, error) {
// Fill in user if auth requested.
if auth {
cc.AuthorizedUser = cc.user
// Add in account iff not the global account.
if cc.acc != _EMPTY_ && (cc.acc != globalAccountName) {
cc.Account = cc.acc
if acc, err := s.LookupAccount(cc.acc); err == nil {
cc.NameTag = acc.getNameTag()
}
}
}
pconns[i] = &cc.ConnInfo
Expand Down Expand Up @@ -925,21 +926,21 @@ type SubszOptions struct {

// SubDetail is for verbose information for subscriptions.
type SubDetail struct {
Account string `json:"account,omitempty"`
Subject string `json:"subject"`
Queue string `json:"qgroup,omitempty"`
Sid string `json:"sid"`
Msgs int64 `json:"msgs"`
Max int64 `json:"max,omitempty"`
Cid uint64 `json:"cid"`
Account string `json:"account,omitempty"`
AccountTag string `json:"account_tag,omitempty"`
Subject string `json:"subject"`
Queue string `json:"qgroup,omitempty"`
Sid string `json:"sid"`
Msgs int64 `json:"msgs"`
Max int64 `json:"max,omitempty"`
Cid uint64 `json:"cid"`
}

// Subscription client should be locked and guaranteed to be present.
func newSubDetail(sub *subscription) SubDetail {
sd := newClientSubDetail(sub)
if sub.client.acc != nil {
sd.Account = sub.client.acc.Name
}
sd.Account = sub.client.acc.GetName()
sd.AccountTag = sub.client.acc.getNameTag()
return sd
}

Expand Down Expand Up @@ -2713,27 +2714,27 @@ func (s *Server) accountInfo(accName string) (*AccountInfo, error) {
mappings[src] = dests
}
return &AccountInfo{
accName,
a.updated.UTC(),
isSys,
a.expired.Load(),
!a.incomplete,
a.js != nil,
a.numLocalLeafNodes(),
a.numLocalConnections(),
a.sl.Count(),
mappings,
exports,
imports,
a.claimJWT,
a.Issuer,
a.nameTag,
a.tags,
claim,
vrIssues,
collectRevocations(a.usersRevoked),
a.sl.Stats(),
responses,
AccountName: accName,
LastUpdate: a.updated.UTC(),
IsSystem: isSys,
Expired: a.expired.Load(),
Complete: !a.incomplete,
JetStream: a.js != nil,
LeafCnt: a.numLocalLeafNodes(),
ClientCnt: a.numLocalConnections(),
SubCnt: a.sl.Count(),
Mappings: mappings,
Exports: exports,
Imports: imports,
Jwt: a.claimJWT,
IssuerKey: a.Issuer,
NameTag: a.getNameTag(),
Tags: a.tags,
Claim: claim,
Vr: vrIssues,
RevokedUser: collectRevocations(a.usersRevoked),
Sublist: a.sl.Stats(),
Responses: responses,
}, nil
}

Expand Down
Loading

0 comments on commit c558b24

Please sign in to comment.