Skip to content

Commit 44ef1a1

Browse files
authored
[self-hosted] add Embedded IdP metrics (netbirdio#5407)
1 parent 2b98dc4 commit 44ef1a1

File tree

2 files changed

+54
-1
lines changed

2 files changed

+54
-1
lines changed

management/server/metrics/selfhosted.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ func (w *Worker) generateProperties(ctx context.Context) properties {
210210
rosenpassEnabled int
211211
localUsers int
212212
idpUsers int
213+
embeddedIdpTypes map[string]int
213214
)
214215
start := time.Now()
215216
metricsProperties := make(properties)
@@ -218,6 +219,7 @@ func (w *Worker) generateProperties(ctx context.Context) properties {
218219
rulesProtocol = make(map[string]int)
219220
rulesDirection = make(map[string]int)
220221
activeUsersLastDay = make(map[string]struct{})
222+
embeddedIdpTypes = make(map[string]int)
221223
uptime = time.Since(w.startupTime).Seconds()
222224
connections := w.connManager.GetAllConnectedPeers()
223225
version = nbversion.NetbirdVersion()
@@ -277,6 +279,8 @@ func (w *Worker) generateProperties(ctx context.Context) properties {
277279
localUsers++
278280
} else {
279281
idpUsers++
282+
idpType := extractIdpType(idpID)
283+
embeddedIdpTypes[idpType]++
280284
}
281285
}
282286
}
@@ -369,6 +373,11 @@ func (w *Worker) generateProperties(ctx context.Context) properties {
369373
metricsProperties["rosenpass_enabled"] = rosenpassEnabled
370374
metricsProperties["local_users_count"] = localUsers
371375
metricsProperties["idp_users_count"] = idpUsers
376+
metricsProperties["embedded_idp_count"] = len(embeddedIdpTypes)
377+
378+
for idpType, count := range embeddedIdpTypes {
379+
metricsProperties["embedded_idp_users_"+idpType] = count
380+
}
372381

373382
for protocol, count := range rulesProtocol {
374383
metricsProperties["rules_protocol_"+protocol] = count
@@ -456,6 +465,17 @@ func createPostRequest(ctx context.Context, endpoint string, payloadStr string)
456465
return req, cancel, nil
457466
}
458467

468+
// extractIdpType extracts the IdP type from a Dex connector ID.
469+
// Connector IDs are formatted as "<type>-<xid>" (e.g., "okta-abc123", "zitadel-xyz").
470+
// Returns the type prefix, or "oidc" if no known prefix is found.
471+
func extractIdpType(connectorID string) string {
472+
idx := strings.LastIndex(connectorID, "-")
473+
if idx <= 0 {
474+
return "oidc"
475+
}
476+
return strings.ToLower(connectorID[:idx])
477+
}
478+
459479
func getMinMaxVersion(inputList []string) (string, string) {
460480
versions := make([]*version.Version, 0)
461481

management/server/metrics/selfhosted_test.go

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ func (mockDatasource) GetAllConnectedPeers() map[string]struct{} {
2727
// GetAllAccounts returns a list of *server.Account for use in tests with predefined information
2828
func (mockDatasource) GetAllAccounts(_ context.Context) []*types.Account {
2929
localUserID := dex.EncodeDexUserID("10", "local")
30-
idpUserID := dex.EncodeDexUserID("20", "zitadel")
30+
idpUserID := dex.EncodeDexUserID("20", "zitadel-d5uv82dra0haedlf6kv0")
3131
return []*types.Account{
3232
{
3333
Id: "1",
@@ -341,4 +341,37 @@ func TestGenerateProperties(t *testing.T) {
341341
if properties["idp_users_count"] != 1 {
342342
t.Errorf("expected 1 idp_users_count, got %d", properties["idp_users_count"])
343343
}
344+
if properties["embedded_idp_users_zitadel"] != 1 {
345+
t.Errorf("expected 1 embedded_idp_users_zitadel, got %v", properties["embedded_idp_users_zitadel"])
346+
}
347+
if properties["embedded_idp_count"] != 1 {
348+
t.Errorf("expected 1 embedded_idp_count, got %v", properties["embedded_idp_count"])
349+
}
350+
}
351+
352+
func TestExtractIdpType(t *testing.T) {
353+
tests := []struct {
354+
connectorID string
355+
expected string
356+
}{
357+
{"okta-abc123def", "okta"},
358+
{"zitadel-d5uv82dra0haedlf6kv0", "zitadel"},
359+
{"entra-xyz789", "entra"},
360+
{"google-abc123", "google"},
361+
{"pocketid-abc123", "pocketid"},
362+
{"microsoft-abc123", "microsoft"},
363+
{"authentik-abc123", "authentik"},
364+
{"keycloak-d5uv82dra0haedlf6kv0", "keycloak"},
365+
{"local", "oidc"},
366+
{"", "oidc"},
367+
}
368+
369+
for _, tt := range tests {
370+
t.Run(tt.connectorID, func(t *testing.T) {
371+
result := extractIdpType(tt.connectorID)
372+
if result != tt.expected {
373+
t.Errorf("extractIdpType(%q) = %q, want %q", tt.connectorID, result, tt.expected)
374+
}
375+
})
376+
}
344377
}

0 commit comments

Comments
 (0)