metrics.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  1. // Package metrics provides Prometheus metrics support
  2. package metrics
  3. import (
  4. "github.com/prometheus/client_golang/prometheus"
  5. "github.com/prometheus/client_golang/prometheus/promauto"
  6. )
  7. var (
  8. // dataproviderAvailability is the metric that reports the availability for the configured data provider
  9. dataproviderAvailability = promauto.NewGauge(prometheus.GaugeOpts{
  10. Name: "sftpgo_dataprovider_availability",
  11. Help: "Availability for the configured data provider, 1 means OK, 0 KO",
  12. })
  13. // activeConnections is the metric that reports the total number of active connections
  14. activeConnections = promauto.NewGauge(prometheus.GaugeOpts{
  15. Name: "sftpgo_active_connections",
  16. Help: "Total number of logged in users",
  17. })
  18. // totalUploads is the metric that reports the total number of successful SFTP/SCP uploads
  19. totalUploads = promauto.NewCounter(prometheus.CounterOpts{
  20. Name: "sftpgo_uploads_total",
  21. Help: "The total number of successful SFTP/SCP uploads",
  22. })
  23. // totalDownloads is the metric that reports the total number of successful SFTP/SCP downloads
  24. totalDownloads = promauto.NewCounter(prometheus.CounterOpts{
  25. Name: "sftpgo_downloads_total",
  26. Help: "The total number of successful SFTP/SCP downloads",
  27. })
  28. // totalUploadErrors is the metric that reports the total number of SFTP/SCP upload errors
  29. totalUploadErrors = promauto.NewCounter(prometheus.CounterOpts{
  30. Name: "sftpgo_upload_errors_total",
  31. Help: "The total number of SFTP/SCP upload errors",
  32. })
  33. // totalDownloadErrors is the metric that reports the total number of SFTP/SCP download errors
  34. totalDownloadErrors = promauto.NewCounter(prometheus.CounterOpts{
  35. Name: "sftpgo_download_errors_total",
  36. Help: "The total number of SFTP/SCP download errors",
  37. })
  38. // totalUploadSize is the metric that reports the total SFTP/SCP uploads size as bytes
  39. totalUploadSize = promauto.NewCounter(prometheus.CounterOpts{
  40. Name: "sftpgo_upload_size",
  41. Help: "The total SFTP/SCP upload size as bytes, partial uploads are included",
  42. })
  43. // totalDownloadSize is the metric that reports the total SFTP/SCP downloads size as bytes
  44. totalDownloadSize = promauto.NewCounter(prometheus.CounterOpts{
  45. Name: "sftpgo_download_size",
  46. Help: "The total SFTP/SCP download size as bytes, partial downloads are included",
  47. })
  48. // totalSSHCommands is the metric that reports the total number of executed SSH commands
  49. totalSSHCommands = promauto.NewCounter(prometheus.CounterOpts{
  50. Name: "sftpgo_ssh_commands_total",
  51. Help: "The total number of executed SSH commands",
  52. })
  53. // totalSSHCommandErrors is the metric that reports the total number of SSH command errors
  54. totalSSHCommandErrors = promauto.NewCounter(prometheus.CounterOpts{
  55. Name: "sftpgo_ssh_command_errors_total",
  56. Help: "The total number of SSH command errors",
  57. })
  58. // totalLoginAttempts is the metric that reports the total number of login attempts
  59. totalLoginAttempts = promauto.NewCounter(prometheus.CounterOpts{
  60. Name: "sftpgo_login_attempts_total",
  61. Help: "The total number of login attempts",
  62. })
  63. // totalLoginOK is the metric that reports the total number of successful logins
  64. totalLoginOK = promauto.NewCounter(prometheus.CounterOpts{
  65. Name: "sftpgo_login_ok_total",
  66. Help: "The total number of successful logins",
  67. })
  68. // totalLoginFailed is the metric that reports the total number of failed logins
  69. totalLoginFailed = promauto.NewCounter(prometheus.CounterOpts{
  70. Name: "sftpgo_login_ko_total",
  71. Help: "The total number of failed logins",
  72. })
  73. // totalPasswordLoginAttempts is the metric that reports the total number of login attempts
  74. // using a password
  75. totalPasswordLoginAttempts = promauto.NewCounter(prometheus.CounterOpts{
  76. Name: "sftpgo_password_login_attempts_total",
  77. Help: "The total number of login attempts using a password",
  78. })
  79. // totalPasswordLoginOK is the metric that reports the total number of successful logins
  80. // using a password
  81. totalPasswordLoginOK = promauto.NewCounter(prometheus.CounterOpts{
  82. Name: "sftpgo_password_login_ok_total",
  83. Help: "The total number of successful logins using a password",
  84. })
  85. // totalPasswordLoginFailed is the metric that reports the total number of failed logins
  86. // using a password
  87. totalPasswordLoginFailed = promauto.NewCounter(prometheus.CounterOpts{
  88. Name: "sftpgo_password_login_ko_total",
  89. Help: "The total number of failed logins using a password",
  90. })
  91. // totalKeyLoginAttempts is the metric that reports the total number of login attempts
  92. // using a public key
  93. totalKeyLoginAttempts = promauto.NewCounter(prometheus.CounterOpts{
  94. Name: "sftpgo_public_key_login_attempts_total",
  95. Help: "The total number of login attempts using a public key",
  96. })
  97. // totalKeyLoginOK is the metric that reports the total number of successful logins
  98. // using a public key
  99. totalKeyLoginOK = promauto.NewCounter(prometheus.CounterOpts{
  100. Name: "sftpgo_public_key_login_ok_total",
  101. Help: "The total number of successful logins using a public key",
  102. })
  103. // totalKeyLoginFailed is the metric that reports the total number of failed logins
  104. // using a public key
  105. totalKeyLoginFailed = promauto.NewCounter(prometheus.CounterOpts{
  106. Name: "sftpgo_public_key_login_ko_total",
  107. Help: "The total number of failed logins using a public key",
  108. })
  109. // totalInteractiveLoginAttempts is the metric that reports the total number of login attempts
  110. // using keyboard interactive authentication
  111. totalInteractiveLoginAttempts = promauto.NewCounter(prometheus.CounterOpts{
  112. Name: "sftpgo_keyboard_interactive_login_attempts_total",
  113. Help: "The total number of login attempts using keyboard interactive authentication",
  114. })
  115. // totalInteractiveLoginOK is the metric that reports the total number of successful logins
  116. // using keyboard interactive authentication
  117. totalInteractiveLoginOK = promauto.NewCounter(prometheus.CounterOpts{
  118. Name: "sftpgo_keyboard_interactive_login_ok_total",
  119. Help: "The total number of successful logins using keyboard interactive authentication",
  120. })
  121. // totalInteractiveLoginFailed is the metric that reports the total number of failed logins
  122. // using keyboard interactive authentication
  123. totalInteractiveLoginFailed = promauto.NewCounter(prometheus.CounterOpts{
  124. Name: "sftpgo_keyboard_interactive_login_ko_total",
  125. Help: "The total number of failed logins using keyboard interactive authentication",
  126. })
  127. totalHTTPRequests = promauto.NewCounter(prometheus.CounterOpts{
  128. Name: "sftpgo_http_req_total",
  129. Help: "The total number of HTTP requests served",
  130. })
  131. totalHTTPOK = promauto.NewCounter(prometheus.CounterOpts{
  132. Name: "sftpgo_http_req_ok_total",
  133. Help: "The total number of HTTP requests served with 2xx status code",
  134. })
  135. totalHTTPClientErrors = promauto.NewCounter(prometheus.CounterOpts{
  136. Name: "sftpgo_http_client_errors_total",
  137. Help: "The total number of HTTP requests served with 4xx status code",
  138. })
  139. totalHTTPServerErrors = promauto.NewCounter(prometheus.CounterOpts{
  140. Name: "sftpgo_http_server_errors_total",
  141. Help: "The total number of HTTP requests served with 5xx status code",
  142. })
  143. // totalS3Uploads is the metric that reports the total number of successful S3 uploads
  144. totalS3Uploads = promauto.NewCounter(prometheus.CounterOpts{
  145. Name: "sftpgo_s3_uploads_total",
  146. Help: "The total number of successful S3 uploads",
  147. })
  148. // totalS3Downloads is the metric that reports the total number of successful S3 downloads
  149. totalS3Downloads = promauto.NewCounter(prometheus.CounterOpts{
  150. Name: "sftpgo_s3_downloads_total",
  151. Help: "The total number of successful S3 downloads",
  152. })
  153. // totalS3UploadErrors is the metric that reports the total number of S3 upload errors
  154. totalS3UploadErrors = promauto.NewCounter(prometheus.CounterOpts{
  155. Name: "sftpgo_s3_upload_errors_total",
  156. Help: "The total number of S3 upload errors",
  157. })
  158. // totalS3DownloadErrors is the metric that reports the total number of S3 download errors
  159. totalS3DownloadErrors = promauto.NewCounter(prometheus.CounterOpts{
  160. Name: "sftpgo_s3_download_errors_total",
  161. Help: "The total number of S3 download errors",
  162. })
  163. // totalS3UploadSize is the metric that reports the total S3 uploads size as bytes
  164. totalS3UploadSize = promauto.NewCounter(prometheus.CounterOpts{
  165. Name: "sftpgo_s3_upload_size",
  166. Help: "The total S3 upload size as bytes, partial uploads are included",
  167. })
  168. // totalS3DownloadSize is the metric that reports the total S3 downloads size as bytes
  169. totalS3DownloadSize = promauto.NewCounter(prometheus.CounterOpts{
  170. Name: "sftpgo_s3_download_size",
  171. Help: "The total S3 download size as bytes, partial downloads are included",
  172. })
  173. // totalS3ListObjects is the metric that reports the total successful S3 list objects requests
  174. totalS3ListObjects = promauto.NewCounter(prometheus.CounterOpts{
  175. Name: "sftpgo_s3_list_objects",
  176. Help: "The total number of successful S3 list objects requests",
  177. })
  178. // totalS3CopyObject is the metric that reports the total successful S3 copy object requests
  179. totalS3CopyObject = promauto.NewCounter(prometheus.CounterOpts{
  180. Name: "sftpgo_s3_copy_object",
  181. Help: "The total number of successful S3 copy object requests",
  182. })
  183. // totalS3DeleteObject is the metric that reports the total successful S3 delete object requests
  184. totalS3DeleteObject = promauto.NewCounter(prometheus.CounterOpts{
  185. Name: "sftpgo_s3_delete_object",
  186. Help: "The total number of successful S3 delete object requests",
  187. })
  188. // totalS3ListObjectsError is the metric that reports the total S3 list objects errors
  189. totalS3ListObjectsErrors = promauto.NewCounter(prometheus.CounterOpts{
  190. Name: "sftpgo_s3_list_objects_errors",
  191. Help: "The total number of S3 list objects errors",
  192. })
  193. // totalS3CopyObjectErrors is the metric that reports the total S3 copy object errors
  194. totalS3CopyObjectErrors = promauto.NewCounter(prometheus.CounterOpts{
  195. Name: "sftpgo_s3_copy_object_errors",
  196. Help: "The total number of S3 copy object errors",
  197. })
  198. // totalS3DeleteObjectErrors is the metric that reports the total S3 delete object errors
  199. totalS3DeleteObjectErrors = promauto.NewCounter(prometheus.CounterOpts{
  200. Name: "sftpgo_s3_delete_object_errors",
  201. Help: "The total number of S3 delete object errors",
  202. })
  203. // totalS3HeadBucket is the metric that reports the total successful S3 head bucket requests
  204. totalS3HeadBucket = promauto.NewCounter(prometheus.CounterOpts{
  205. Name: "sftpgo_s3_head_bucket",
  206. Help: "The total number of successful S3 head bucket requests",
  207. })
  208. // totalS3HeadBucketErrors is the metric that reports the total S3 head bucket errors
  209. totalS3HeadBucketErrors = promauto.NewCounter(prometheus.CounterOpts{
  210. Name: "sftpgo_s3_head_bucket_errors",
  211. Help: "The total number of S3 head bucket errors",
  212. })
  213. // totalGCSUploads is the metric that reports the total number of successful GCS uploads
  214. totalGCSUploads = promauto.NewCounter(prometheus.CounterOpts{
  215. Name: "sftpgo_gcs_uploads_total",
  216. Help: "The total number of successful GCS uploads",
  217. })
  218. // totalGCSDownloads is the metric that reports the total number of successful GCS downloads
  219. totalGCSDownloads = promauto.NewCounter(prometheus.CounterOpts{
  220. Name: "sftpgo_gcs_downloads_total",
  221. Help: "The total number of successful GCS downloads",
  222. })
  223. // totalGCSUploadErrors is the metric that reports the total number of GCS upload errors
  224. totalGCSUploadErrors = promauto.NewCounter(prometheus.CounterOpts{
  225. Name: "sftpgo_gcs_upload_errors_total",
  226. Help: "The total number of GCS upload errors",
  227. })
  228. // totalGCSDownloadErrors is the metric that reports the total number of GCS download errors
  229. totalGCSDownloadErrors = promauto.NewCounter(prometheus.CounterOpts{
  230. Name: "sftpgo_gcs_download_errors_total",
  231. Help: "The total number of GCS download errors",
  232. })
  233. // totalGCSUploadSize is the metric that reports the total GCS uploads size as bytes
  234. totalGCSUploadSize = promauto.NewCounter(prometheus.CounterOpts{
  235. Name: "sftpgo_gcs_upload_size",
  236. Help: "The total GCS upload size as bytes, partial uploads are included",
  237. })
  238. // totalGCSDownloadSize is the metric that reports the total GCS downloads size as bytes
  239. totalGCSDownloadSize = promauto.NewCounter(prometheus.CounterOpts{
  240. Name: "sftpgo_gcs_download_size",
  241. Help: "The total GCS download size as bytes, partial downloads are included",
  242. })
  243. // totalS3ListObjects is the metric that reports the total successful GCS list objects requests
  244. totalGCSListObjects = promauto.NewCounter(prometheus.CounterOpts{
  245. Name: "sftpgo_gcs_list_objects",
  246. Help: "The total number of successful GCS list objects requests",
  247. })
  248. // totalGCSCopyObject is the metric that reports the total successful GCS copy object requests
  249. totalGCSCopyObject = promauto.NewCounter(prometheus.CounterOpts{
  250. Name: "sftpgo_gcs_copy_object",
  251. Help: "The total number of successful GCS copy object requests",
  252. })
  253. // totalGCSDeleteObject is the metric that reports the total successful S3 delete object requests
  254. totalGCSDeleteObject = promauto.NewCounter(prometheus.CounterOpts{
  255. Name: "sftpgo_gcs_delete_object",
  256. Help: "The total number of successful GCS delete object requests",
  257. })
  258. // totalGCSListObjectsError is the metric that reports the total GCS list objects errors
  259. totalGCSListObjectsErrors = promauto.NewCounter(prometheus.CounterOpts{
  260. Name: "sftpgo_gcs_list_objects_errors",
  261. Help: "The total number of GCS list objects errors",
  262. })
  263. // totalGCSCopyObjectErrors is the metric that reports the total GCS copy object errors
  264. totalGCSCopyObjectErrors = promauto.NewCounter(prometheus.CounterOpts{
  265. Name: "sftpgo_gcs_copy_object_errors",
  266. Help: "The total number of GCS copy object errors",
  267. })
  268. // totalGCSDeleteObjectErrors is the metric that reports the total GCS delete object errors
  269. totalGCSDeleteObjectErrors = promauto.NewCounter(prometheus.CounterOpts{
  270. Name: "sftpgo_gcs_delete_object_errors",
  271. Help: "The total number of GCS delete object errors",
  272. })
  273. // totalGCSHeadBucket is the metric that reports the total successful GCS head bucket requests
  274. totalGCSHeadBucket = promauto.NewCounter(prometheus.CounterOpts{
  275. Name: "sftpgo_gcs_head_bucket",
  276. Help: "The total number of successful GCS head bucket requests",
  277. })
  278. // totalGCSHeadBucketErrors is the metric that reports the total GCS head bucket errors
  279. totalGCSHeadBucketErrors = promauto.NewCounter(prometheus.CounterOpts{
  280. Name: "sftpgo_gcs_head_bucket_errors",
  281. Help: "The total number of GCS head bucket errors",
  282. })
  283. )
  284. // TransferCompleted updates metrics after an upload or a download
  285. func TransferCompleted(bytesSent, bytesReceived int64, transferKind int, err error) {
  286. if transferKind == 0 {
  287. // upload
  288. if err == nil {
  289. totalUploads.Inc()
  290. } else {
  291. totalUploadErrors.Inc()
  292. }
  293. totalUploadSize.Add(float64(bytesReceived))
  294. } else {
  295. // download
  296. if err == nil {
  297. totalDownloads.Inc()
  298. } else {
  299. totalDownloadErrors.Inc()
  300. }
  301. totalDownloadSize.Add(float64(bytesSent))
  302. }
  303. }
  304. // S3TransferCompleted updates metrics after an S3 upload or a download
  305. func S3TransferCompleted(bytes int64, transferKind int, err error) {
  306. if transferKind == 0 {
  307. // upload
  308. if err == nil {
  309. totalS3Uploads.Inc()
  310. } else {
  311. totalS3UploadErrors.Inc()
  312. }
  313. totalS3UploadSize.Add(float64(bytes))
  314. } else {
  315. // download
  316. if err == nil {
  317. totalS3Downloads.Inc()
  318. } else {
  319. totalS3DownloadErrors.Inc()
  320. }
  321. totalS3DownloadSize.Add(float64(bytes))
  322. }
  323. }
  324. // S3ListObjectsCompleted updates metrics after an S3 list objects request terminates
  325. func S3ListObjectsCompleted(err error) {
  326. if err == nil {
  327. totalS3ListObjects.Inc()
  328. } else {
  329. totalS3ListObjectsErrors.Inc()
  330. }
  331. }
  332. // S3CopyObjectCompleted updates metrics after an S3 copy object request terminates
  333. func S3CopyObjectCompleted(err error) {
  334. if err == nil {
  335. totalS3CopyObject.Inc()
  336. } else {
  337. totalS3CopyObjectErrors.Inc()
  338. }
  339. }
  340. // S3DeleteObjectCompleted updates metrics after an S3 delete object request terminates
  341. func S3DeleteObjectCompleted(err error) {
  342. if err == nil {
  343. totalS3DeleteObject.Inc()
  344. } else {
  345. totalS3DeleteObjectErrors.Inc()
  346. }
  347. }
  348. // S3HeadBucketCompleted updates metrics after an S3 head bucket request terminates
  349. func S3HeadBucketCompleted(err error) {
  350. if err == nil {
  351. totalS3HeadBucket.Inc()
  352. } else {
  353. totalS3HeadBucketErrors.Inc()
  354. }
  355. }
  356. // GCSTransferCompleted updates metrics after a GCS upload or a download
  357. func GCSTransferCompleted(bytes int64, transferKind int, err error) {
  358. if transferKind == 0 {
  359. // upload
  360. if err == nil {
  361. totalGCSUploads.Inc()
  362. } else {
  363. totalGCSUploadErrors.Inc()
  364. }
  365. totalGCSUploadSize.Add(float64(bytes))
  366. } else {
  367. // download
  368. if err == nil {
  369. totalGCSDownloads.Inc()
  370. } else {
  371. totalGCSDownloadErrors.Inc()
  372. }
  373. totalGCSDownloadSize.Add(float64(bytes))
  374. }
  375. }
  376. // GCSListObjectsCompleted updates metrics after a GCS list objects request terminates
  377. func GCSListObjectsCompleted(err error) {
  378. if err == nil {
  379. totalGCSListObjects.Inc()
  380. } else {
  381. totalGCSListObjectsErrors.Inc()
  382. }
  383. }
  384. // GCSCopyObjectCompleted updates metrics after a GCS copy object request terminates
  385. func GCSCopyObjectCompleted(err error) {
  386. if err == nil {
  387. totalGCSCopyObject.Inc()
  388. } else {
  389. totalGCSCopyObjectErrors.Inc()
  390. }
  391. }
  392. // GCSDeleteObjectCompleted updates metrics after a GCS delete object request terminates
  393. func GCSDeleteObjectCompleted(err error) {
  394. if err == nil {
  395. totalGCSDeleteObject.Inc()
  396. } else {
  397. totalGCSDeleteObjectErrors.Inc()
  398. }
  399. }
  400. // GCSHeadBucketCompleted updates metrics after a GCS head bucket request terminates
  401. func GCSHeadBucketCompleted(err error) {
  402. if err == nil {
  403. totalGCSHeadBucket.Inc()
  404. } else {
  405. totalGCSHeadBucketErrors.Inc()
  406. }
  407. }
  408. // SSHCommandCompleted update metrics after an SSH command terminates
  409. func SSHCommandCompleted(err error) {
  410. if err == nil {
  411. totalSSHCommands.Inc()
  412. } else {
  413. totalSSHCommandErrors.Inc()
  414. }
  415. }
  416. // UpdateDataProviderAvailability updates the metric for the data provider availability
  417. func UpdateDataProviderAvailability(err error) {
  418. if err == nil {
  419. dataproviderAvailability.Set(1)
  420. } else {
  421. dataproviderAvailability.Set(0)
  422. }
  423. }
  424. // AddLoginAttempt increments the metrics for login attempts
  425. func AddLoginAttempt(authMethod string) {
  426. totalLoginAttempts.Inc()
  427. switch authMethod {
  428. case "public_key":
  429. totalKeyLoginAttempts.Inc()
  430. case "keyboard-interactive":
  431. totalInteractiveLoginAttempts.Inc()
  432. default:
  433. totalPasswordLoginAttempts.Inc()
  434. }
  435. }
  436. // AddLoginResult increments the metrics for login results
  437. func AddLoginResult(authMethod string, err error) {
  438. if err == nil {
  439. totalLoginOK.Inc()
  440. switch authMethod {
  441. case "public_key":
  442. totalKeyLoginOK.Inc()
  443. case "keyboard-interactive":
  444. totalInteractiveLoginOK.Inc()
  445. default:
  446. totalPasswordLoginOK.Inc()
  447. }
  448. } else {
  449. totalLoginFailed.Inc()
  450. switch authMethod {
  451. case "public_key":
  452. totalKeyLoginFailed.Inc()
  453. case "keyboard-interactive":
  454. totalInteractiveLoginFailed.Inc()
  455. default:
  456. totalPasswordLoginFailed.Inc()
  457. }
  458. }
  459. }
  460. // HTTPRequestServed increments the metrics for HTTP requests
  461. func HTTPRequestServed(status int) {
  462. totalHTTPRequests.Inc()
  463. if status >= 200 && status < 300 {
  464. totalHTTPOK.Inc()
  465. } else if status >= 400 && status < 500 {
  466. totalHTTPClientErrors.Inc()
  467. } else if status >= 500 {
  468. totalHTTPServerErrors.Inc()
  469. }
  470. }
  471. // UpdateActiveConnectionsSize sets the metric for active connections
  472. func UpdateActiveConnectionsSize(size int) {
  473. activeConnections.Set(float64(size))
  474. }