sftpgo-mirror/metrics/metrics.go
2020-07-29 21:56:56 +02:00

635 lines
22 KiB
Go

// +build !nometrics
// Package metrics provides Prometheus metrics support
package metrics
import (
"github.com/go-chi/chi"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/drakkan/sftpgo/version"
)
const (
loginMethodPublicKey = "publickey"
loginMethodKeyboardInteractive = "keyboard-interactive"
loginMethodKeyAndPassword = "publickey+password"
loginMethodKeyAndKeyboardInt = "publickey+keyboard-interactive"
)
func init() {
version.AddFeature("+metrics")
}
var (
// dataproviderAvailability is the metric that reports the availability for the configured data provider
dataproviderAvailability = promauto.NewGauge(prometheus.GaugeOpts{
Name: "sftpgo_dataprovider_availability",
Help: "Availability for the configured data provider, 1 means OK, 0 KO",
})
// activeConnections is the metric that reports the total number of active connections
activeConnections = promauto.NewGauge(prometheus.GaugeOpts{
Name: "sftpgo_active_connections",
Help: "Total number of logged in users",
})
// totalUploads is the metric that reports the total number of successful uploads
totalUploads = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_uploads_total",
Help: "The total number of successful uploads",
})
// totalDownloads is the metric that reports the total number of successful downloads
totalDownloads = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_downloads_total",
Help: "The total number of successful downloads",
})
// totalUploadErrors is the metric that reports the total number of upload errors
totalUploadErrors = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_upload_errors_total",
Help: "The total number of upload errors",
})
// totalDownloadErrors is the metric that reports the total number of download errors
totalDownloadErrors = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_download_errors_total",
Help: "The total number of download errors",
})
// totalUploadSize is the metric that reports the total uploads size as bytes
totalUploadSize = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_upload_size",
Help: "The total upload size as bytes, partial uploads are included",
})
// totalDownloadSize is the metric that reports the total downloads size as bytes
totalDownloadSize = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_download_size",
Help: "The total download size as bytes, partial downloads are included",
})
// totalSSHCommands is the metric that reports the total number of executed SSH commands
totalSSHCommands = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_ssh_commands_total",
Help: "The total number of executed SSH commands",
})
// totalSSHCommandErrors is the metric that reports the total number of SSH command errors
totalSSHCommandErrors = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_ssh_command_errors_total",
Help: "The total number of SSH command errors",
})
// totalLoginAttempts is the metric that reports the total number of login attempts
totalLoginAttempts = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_login_attempts_total",
Help: "The total number of login attempts",
})
// totalNoAuthTryed is te metric that reports the total number of clients disconnected
// for inactivity before trying to login
totalNoAuthTryed = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_no_auth_total",
Help: "The total number of clients disconnected for inactivity before trying to login",
})
// totalLoginOK is the metric that reports the total number of successful logins
totalLoginOK = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_login_ok_total",
Help: "The total number of successful logins",
})
// totalLoginFailed is the metric that reports the total number of failed logins
totalLoginFailed = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_login_ko_total",
Help: "The total number of failed logins",
})
// totalPasswordLoginAttempts is the metric that reports the total number of login attempts
// using a password
totalPasswordLoginAttempts = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_password_login_attempts_total",
Help: "The total number of login attempts using a password",
})
// totalPasswordLoginOK is the metric that reports the total number of successful logins
// using a password
totalPasswordLoginOK = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_password_login_ok_total",
Help: "The total number of successful logins using a password",
})
// totalPasswordLoginFailed is the metric that reports the total number of failed logins
// using a password
totalPasswordLoginFailed = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_password_login_ko_total",
Help: "The total number of failed logins using a password",
})
// totalKeyLoginAttempts is the metric that reports the total number of login attempts
// using a public key
totalKeyLoginAttempts = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_public_key_login_attempts_total",
Help: "The total number of login attempts using a public key",
})
// totalKeyLoginOK is the metric that reports the total number of successful logins
// using a public key
totalKeyLoginOK = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_public_key_login_ok_total",
Help: "The total number of successful logins using a public key",
})
// totalKeyLoginFailed is the metric that reports the total number of failed logins
// using a public key
totalKeyLoginFailed = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_public_key_login_ko_total",
Help: "The total number of failed logins using a public key",
})
// totalInteractiveLoginAttempts is the metric that reports the total number of login attempts
// using keyboard interactive authentication
totalInteractiveLoginAttempts = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_keyboard_interactive_login_attempts_total",
Help: "The total number of login attempts using keyboard interactive authentication",
})
// totalInteractiveLoginOK is the metric that reports the total number of successful logins
// using keyboard interactive authentication
totalInteractiveLoginOK = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_keyboard_interactive_login_ok_total",
Help: "The total number of successful logins using keyboard interactive authentication",
})
// totalInteractiveLoginFailed is the metric that reports the total number of failed logins
// using keyboard interactive authentication
totalInteractiveLoginFailed = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_keyboard_interactive_login_ko_total",
Help: "The total number of failed logins using keyboard interactive authentication",
})
// totalKeyAndPasswordLoginAttempts is the metric that reports the total number of
// login attempts using public key + password multi steps auth
totalKeyAndPasswordLoginAttempts = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_key_and_password_login_attempts_total",
Help: "The total number of login attempts using public key + password",
})
// totalKeyAndPasswordLoginOK is the metric that reports the total number of
// successful logins using public key + password multi steps auth
totalKeyAndPasswordLoginOK = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_key_and_password_login_ok_total",
Help: "The total number of successful logins using public key + password",
})
// totalKeyAndPasswordLoginFailed is the metric that reports the total number of
// failed logins using public key + password multi steps auth
totalKeyAndPasswordLoginFailed = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_key_and_password_login_ko_total",
Help: "The total number of failed logins using public key + password",
})
// totalKeyAndKeyIntLoginAttempts is the metric that reports the total number of
// login attempts using public key + keyboard interactive multi steps auth
totalKeyAndKeyIntLoginAttempts = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_key_and_keyboard_int_login_attempts_total",
Help: "The total number of login attempts using public key + keyboard interactive",
})
// totalKeyAndKeyIntLoginOK is the metric that reports the total number of
// successful logins using public key + keyboard interactive multi steps auth
totalKeyAndKeyIntLoginOK = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_key_and_keyboard_int_login_ok_total",
Help: "The total number of successful logins using public key + keyboard interactive",
})
// totalKeyAndKeyIntLoginFailed is the metric that reports the total number of
// failed logins using public key + keyboard interactive multi steps auth
totalKeyAndKeyIntLoginFailed = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_key_and_keyboard_int_login_ko_total",
Help: "The total number of failed logins using public key + keyboard interactive",
})
totalHTTPRequests = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_http_req_total",
Help: "The total number of HTTP requests served",
})
totalHTTPOK = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_http_req_ok_total",
Help: "The total number of HTTP requests served with 2xx status code",
})
totalHTTPClientErrors = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_http_client_errors_total",
Help: "The total number of HTTP requests served with 4xx status code",
})
totalHTTPServerErrors = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_http_server_errors_total",
Help: "The total number of HTTP requests served with 5xx status code",
})
// totalS3Uploads is the metric that reports the total number of successful S3 uploads
totalS3Uploads = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_s3_uploads_total",
Help: "The total number of successful S3 uploads",
})
// totalS3Downloads is the metric that reports the total number of successful S3 downloads
totalS3Downloads = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_s3_downloads_total",
Help: "The total number of successful S3 downloads",
})
// totalS3UploadErrors is the metric that reports the total number of S3 upload errors
totalS3UploadErrors = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_s3_upload_errors_total",
Help: "The total number of S3 upload errors",
})
// totalS3DownloadErrors is the metric that reports the total number of S3 download errors
totalS3DownloadErrors = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_s3_download_errors_total",
Help: "The total number of S3 download errors",
})
// totalS3UploadSize is the metric that reports the total S3 uploads size as bytes
totalS3UploadSize = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_s3_upload_size",
Help: "The total S3 upload size as bytes, partial uploads are included",
})
// totalS3DownloadSize is the metric that reports the total S3 downloads size as bytes
totalS3DownloadSize = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_s3_download_size",
Help: "The total S3 download size as bytes, partial downloads are included",
})
// totalS3ListObjects is the metric that reports the total successful S3 list objects requests
totalS3ListObjects = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_s3_list_objects",
Help: "The total number of successful S3 list objects requests",
})
// totalS3CopyObject is the metric that reports the total successful S3 copy object requests
totalS3CopyObject = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_s3_copy_object",
Help: "The total number of successful S3 copy object requests",
})
// totalS3DeleteObject is the metric that reports the total successful S3 delete object requests
totalS3DeleteObject = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_s3_delete_object",
Help: "The total number of successful S3 delete object requests",
})
// totalS3ListObjectsError is the metric that reports the total S3 list objects errors
totalS3ListObjectsErrors = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_s3_list_objects_errors",
Help: "The total number of S3 list objects errors",
})
// totalS3CopyObjectErrors is the metric that reports the total S3 copy object errors
totalS3CopyObjectErrors = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_s3_copy_object_errors",
Help: "The total number of S3 copy object errors",
})
// totalS3DeleteObjectErrors is the metric that reports the total S3 delete object errors
totalS3DeleteObjectErrors = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_s3_delete_object_errors",
Help: "The total number of S3 delete object errors",
})
// totalS3HeadBucket is the metric that reports the total successful S3 head bucket requests
totalS3HeadBucket = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_s3_head_bucket",
Help: "The total number of successful S3 head bucket requests",
})
// totalS3HeadBucketErrors is the metric that reports the total S3 head bucket errors
totalS3HeadBucketErrors = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_s3_head_bucket_errors",
Help: "The total number of S3 head bucket errors",
})
// totalGCSUploads is the metric that reports the total number of successful GCS uploads
totalGCSUploads = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_gcs_uploads_total",
Help: "The total number of successful GCS uploads",
})
// totalGCSDownloads is the metric that reports the total number of successful GCS downloads
totalGCSDownloads = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_gcs_downloads_total",
Help: "The total number of successful GCS downloads",
})
// totalGCSUploadErrors is the metric that reports the total number of GCS upload errors
totalGCSUploadErrors = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_gcs_upload_errors_total",
Help: "The total number of GCS upload errors",
})
// totalGCSDownloadErrors is the metric that reports the total number of GCS download errors
totalGCSDownloadErrors = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_gcs_download_errors_total",
Help: "The total number of GCS download errors",
})
// totalGCSUploadSize is the metric that reports the total GCS uploads size as bytes
totalGCSUploadSize = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_gcs_upload_size",
Help: "The total GCS upload size as bytes, partial uploads are included",
})
// totalGCSDownloadSize is the metric that reports the total GCS downloads size as bytes
totalGCSDownloadSize = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_gcs_download_size",
Help: "The total GCS download size as bytes, partial downloads are included",
})
// totalS3ListObjects is the metric that reports the total successful GCS list objects requests
totalGCSListObjects = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_gcs_list_objects",
Help: "The total number of successful GCS list objects requests",
})
// totalGCSCopyObject is the metric that reports the total successful GCS copy object requests
totalGCSCopyObject = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_gcs_copy_object",
Help: "The total number of successful GCS copy object requests",
})
// totalGCSDeleteObject is the metric that reports the total successful S3 delete object requests
totalGCSDeleteObject = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_gcs_delete_object",
Help: "The total number of successful GCS delete object requests",
})
// totalGCSListObjectsError is the metric that reports the total GCS list objects errors
totalGCSListObjectsErrors = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_gcs_list_objects_errors",
Help: "The total number of GCS list objects errors",
})
// totalGCSCopyObjectErrors is the metric that reports the total GCS copy object errors
totalGCSCopyObjectErrors = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_gcs_copy_object_errors",
Help: "The total number of GCS copy object errors",
})
// totalGCSDeleteObjectErrors is the metric that reports the total GCS delete object errors
totalGCSDeleteObjectErrors = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_gcs_delete_object_errors",
Help: "The total number of GCS delete object errors",
})
// totalGCSHeadBucket is the metric that reports the total successful GCS head bucket requests
totalGCSHeadBucket = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_gcs_head_bucket",
Help: "The total number of successful GCS head bucket requests",
})
// totalGCSHeadBucketErrors is the metric that reports the total GCS head bucket errors
totalGCSHeadBucketErrors = promauto.NewCounter(prometheus.CounterOpts{
Name: "sftpgo_gcs_head_bucket_errors",
Help: "The total number of GCS head bucket errors",
})
)
// AddMetricsEndpoint exposes metrics to the specified endpoint
func AddMetricsEndpoint(metricsPath string, handler chi.Router) {
handler.Handle(metricsPath, promhttp.Handler())
}
// TransferCompleted updates metrics after an upload or a download
func TransferCompleted(bytesSent, bytesReceived int64, transferKind int, err error) {
if transferKind == 0 {
// upload
if err == nil {
totalUploads.Inc()
} else {
totalUploadErrors.Inc()
}
totalUploadSize.Add(float64(bytesReceived))
} else {
// download
if err == nil {
totalDownloads.Inc()
} else {
totalDownloadErrors.Inc()
}
totalDownloadSize.Add(float64(bytesSent))
}
}
// S3TransferCompleted updates metrics after an S3 upload or a download
func S3TransferCompleted(bytes int64, transferKind int, err error) {
if transferKind == 0 {
// upload
if err == nil {
totalS3Uploads.Inc()
} else {
totalS3UploadErrors.Inc()
}
totalS3UploadSize.Add(float64(bytes))
} else {
// download
if err == nil {
totalS3Downloads.Inc()
} else {
totalS3DownloadErrors.Inc()
}
totalS3DownloadSize.Add(float64(bytes))
}
}
// S3ListObjectsCompleted updates metrics after an S3 list objects request terminates
func S3ListObjectsCompleted(err error) {
if err == nil {
totalS3ListObjects.Inc()
} else {
totalS3ListObjectsErrors.Inc()
}
}
// S3CopyObjectCompleted updates metrics after an S3 copy object request terminates
func S3CopyObjectCompleted(err error) {
if err == nil {
totalS3CopyObject.Inc()
} else {
totalS3CopyObjectErrors.Inc()
}
}
// S3DeleteObjectCompleted updates metrics after an S3 delete object request terminates
func S3DeleteObjectCompleted(err error) {
if err == nil {
totalS3DeleteObject.Inc()
} else {
totalS3DeleteObjectErrors.Inc()
}
}
// S3HeadBucketCompleted updates metrics after an S3 head bucket request terminates
func S3HeadBucketCompleted(err error) {
if err == nil {
totalS3HeadBucket.Inc()
} else {
totalS3HeadBucketErrors.Inc()
}
}
// GCSTransferCompleted updates metrics after a GCS upload or a download
func GCSTransferCompleted(bytes int64, transferKind int, err error) {
if transferKind == 0 {
// upload
if err == nil {
totalGCSUploads.Inc()
} else {
totalGCSUploadErrors.Inc()
}
totalGCSUploadSize.Add(float64(bytes))
} else {
// download
if err == nil {
totalGCSDownloads.Inc()
} else {
totalGCSDownloadErrors.Inc()
}
totalGCSDownloadSize.Add(float64(bytes))
}
}
// GCSListObjectsCompleted updates metrics after a GCS list objects request terminates
func GCSListObjectsCompleted(err error) {
if err == nil {
totalGCSListObjects.Inc()
} else {
totalGCSListObjectsErrors.Inc()
}
}
// GCSCopyObjectCompleted updates metrics after a GCS copy object request terminates
func GCSCopyObjectCompleted(err error) {
if err == nil {
totalGCSCopyObject.Inc()
} else {
totalGCSCopyObjectErrors.Inc()
}
}
// GCSDeleteObjectCompleted updates metrics after a GCS delete object request terminates
func GCSDeleteObjectCompleted(err error) {
if err == nil {
totalGCSDeleteObject.Inc()
} else {
totalGCSDeleteObjectErrors.Inc()
}
}
// GCSHeadBucketCompleted updates metrics after a GCS head bucket request terminates
func GCSHeadBucketCompleted(err error) {
if err == nil {
totalGCSHeadBucket.Inc()
} else {
totalGCSHeadBucketErrors.Inc()
}
}
// SSHCommandCompleted update metrics after an SSH command terminates
func SSHCommandCompleted(err error) {
if err == nil {
totalSSHCommands.Inc()
} else {
totalSSHCommandErrors.Inc()
}
}
// UpdateDataProviderAvailability updates the metric for the data provider availability
func UpdateDataProviderAvailability(err error) {
if err == nil {
dataproviderAvailability.Set(1)
} else {
dataproviderAvailability.Set(0)
}
}
// AddLoginAttempt increments the metrics for login attempts
func AddLoginAttempt(authMethod string) {
totalLoginAttempts.Inc()
switch authMethod {
case loginMethodPublicKey:
totalKeyLoginAttempts.Inc()
case loginMethodKeyboardInteractive:
totalInteractiveLoginAttempts.Inc()
case loginMethodKeyAndPassword:
totalKeyAndPasswordLoginAttempts.Inc()
case loginMethodKeyAndKeyboardInt:
totalKeyAndKeyIntLoginAttempts.Inc()
default:
totalPasswordLoginAttempts.Inc()
}
}
// AddLoginResult increments the metrics for login results
func AddLoginResult(authMethod string, err error) {
if err == nil {
totalLoginOK.Inc()
switch authMethod {
case loginMethodPublicKey:
totalKeyLoginOK.Inc()
case loginMethodKeyboardInteractive:
totalInteractiveLoginOK.Inc()
case loginMethodKeyAndPassword:
totalKeyAndPasswordLoginOK.Inc()
case loginMethodKeyAndKeyboardInt:
totalKeyAndKeyIntLoginOK.Inc()
default:
totalPasswordLoginOK.Inc()
}
} else {
totalLoginFailed.Inc()
switch authMethod {
case loginMethodPublicKey:
totalKeyLoginFailed.Inc()
case loginMethodKeyboardInteractive:
totalInteractiveLoginFailed.Inc()
case loginMethodKeyAndPassword:
totalKeyAndPasswordLoginFailed.Inc()
case loginMethodKeyAndKeyboardInt:
totalKeyAndKeyIntLoginFailed.Inc()
default:
totalPasswordLoginFailed.Inc()
}
}
}
// AddNoAuthTryed increments the metric for clients disconnected
// for inactivity before trying to login
func AddNoAuthTryed() {
totalNoAuthTryed.Inc()
}
// HTTPRequestServed increments the metrics for HTTP requests
func HTTPRequestServed(status int) {
totalHTTPRequests.Inc()
if status >= 200 && status < 300 {
totalHTTPOK.Inc()
} else if status >= 400 && status < 500 {
totalHTTPClientErrors.Inc()
} else if status >= 500 {
totalHTTPServerErrors.Inc()
}
}
// UpdateActiveConnectionsSize sets the metric for active connections
func UpdateActiveConnectionsSize(size int) {
activeConnections.Set(float64(size))
}