Deprecated : This is a beta service. Future versions may have changes to the telemetry API structure.
Overview
The BetaTelemetryServiceApi provides methods for reporting system information and resource usage to ZITADEL analytics. This helps with system monitoring, capacity planning, and feature usage tracking.
Initialization
require 'zitadel/client'
client = Zitadel :: Client :: ApiClient . new
client. config . access_token = 'your_access_token'
telemetry_service = Zitadel :: Client :: Api :: BetaTelemetryServiceApi . new (client)
Telemetry reporting is typically used by system administrators and automated monitoring tools.
Key Methods
report_base_information - Report system base information
Resource Count Reporting
report_resource_counts - Report resource usage
beta_telemetry_service_report_resource_counts_request
Resource count information System identifier (same as base report)
Report ID from base information
Array of resource counts per organization
request = Zitadel :: Client :: Models :: BetaTelemetryServiceReportResourceCountsRequest . new (
system_id: 'system_unique_id' ,
report_id: response. report_id , # From base information report
resource_counts: [
{
organization_id: 'org_1' ,
user_count: 150 ,
project_count: 5 ,
application_count: 12 ,
session_count: 45 ,
action_count: 8
},
{
organization_id: 'org_2' ,
user_count: 320 ,
project_count: 10 ,
application_count: 25 ,
session_count: 120 ,
action_count: 15
}
]
)
response = telemetry_service. report_resource_counts (request)
puts "Resource counts reported successfully"
puts "Report ID: #{ response. report_id } "
Returns : BetaTelemetryServiceReportResourceCountsResponseResource counts can be reported in multiple batches using the same report ID.
Reporting Workflow
Complete Telemetry Report
def generate_telemetry_report
# Step 1: Report base information
puts "Collecting system information..."
base_request = Zitadel :: Client :: Models :: BetaTelemetryServiceReportBaseInformationRequest . new (
system_id: ENV [ 'ZITADEL_SYSTEM_ID' ],
version: get_zitadel_version,
instances: collect_instances
)
base_response = telemetry_service. report_base_information (base_request)
report_id = base_response. report_id
puts "Base report created: #{ report_id } "
# Step 2: Collect resource counts
puts "Collecting resource counts..."
organizations = list_all_organizations
# Report in batches (e.g., 100 orgs at a time)
organizations. each_slice ( 100 ) do | org_batch |
resource_counts = org_batch. map do | org |
{
organization_id: org. id ,
user_count: count_users (org. id ),
project_count: count_projects (org. id ),
application_count: count_applications (org. id ),
session_count: count_active_sessions (org. id ),
action_count: count_actions (org. id )
}
end
count_request = Zitadel :: Client :: Models :: BetaTelemetryServiceReportResourceCountsRequest . new (
system_id: ENV [ 'ZITADEL_SYSTEM_ID' ],
report_id: report_id,
resource_counts: resource_counts
)
telemetry_service. report_resource_counts (count_request)
puts "Reported counts for #{ org_batch. size } organizations"
end
puts "Telemetry report complete!"
report_id
end
Use Cases
Scheduled Daily Report
require 'rufus-scheduler'
scheduler = Rufus :: Scheduler . new
# Report telemetry daily at 2 AM
scheduler. cron '0 2 * * *' do
begin
puts "Starting daily telemetry report..."
report_id = generate_telemetry_report
puts "Daily report completed: #{ report_id } "
rescue => e
puts "Error generating report: #{ e. message } "
end
end
Monitor System Growth
def system_growth_metrics
# Get all instances
instances = instance_service. list_instances ({}). result
# Prepare base information
base_request = Zitadel :: Client :: Models :: BetaTelemetryServiceReportBaseInformationRequest . new (
system_id: ENV [ 'ZITADEL_SYSTEM_ID' ],
version: ZITADEL_VERSION ,
instances: instances. map { | i |
{
instance_id: i. id ,
creation_date: i. creation_date ,
domains: i. domains
}
}
)
base_response = telemetry_service. report_base_information (base_request)
# Collect aggregate metrics
total_users = 0
total_projects = 0
total_apps = 0
resource_counts = organizations. map do | org |
user_count = count_users (org. id )
project_count = count_projects (org. id )
app_count = count_applications (org. id )
total_users += user_count
total_projects += project_count
total_apps += app_count
{
organization_id: org. id ,
user_count: user_count,
project_count: project_count,
application_count: app_count
}
end
# Report counts
count_request = Zitadel :: Client :: Models :: BetaTelemetryServiceReportResourceCountsRequest . new (
system_id: ENV [ 'ZITADEL_SYSTEM_ID' ],
report_id: base_response. report_id ,
resource_counts: resource_counts
)
telemetry_service. report_resource_counts (count_request)
# Return summary
{
instances: instances. size ,
organizations: organizations. size ,
users: total_users,
projects: total_projects,
applications: total_apps
}
end
Capacity Planning Report
def capacity_planning_report
metrics = system_growth_metrics
# Calculate averages
avg_users_per_org = metrics[ :users ] / [metrics[ :organizations ], 1 ]. max
avg_projects_per_org = metrics[ :projects ] / [metrics[ :organizations ], 1 ]. max
avg_apps_per_project = metrics[ :applications ] / [metrics[ :projects ], 1 ]. max
report = <<~REPORT
Capacity Planning Report
=======================
System Overview:
- Instances: #{ metrics[ :instances ] }
- Organizations: #{ metrics[ :organizations ] }
- Total Users: #{ metrics[ :users ] }
- Total Projects: #{ metrics[ :projects ] }
- Total Applications: #{ metrics[ :applications ] }
Averages:
- Users per Organization: #{ avg_users_per_org. round ( 1 ) }
- Projects per Organization: #{ avg_projects_per_org. round ( 1 ) }
- Applications per Project: #{ avg_apps_per_project. round ( 1 ) }
Growth Rate: (calculate based on historical data)
REPORT
puts report
report
end
Feature Usage Tracking
def track_feature_usage
organizations = list_all_organizations
feature_stats = {
actions_enabled: 0 ,
mfa_enforced: 0 ,
custom_domains: 0 ,
external_idp: 0
}
resource_counts = organizations. map do | org |
# Check features
features = get_organization_features (org. id )
feature_stats[ :actions_enabled ] += 1 if features. actions &. enabled
settings = get_organization_settings (org. id )
feature_stats[ :mfa_enforced ] += 1 if settings. force_mfa
# Count resources
{
organization_id: org. id ,
user_count: count_users (org. id ),
action_count: count_actions (org. id ),
# Add custom metrics
custom_metrics: {
actions_enabled: features. actions &. enabled ,
mfa_enforced: settings. force_mfa
}
}
end
# Report to telemetry
base = telemetry_service. report_base_information (...)
telemetry_service. report_resource_counts (
system_id: ENV [ 'ZITADEL_SYSTEM_ID' ],
report_id: base. report_id ,
resource_counts: resource_counts
)
feature_stats
end
Batch Reporting
For large installations, report in batches:
def batch_resource_report ( batch_size: 100 )
base_response = telemetry_service. report_base_information (...)
report_id = base_response. report_id
organizations = list_all_organizations
organizations. each_slice (batch_size). with_index do | batch , index |
puts "Processing batch #{ index + 1 } ..."
counts = batch. map { | org | collect_org_counts (org) }
telemetry_service. report_resource_counts (
system_id: ENV [ 'ZITADEL_SYSTEM_ID' ],
report_id: report_id,
resource_counts: counts
)
# Small delay between batches
sleep ( 1 )
end
puts "Batch reporting complete"
end
Report Linking
Reports are linked by:
system_id : Identifies your ZITADEL installation
report_id : Links resource counts to base information
# Base report creates report_id
base = telemetry_service. report_base_information (
system_id: 'sys_123'
)
# Use same report_id for all resource count batches
telemetry_service. report_resource_counts (
system_id: 'sys_123' ,
report_id: base. report_id , # Same ID
resource_counts: batch_1
)
telemetry_service. report_resource_counts (
system_id: 'sys_123' ,
report_id: base. report_id , # Same ID
resource_counts: batch_2
)
Resource Types
Typical resources to count:
Users : Total users per organization
Organizations : Total organizations
Projects : Projects per organization
Applications : Applications per project/organization
Sessions : Active sessions
Actions : Configured actions/targets
Authorizations : User grants
Identity Providers : Configured IDPs
Privacy Considerations
Telemetry should only include aggregate counts and metadata, not personally identifiable information (PII).
What to include:
Resource counts
Feature flags
Configuration settings
System version
Creation dates
What NOT to include:
User names
Email addresses
Personal data
Sensitive configuration values
Error Handling
def safe_telemetry_report
begin
base = telemetry_service. report_base_information (...)
telemetry_service. report_resource_counts (...)
puts "Telemetry reported successfully"
rescue Zitadel :: Client :: ApiError => e
# Log error but don't fail main application
Rails . logger . error "Telemetry reporting failed: #{ e. message } "
rescue => e
Rails . logger . error "Unexpected telemetry error: #{ e. message } "
end
end
Automated Monitoring
class TelemetryReporter
def initialize
@telemetry_service = Zitadel :: Client :: Api :: BetaTelemetryServiceApi . new
end
def daily_report
# Collect system information
base_info = collect_base_information
# Report base information
base_response = @telemetry_service . report_base_information (base_info)
# Collect and report resource counts
report_all_resources (base_response. report_id )
# Log metrics
log_metrics (base_response. report_id )
end
private
def collect_base_information
instances = InstanceService . list_instances . result
Zitadel :: Client :: Models :: BetaTelemetryServiceReportBaseInformationRequest . new (
system_id: ENV [ 'ZITADEL_SYSTEM_ID' ],
version: ZITADEL :: VERSION ,
instances: instances. map { | i |
{
instance_id: i. id ,
creation_date: i. creation_date ,
domains: i. domains
}
}
)
end
def report_all_resources ( report_id )
organizations = OrganizationService . list_all
organizations. each_slice ( 100 ) do | batch |
counts = batch. map { | org | collect_org_metrics (org) }
@telemetry_service . report_resource_counts (
system_id: ENV [ 'ZITADEL_SYSTEM_ID' ],
report_id: report_id,
resource_counts: counts
)
end
end
def collect_org_metrics ( org )
{
organization_id: org. id ,
user_count: UserService . count ( organization_id: org. id ),
project_count: ProjectService . count ( organization_id: org. id ),
application_count: AppService . count ( organization_id: org. id ),
session_count: SessionService . count_active ( organization_id: org. id ),
action_count: ActionService . count ( organization_id: org. id )
}
end
def log_metrics ( report_id )
Rails . logger . info "Telemetry report completed: #{ report_id } "
end
end
# Usage
reporter = TelemetryReporter . new
reporter. daily_report
Best Practices
Report telemetry on a regular schedule (daily or weekly)
Use background jobs to avoid blocking main application
Handle failures gracefully
Ensure counts are accurate and up-to-date
Use database queries or caching for performance
Verify counts before reporting
Never include PII in reports
Only send aggregate statistics
Follow data protection regulations
Don’t let telemetry failures affect main application
Log errors for debugging
Implement retry logic for transient failures
Migration Guide
Future versions may have updated telemetry APIs:
Monitor ZITADEL release notes
Update reporting structure as needed
Test telemetry integration
Update monitoring dashboards
See Also