More metrics
parent
358b344916
commit
ca9fed7b67
|
@ -1099,7 +1099,7 @@ If a non-200 HTTP status code is returned or if the returned `health` field is `
|
||||||
|
|
||||||
See [Installation for Docker](install.md#docker) for an example of how this could be used in a `docker-compose` environment.
|
See [Installation for Docker](install.md#docker) for an example of how this could be used in a `docker-compose` environment.
|
||||||
|
|
||||||
## Metrics
|
## Monitoring
|
||||||
If configured, ntfy can expose a `/metrics` endpoint for [Prometheus](https://prometheus.io/), which can then be used to
|
If configured, ntfy can expose a `/metrics` endpoint for [Prometheus](https://prometheus.io/), which can then be used to
|
||||||
create dashboards and alerts (e.g. via [Grafana](https://grafana.com/)).
|
create dashboards and alerts (e.g. via [Grafana](https://grafana.com/)).
|
||||||
|
|
||||||
|
@ -1108,7 +1108,7 @@ listen address. Metrics may be considered sensitive information, so before you e
|
||||||
doing, and/or secure access to the endpoint in your reverse proxy.
|
doing, and/or secure access to the endpoint in your reverse proxy.
|
||||||
|
|
||||||
- `enable-metrics` enables the /metrics endpoint for the default ntfy server (i.e. HTTP, HTTPS and/or Unix socket)
|
- `enable-metrics` enables the /metrics endpoint for the default ntfy server (i.e. HTTP, HTTPS and/or Unix socket)
|
||||||
- `metrics-listen-http` exposes the metrics endpoint via a dedicated [IP]:port. If set, this option implicitly
|
- `metrics-listen-http` exposes the metrics endpoint via a dedicated `[IP]:port`. If set, this option implicitly
|
||||||
enables metrics as well, e.g. "10.0.1.1:9090" or ":9090"
|
enables metrics as well, e.g. "10.0.1.1:9090" or ":9090"
|
||||||
|
|
||||||
=== Using default port
|
=== Using default port
|
||||||
|
|
|
@ -618,6 +618,7 @@ func (s *Server) handleMatrixDiscovery(w http.ResponseWriter) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) handlePublishInternal(r *http.Request, v *visitor) (*message, error) {
|
func (s *Server) handlePublishInternal(r *http.Request, v *visitor) (*message, error) {
|
||||||
|
start := time.Now()
|
||||||
t, err := fromContext[*topic](r, contextTopic)
|
t, err := fromContext[*topic](r, contextTopic)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -707,6 +708,7 @@ func (s *Server) handlePublishInternal(r *http.Request, v *visitor) (*message, e
|
||||||
if unifiedpush {
|
if unifiedpush {
|
||||||
minc(metricUnifiedPushPublishedSuccess)
|
minc(metricUnifiedPushPublishedSuccess)
|
||||||
}
|
}
|
||||||
|
mset(metricMessagePublishDurationMillis, time.Since(start).Milliseconds())
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,15 @@ func (s *Server) execManager() {
|
||||||
sentMailTotal, sentMailSuccess, sentMailFailure = s.smtpSender.Counts()
|
sentMailTotal, sentMailSuccess, sentMailFailure = s.smtpSender.Counts()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Users
|
||||||
|
var usersCount int64
|
||||||
|
if s.userManager != nil {
|
||||||
|
usersCount, err = s.userManager.UsersCount()
|
||||||
|
if err != nil {
|
||||||
|
log.Tag(tagManager).Err(err).Warn("Error counting users")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Print stats
|
// Print stats
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
messagesCount, topicsCount, visitorsCount := s.messages, len(s.topics), len(s.visitors)
|
messagesCount, topicsCount, visitorsCount := s.messages, len(s.topics), len(s.visitors)
|
||||||
|
@ -75,6 +84,7 @@ func (s *Server) execManager() {
|
||||||
"topics_active": topicsCount,
|
"topics_active": topicsCount,
|
||||||
"subscribers": subscribers,
|
"subscribers": subscribers,
|
||||||
"visitors": visitorsCount,
|
"visitors": visitorsCount,
|
||||||
|
"users": usersCount,
|
||||||
"emails_received": receivedMailTotal,
|
"emails_received": receivedMailTotal,
|
||||||
"emails_received_success": receivedMailSuccess,
|
"emails_received_success": receivedMailSuccess,
|
||||||
"emails_received_failure": receivedMailFailure,
|
"emails_received_failure": receivedMailFailure,
|
||||||
|
@ -85,6 +95,7 @@ func (s *Server) execManager() {
|
||||||
Info("Server stats")
|
Info("Server stats")
|
||||||
mset(metricMessagesCached, messagesCached)
|
mset(metricMessagesCached, messagesCached)
|
||||||
mset(metricVisitors, visitorsCount)
|
mset(metricVisitors, visitorsCount)
|
||||||
|
mset(metricUsers, usersCount)
|
||||||
mset(metricSubscribers, subscribers)
|
mset(metricSubscribers, subscribers)
|
||||||
mset(metricTopics, topicsCount)
|
mset(metricTopics, topicsCount)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,23 +5,25 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
metricMessagesPublishedSuccess prometheus.Counter
|
metricMessagesPublishedSuccess prometheus.Counter
|
||||||
metricMessagesPublishedFailure prometheus.Counter
|
metricMessagesPublishedFailure prometheus.Counter
|
||||||
metricMessagesCached prometheus.Gauge
|
metricMessagesCached prometheus.Gauge
|
||||||
metricFirebasePublishedSuccess prometheus.Counter
|
metricMessagePublishDurationMillis prometheus.Gauge
|
||||||
metricFirebasePublishedFailure prometheus.Counter
|
metricFirebasePublishedSuccess prometheus.Counter
|
||||||
metricEmailsPublishedSuccess prometheus.Counter
|
metricFirebasePublishedFailure prometheus.Counter
|
||||||
metricEmailsPublishedFailure prometheus.Counter
|
metricEmailsPublishedSuccess prometheus.Counter
|
||||||
metricEmailsReceivedSuccess prometheus.Counter
|
metricEmailsPublishedFailure prometheus.Counter
|
||||||
metricEmailsReceivedFailure prometheus.Counter
|
metricEmailsReceivedSuccess prometheus.Counter
|
||||||
metricUnifiedPushPublishedSuccess prometheus.Counter
|
metricEmailsReceivedFailure prometheus.Counter
|
||||||
metricMatrixPublishedSuccess prometheus.Counter
|
metricUnifiedPushPublishedSuccess prometheus.Counter
|
||||||
metricMatrixPublishedFailure prometheus.Counter
|
metricMatrixPublishedSuccess prometheus.Counter
|
||||||
metricAttachmentsTotalSize prometheus.Gauge
|
metricMatrixPublishedFailure prometheus.Counter
|
||||||
metricVisitors prometheus.Gauge
|
metricAttachmentsTotalSize prometheus.Gauge
|
||||||
metricSubscribers prometheus.Gauge
|
metricVisitors prometheus.Gauge
|
||||||
metricTopics prometheus.Gauge
|
metricSubscribers prometheus.Gauge
|
||||||
metricHTTPRequests *prometheus.CounterVec
|
metricTopics prometheus.Gauge
|
||||||
|
metricUsers prometheus.Gauge
|
||||||
|
metricHTTPRequests *prometheus.CounterVec
|
||||||
)
|
)
|
||||||
|
|
||||||
func initMetrics() {
|
func initMetrics() {
|
||||||
|
@ -34,6 +36,9 @@ func initMetrics() {
|
||||||
metricMessagesCached = prometheus.NewGauge(prometheus.GaugeOpts{
|
metricMessagesCached = prometheus.NewGauge(prometheus.GaugeOpts{
|
||||||
Name: "ntfy_messages_cached_total",
|
Name: "ntfy_messages_cached_total",
|
||||||
})
|
})
|
||||||
|
metricMessagePublishDurationMillis = prometheus.NewGauge(prometheus.GaugeOpts{
|
||||||
|
Name: "ntfy_message_publish_duration_ms",
|
||||||
|
})
|
||||||
metricFirebasePublishedSuccess = prometheus.NewCounter(prometheus.CounterOpts{
|
metricFirebasePublishedSuccess = prometheus.NewCounter(prometheus.CounterOpts{
|
||||||
Name: "ntfy_firebase_published_success",
|
Name: "ntfy_firebase_published_success",
|
||||||
})
|
})
|
||||||
|
@ -67,6 +72,9 @@ func initMetrics() {
|
||||||
metricVisitors = prometheus.NewGauge(prometheus.GaugeOpts{
|
metricVisitors = prometheus.NewGauge(prometheus.GaugeOpts{
|
||||||
Name: "ntfy_visitors_total",
|
Name: "ntfy_visitors_total",
|
||||||
})
|
})
|
||||||
|
metricUsers = prometheus.NewGauge(prometheus.GaugeOpts{
|
||||||
|
Name: "ntfy_users_total",
|
||||||
|
})
|
||||||
metricSubscribers = prometheus.NewGauge(prometheus.GaugeOpts{
|
metricSubscribers = prometheus.NewGauge(prometheus.GaugeOpts{
|
||||||
Name: "ntfy_subscribers_total",
|
Name: "ntfy_subscribers_total",
|
||||||
})
|
})
|
||||||
|
@ -80,6 +88,7 @@ func initMetrics() {
|
||||||
metricMessagesPublishedSuccess,
|
metricMessagesPublishedSuccess,
|
||||||
metricMessagesPublishedFailure,
|
metricMessagesPublishedFailure,
|
||||||
metricMessagesCached,
|
metricMessagesCached,
|
||||||
|
metricMessagePublishDurationMillis,
|
||||||
metricFirebasePublishedSuccess,
|
metricFirebasePublishedSuccess,
|
||||||
metricFirebasePublishedFailure,
|
metricFirebasePublishedFailure,
|
||||||
metricEmailsPublishedSuccess,
|
metricEmailsPublishedSuccess,
|
||||||
|
@ -91,6 +100,7 @@ func initMetrics() {
|
||||||
metricMatrixPublishedFailure,
|
metricMatrixPublishedFailure,
|
||||||
metricAttachmentsTotalSize,
|
metricAttachmentsTotalSize,
|
||||||
metricVisitors,
|
metricVisitors,
|
||||||
|
metricUsers,
|
||||||
metricSubscribers,
|
metricSubscribers,
|
||||||
metricTopics,
|
metricTopics,
|
||||||
metricHTTPRequests,
|
metricHTTPRequests,
|
||||||
|
|
|
@ -169,6 +169,7 @@ const (
|
||||||
ELSE 2
|
ELSE 2
|
||||||
END, user
|
END, user
|
||||||
`
|
`
|
||||||
|
selectUserCountQuery = `SELECT COUNT(*) FROM user`
|
||||||
updateUserPassQuery = `UPDATE user SET pass = ? WHERE user = ?`
|
updateUserPassQuery = `UPDATE user SET pass = ? WHERE user = ?`
|
||||||
updateUserRoleQuery = `UPDATE user SET role = ? WHERE user = ?`
|
updateUserRoleQuery = `UPDATE user SET role = ? WHERE user = ?`
|
||||||
updateUserPrefsQuery = `UPDATE user SET prefs = ? WHERE id = ?`
|
updateUserPrefsQuery = `UPDATE user SET prefs = ? WHERE id = ?`
|
||||||
|
@ -853,6 +854,23 @@ func (a *Manager) Users() ([]*User, error) {
|
||||||
return users, nil
|
return users, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UsersCount returns the number of users in the databsae
|
||||||
|
func (a *Manager) UsersCount() (int64, error) {
|
||||||
|
rows, err := a.db.Query(selectUserCountQuery)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
if !rows.Next() {
|
||||||
|
return 0, errNoRows
|
||||||
|
}
|
||||||
|
var count int64
|
||||||
|
if err := rows.Scan(&count); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return count, nil
|
||||||
|
}
|
||||||
|
|
||||||
// User returns the user with the given username if it exists, or ErrUserNotFound otherwise.
|
// User returns the user with the given username if it exists, or ErrUserNotFound otherwise.
|
||||||
// You may also pass Everyone to retrieve the anonymous user and its Grant list.
|
// You may also pass Everyone to retrieve the anonymous user and its Grant list.
|
||||||
func (a *Manager) User(username string) (*User, error) {
|
func (a *Manager) User(username string) (*User, error) {
|
||||||
|
|
Loading…
Reference in New Issue