Documentation
¶
Index ¶
- Constants
- func IsBuiltinTool(name string) bool
- func IsValidErrorCategory(c ErrorCategory) bool
- func MaybePrintFirstRunNotice(cfg *config.Config, w io.Writer) bool
- func RecordBuiltinToolOn(reg *CounterRegistry, name string)
- func RecordErrorOn(reg *CounterRegistry, c ErrorCategory)
- func RecordRESTRequestOn(reg *CounterRegistry, method, template, statusClass string)
- func RecordSurfaceOn(reg *CounterRegistry, s Surface)
- func RecordUpstreamToolOn(reg *CounterRegistry)
- func SortedOAuthProviderTypes(types []string) []string
- func ValidateCategory(category string) bool
- func ValidateMessage(message string) error
- type CounterRegistry
- func (r *CounterRegistry) RecordBuiltinTool(name string)
- func (r *CounterRegistry) RecordDoctorRun(results []DoctorCheckResult)
- func (r *CounterRegistry) RecordError(c ErrorCategory)
- func (r *CounterRegistry) RecordRESTRequest(method, template, statusClass string)
- func (r *CounterRegistry) RecordSurface(s Surface)
- func (r *CounterRegistry) RecordUpstreamTool()
- func (r *CounterRegistry) Reset()
- func (r *CounterRegistry) Snapshot() RegistrySnapshot
- type DoctorCheckResult
- type DoctorCounts
- type EnvDisabledReason
- type ErrorCategory
- type FeatureFlagSnapshot
- type FeedbackContext
- type FeedbackRequest
- type FeedbackResponse
- type HeartbeatPayload
- type RateLimiter
- type RegistrySnapshot
- type RuntimeStats
- type Service
- func (s *Service) BuildPayload() HeartbeatPayload
- func (s *Service) EnvDisabledReason() EnvDisabledReason
- func (s *Service) Registry() *CounterRegistry
- func (s *Service) SetRuntimeStats(stats RuntimeStats)
- func (s *Service) Start(ctx context.Context)
- func (s *Service) SubmitFeedback(ctx context.Context, req *FeedbackRequest) (*FeedbackResponse, error)
- type Surface
Constants ¶
const FirstRunNoticeText = `` /* 192-byte string literal not displayed */
FirstRunNoticeText is the one-time banner printed to stderr the first time `mcpproxy serve` runs against a config that has no telemetry_notice_shown flag. Spec 042 User Story 10.
const SchemaVersion = 2
SchemaVersion is the heartbeat payload schema version. v1 payloads have no such field; receivers can route by absence vs presence.
Variables ¶
This section is empty.
Functions ¶
func IsBuiltinTool ¶ added in v0.24.0
IsBuiltinTool reports whether the given tool name is in the fixed enum.
func IsValidErrorCategory ¶ added in v0.24.0
func IsValidErrorCategory(c ErrorCategory) bool
IsValidErrorCategory reports whether the given category is in the fixed enum.
func MaybePrintFirstRunNotice ¶ added in v0.24.0
MaybePrintFirstRunNotice prints the first-run telemetry notice to w if it has not been shown before. It mutates cfg.Telemetry.NoticeShown so the caller can persist the change. Returns true if the notice was printed.
Spec 042 User Story 10. Idempotent: subsequent calls with the same config are no-ops.
func RecordBuiltinToolOn ¶ added in v0.24.0
func RecordBuiltinToolOn(reg *CounterRegistry, name string)
RecordBuiltinToolOn calls reg.RecordBuiltinTool(name) if reg is non-nil.
func RecordErrorOn ¶ added in v0.24.0
func RecordErrorOn(reg *CounterRegistry, c ErrorCategory)
RecordErrorOn calls reg.RecordError(c) if reg is non-nil.
func RecordRESTRequestOn ¶ added in v0.24.0
func RecordRESTRequestOn(reg *CounterRegistry, method, template, statusClass string)
RecordRESTRequestOn calls reg.RecordRESTRequest(...) if reg is non-nil.
func RecordSurfaceOn ¶ added in v0.24.0
func RecordSurfaceOn(reg *CounterRegistry, s Surface)
RecordSurfaceOn calls reg.RecordSurface(s) if reg is non-nil.
func RecordUpstreamToolOn ¶ added in v0.24.0
func RecordUpstreamToolOn(reg *CounterRegistry)
RecordUpstreamToolOn calls reg.RecordUpstreamTool() if reg is non-nil.
func SortedOAuthProviderTypes ¶ added in v0.24.0
SortedOAuthProviderTypes returns a sorted, deduplicated list. Helper used by feature_flags.go but defined here to avoid an extra file.
func ValidateCategory ¶
ValidateCategory checks if the feedback category is valid.
func ValidateMessage ¶
ValidateMessage checks if the feedback message meets length requirements.
Types ¶
type CounterRegistry ¶ added in v0.24.0
type CounterRegistry struct {
// contains filtered or unexported fields
}
CounterRegistry aggregates Tier 2 telemetry counters in memory. All methods are safe for concurrent use. Counters are zeroed only by Reset(), which the telemetry service calls after a successful heartbeat send.
func NewCounterRegistry ¶ added in v0.24.0
func NewCounterRegistry() *CounterRegistry
NewCounterRegistry creates an empty registry. All counters start at zero.
func (*CounterRegistry) RecordBuiltinTool ¶ added in v0.24.0
func (r *CounterRegistry) RecordBuiltinTool(name string)
RecordBuiltinTool increments the counter for the named built-in tool. Unknown names (i.e., upstream tool names) are silently dropped.
func (*CounterRegistry) RecordDoctorRun ¶ added in v0.24.0
func (r *CounterRegistry) RecordDoctorRun(results []DoctorCheckResult)
RecordDoctorRun aggregates the structured doctor check results into the registry's doctor counter. Each result increments either Pass or Fail for its check name.
func (*CounterRegistry) RecordError ¶ added in v0.24.0
func (r *CounterRegistry) RecordError(c ErrorCategory)
RecordError increments the counter for the given error category. Unknown categories are silently dropped.
func (*CounterRegistry) RecordRESTRequest ¶ added in v0.24.0
func (r *CounterRegistry) RecordRESTRequest(method, template, statusClass string)
RecordRESTRequest increments the counter for the given route template and status class. Both inputs are expected to be from a fixed enum (Chi route template + "2xx"/"3xx"/"4xx"/"5xx") so no sanitization is needed here.
func (*CounterRegistry) RecordSurface ¶ added in v0.24.0
func (r *CounterRegistry) RecordSurface(s Surface)
RecordSurface increments the counter for the given surface.
func (*CounterRegistry) RecordUpstreamTool ¶ added in v0.24.0
func (r *CounterRegistry) RecordUpstreamTool()
RecordUpstreamTool increments the upstream tool call counter. The tool name itself is intentionally not accepted: only an aggregate count is recorded.
func (*CounterRegistry) Reset ¶ added in v0.24.0
func (r *CounterRegistry) Reset()
Reset zeros all counters. Called only after a successful heartbeat send.
func (*CounterRegistry) Snapshot ¶ added in v0.24.0
func (r *CounterRegistry) Snapshot() RegistrySnapshot
Snapshot returns an immutable view of all counters. The registry is NOT reset; call Reset() after a successful flush.
type DoctorCheckResult ¶ added in v0.24.0
DoctorCheckResult is the minimal interface the registry needs to record a doctor check outcome. It is satisfied by internal/doctor.CheckResult without importing that package (avoiding an import cycle).
type DoctorCounts ¶ added in v0.24.0
DoctorCounts holds pass/fail counts for a single doctor check.
type EnvDisabledReason ¶ added in v0.24.0
type EnvDisabledReason string
EnvDisabledReason explains why telemetry was disabled by an environment variable, if any. The empty string means env did not disable telemetry.
const ( EnvDisabledNone EnvDisabledReason = "" EnvDisabledByDoNotTrack EnvDisabledReason = "DO_NOT_TRACK" EnvDisabledByCI EnvDisabledReason = "CI" EnvDisabledByMCPProxy EnvDisabledReason = "MCPPROXY_TELEMETRY=false" )
func IsDisabledByEnv ¶ added in v0.24.0
func IsDisabledByEnv() (bool, EnvDisabledReason)
IsDisabledByEnv evaluates the env var precedence chain for telemetry disablement. Precedence (highest first):
- DO_NOT_TRACK set to any non-empty, non-"0" value (consoledonottrack.com)
- CI=true or CI=1
- MCPPROXY_TELEMETRY=false
Returns true and the reason if telemetry should be disabled.
type ErrorCategory ¶ added in v0.24.0
type ErrorCategory string
ErrorCategory is a typed enum of error categories that telemetry will count. Only values defined here may be recorded; unknown categories are silently dropped by RecordError to prevent free-text error messages from leaking into telemetry.
const ( ErrCatOAuthRefreshFailed ErrorCategory = "oauth_refresh_failed" ErrCatOAuthTokenExpired ErrorCategory = "oauth_token_expired" ErrCatUpstreamConnectTimeout ErrorCategory = "upstream_connect_timeout" ErrCatUpstreamConnectRefused ErrorCategory = "upstream_connect_refused" ErrCatUpstreamHandshakeFailed ErrorCategory = "upstream_handshake_failed" ErrCatToolQuarantineBlocked ErrorCategory = "tool_quarantine_blocked" ErrCatDockerPullFailed ErrorCategory = "docker_pull_failed" ErrCatDockerRunFailed ErrorCategory = "docker_run_failed" ErrCatIndexRebuildFailed ErrorCategory = "index_rebuild_failed" ErrCatConfigReloadFailed ErrorCategory = "config_reload_failed" ErrCatSocketBindFailed ErrorCategory = "socket_bind_failed" )
type FeatureFlagSnapshot ¶ added in v0.24.0
type FeatureFlagSnapshot struct {
EnableSocket bool `json:"enable_socket"`
EnableWebUI bool `json:"enable_web_ui"`
EnablePrompts bool `json:"enable_prompts"`
RequireMCPAuth bool `json:"require_mcp_auth"`
EnableCodeExecution bool `json:"enable_code_execution"`
QuarantineEnabled bool `json:"quarantine_enabled"`
SensitiveDataDetectionEnabled bool `json:"sensitive_data_detection_enabled"`
OAuthProviderTypes []string `json:"oauth_provider_types"`
}
FeatureFlagSnapshot captures the boolean / enum feature flags reported in the daily heartbeat. Spec 042 User Story 4.
func BuildFeatureFlagSnapshot ¶ added in v0.24.0
func BuildFeatureFlagSnapshot(cfg *config.Config) *FeatureFlagSnapshot
BuildFeatureFlagSnapshot returns a snapshot of the current feature flag state. It records boolean flags and a sorted, deduplicated list of OAuth provider TYPES (not URLs, client IDs, or tenant identifiers). The empty list is returned if no upstream servers have OAuth configured.
type FeedbackContext ¶
type FeedbackContext struct {
Version string `json:"version"`
Edition string `json:"edition"`
OS string `json:"os"`
Arch string `json:"arch"`
ServerCount int `json:"server_count"`
ConnectedServerCount int `json:"connected_server_count"`
RoutingMode string `json:"routing_mode"`
}
FeedbackContext provides automatic system context alongside feedback.
type FeedbackRequest ¶
type FeedbackRequest struct {
Category string `json:"category"` // bug, feature, other
Message string `json:"message"`
Email string `json:"email,omitempty"`
Context FeedbackContext `json:"context"`
}
FeedbackRequest is the user-submitted feedback payload.
type FeedbackResponse ¶
type FeedbackResponse struct {
Success bool `json:"success"`
IssueURL string `json:"issue_url,omitempty"`
Error string `json:"error,omitempty"`
}
FeedbackResponse is the response from the telemetry backend.
type HeartbeatPayload ¶
type HeartbeatPayload struct {
// v1 fields (preserved unchanged)
AnonymousID string `json:"anonymous_id"`
Version string `json:"version"`
Edition string `json:"edition"`
OS string `json:"os"`
Arch string `json:"arch"`
GoVersion string `json:"go_version"`
ServerCount int `json:"server_count"`
ConnectedServerCount int `json:"connected_server_count"`
ToolCount int `json:"tool_count"`
UptimeHours int `json:"uptime_hours"`
RoutingMode string `json:"routing_mode"`
QuarantineEnabled bool `json:"quarantine_enabled"`
Timestamp string `json:"timestamp"`
// Spec 042 (Tier 2) additions
SchemaVersion int `json:"schema_version,omitempty"`
AnonymousIDCreatedAt string `json:"anonymous_id_created_at,omitempty"`
CurrentVersion string `json:"current_version,omitempty"`
PreviousVersion string `json:"previous_version"`
LastStartupOutcome string `json:"last_startup_outcome,omitempty"`
SurfaceRequests map[string]int64 `json:"surface_requests,omitempty"`
BuiltinToolCalls map[string]int64 `json:"builtin_tool_calls,omitempty"`
UpstreamToolCallCountBucket string `json:"upstream_tool_call_count_bucket,omitempty"`
RESTEndpointCalls map[string]map[string]int64 `json:"rest_endpoint_calls,omitempty"`
FeatureFlags *FeatureFlagSnapshot `json:"feature_flags,omitempty"`
ErrorCategoryCounts map[string]int64 `json:"error_category_counts,omitempty"`
DoctorChecks map[string]DoctorCounts `json:"doctor_checks,omitempty"`
}
HeartbeatPayload is the anonymous telemetry payload sent periodically. Spec 042 expanded the payload with Tier 2 fields; v1 fields are preserved.
type RateLimiter ¶
type RateLimiter struct {
// contains filtered or unexported fields
}
RateLimiter enforces a maximum number of requests per hour.
func NewRateLimiter ¶
func NewRateLimiter(maxPerHour int) *RateLimiter
NewRateLimiter creates a rate limiter with the given max requests per hour.
func (*RateLimiter) Allow ¶
func (rl *RateLimiter) Allow() bool
Allow returns true if the request is within the rate limit.
type RegistrySnapshot ¶ added in v0.24.0
type RegistrySnapshot struct {
SurfaceCounts map[string]int64 `json:"surface_requests"`
BuiltinToolCalls map[string]int64 `json:"builtin_tool_calls"`
UpstreamToolCallCountBucket string `json:"upstream_tool_call_count_bucket"`
RESTEndpointCalls map[string]map[string]int64 `json:"rest_endpoint_calls"`
ErrorCategoryCounts map[string]int64 `json:"error_category_counts"`
DoctorChecks map[string]DoctorCounts `json:"doctor_checks"`
}
RegistrySnapshot is an immutable view of the registry built by Snapshot(). It is safe to mutate the maps in a snapshot — they are copies.
type RuntimeStats ¶
type RuntimeStats interface {
GetServerCount() int
GetConnectedServerCount() int
GetToolCount() int
GetRoutingMode() string
IsQuarantineEnabled() bool
}
RuntimeStats is an interface to decouple from the runtime package.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service manages anonymous telemetry heartbeats and feedback submission.
func (*Service) BuildPayload ¶ added in v0.24.0
func (s *Service) BuildPayload() HeartbeatPayload
BuildPayload renders the heartbeat payload at the current point in time. It is exported so the `mcpproxy telemetry show-payload` command can render the same payload that would next be sent, without making a network call.
func (*Service) EnvDisabledReason ¶ added in v0.24.0
func (s *Service) EnvDisabledReason() EnvDisabledReason
EnvDisabledReason returns the env-var reason telemetry is disabled, if any.
func (*Service) Registry ¶ added in v0.24.0
func (s *Service) Registry() *CounterRegistry
Registry returns the counter registry for Tier 2 telemetry events. Always non-nil after New, even if telemetry is disabled — that way callers can always Record* without nil checks; the data simply never leaves the process.
func (*Service) SetRuntimeStats ¶
func (s *Service) SetRuntimeStats(stats RuntimeStats)
SetRuntimeStats sets the runtime stats provider (called after runtime is fully initialized).
func (*Service) Start ¶
Start begins the telemetry heartbeat loop. This is a blocking call; run in a goroutine.
func (*Service) SubmitFeedback ¶
func (s *Service) SubmitFeedback(ctx context.Context, req *FeedbackRequest) (*FeedbackResponse, error)
SubmitFeedback sends feedback to the telemetry backend.
type Surface ¶ added in v0.24.0
type Surface int
Surface identifies which client surface originated a request.
func ParseClientSurface ¶ added in v0.24.0
ParseClientSurface maps the X-MCPProxy-Client header value to a Surface enum. The expected format is "<surface>/<version>"; unknown prefixes and missing headers map to SurfaceUnknown.