forked from vieter-v/vieter
				
			feat(server): add metric collection
							parent
							
								
									8a0214babe
								
							
						
					
					
						commit
						c0f58ddc77
					
				| 
						 | 
					@ -0,0 +1,16 @@
 | 
				
			||||||
 | 
					module server
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import metrics
 | 
				
			||||||
 | 
					import web
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					['/api/v1/metrics'; get]
 | 
				
			||||||
 | 
					fn (mut app App) v1_metrics() web.Result {
 | 
				
			||||||
 | 
						mut exporter := metrics.new_prometheus_exporter([0.01, 0.05, 0.1, 0.5, 1, 100])
 | 
				
			||||||
 | 
						exporter.load(app.collector)
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						// TODO stream to connection instead
 | 
				
			||||||
 | 
						body := exporter.export_to_string() or {
 | 
				
			||||||
 | 
							return app.status(.internal_server_error)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return app.body(.ok, 'text/plain', body)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -8,6 +8,7 @@ import util
 | 
				
			||||||
import db
 | 
					import db
 | 
				
			||||||
import build { BuildJobQueue }
 | 
					import build { BuildJobQueue }
 | 
				
			||||||
import cron.expression
 | 
					import cron.expression
 | 
				
			||||||
 | 
					import metrics
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	log_file_name = 'vieter.log'
 | 
						log_file_name = 'vieter.log'
 | 
				
			||||||
| 
						 | 
					@ -107,6 +108,7 @@ pub fn server(conf Config) ! {
 | 
				
			||||||
		repo: repo
 | 
							repo: repo
 | 
				
			||||||
		db: db
 | 
							db: db
 | 
				
			||||||
		job_queue: build.new_job_queue(global_ce, conf.base_image)
 | 
							job_queue: build.new_job_queue(global_ce, conf.base_image)
 | 
				
			||||||
 | 
							collector: metrics.new_default_collector()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	app.init_job_queue() or {
 | 
						app.init_job_queue() or {
 | 
				
			||||||
		util.exit_with_message(1, 'Failed to inialize job queue: $err.msg()')
 | 
							util.exit_with_message(1, 'Failed to inialize job queue: $err.msg()')
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,7 @@ Module {
 | 
				
			||||||
    dependencies: [
 | 
					    dependencies: [
 | 
				
			||||||
        'https://git.rustybever.be/vieter-v/conf',
 | 
					        'https://git.rustybever.be/vieter-v/conf',
 | 
				
			||||||
        'https://git.rustybever.be/vieter-v/docker',
 | 
					        'https://git.rustybever.be/vieter-v/docker',
 | 
				
			||||||
        'https://git.rustybever.be/vieter-v/aur'
 | 
					        'https://git.rustybever.be/vieter-v/aur',
 | 
				
			||||||
 | 
					        'https://git.rustybever.be/vieter-v/metrics'
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,6 +11,7 @@ import net.urllib
 | 
				
			||||||
import time
 | 
					import time
 | 
				
			||||||
import json
 | 
					import json
 | 
				
			||||||
import log
 | 
					import log
 | 
				
			||||||
 | 
					import metrics
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// The Context struct represents the Context which hold the HTTP request and response.
 | 
					// The Context struct represents the Context which hold the HTTP request and response.
 | 
				
			||||||
// It has fields for the query, form, files.
 | 
					// It has fields for the query, form, files.
 | 
				
			||||||
| 
						 | 
					@ -27,6 +28,8 @@ pub mut:
 | 
				
			||||||
	conn &net.TcpConn = unsafe { nil }
 | 
						conn &net.TcpConn = unsafe { nil }
 | 
				
			||||||
	// Gives access to a shared logger object
 | 
						// Gives access to a shared logger object
 | 
				
			||||||
	logger shared log.Log
 | 
						logger shared log.Log
 | 
				
			||||||
 | 
						// Used to collect metrics on the web server
 | 
				
			||||||
 | 
						collector &metrics.MetricsCollector
 | 
				
			||||||
	// time.ticks() from start of web connection handle.
 | 
						// time.ticks() from start of web connection handle.
 | 
				
			||||||
	// You can use it to determine how much time is spent on your request.
 | 
						// You can use it to determine how much time is spent on your request.
 | 
				
			||||||
	page_gen_start i64
 | 
						page_gen_start i64
 | 
				
			||||||
| 
						 | 
					@ -145,6 +148,14 @@ pub fn (ctx &Context) is_authenticated() bool {
 | 
				
			||||||
	return false
 | 
						return false
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn (mut ctx Context) body(status http.Status, content_type string, body string) Result {
 | 
				
			||||||
 | 
						ctx.status = status
 | 
				
			||||||
 | 
						ctx.content_type = content_type
 | 
				
			||||||
 | 
						ctx.send_response(body)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return Result{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// json<T> HTTP_OK with json_s as payload with content-type `application/json`
 | 
					// json<T> HTTP_OK with json_s as payload with content-type `application/json`
 | 
				
			||||||
pub fn (mut ctx Context) json<T>(status http.Status, j T) Result {
 | 
					pub fn (mut ctx Context) json<T>(status http.Status, j T) Result {
 | 
				
			||||||
	ctx.status = status
 | 
						ctx.status = status
 | 
				
			||||||
| 
						 | 
					@ -319,6 +330,16 @@ fn handle_conn<T>(mut conn net.TcpConn, mut app T, routes map[string]Route) {
 | 
				
			||||||
			app.logger.flush()
 | 
								app.logger.flush()
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Record how long request took to process
 | 
				
			||||||
 | 
							labels := [
 | 
				
			||||||
 | 
								['method', app.req.method.str()]!,
 | 
				
			||||||
 | 
								['path', app.req.url]!,
 | 
				
			||||||
 | 
								['status', app.status.int().str()]!
 | 
				
			||||||
 | 
							]
 | 
				
			||||||
 | 
							app.collector.counter_increment(name: 'http_requests_total', labels: labels)
 | 
				
			||||||
 | 
							app.collector.histogram_record(time.ticks() - app.page_gen_start, name: 'http_requests_time_ms', labels: labels)
 | 
				
			||||||
 | 
							/* app.collector.histogram_ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		unsafe {
 | 
							unsafe {
 | 
				
			||||||
			free(app)
 | 
								free(app)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -384,6 +405,7 @@ fn handle_conn<T>(mut conn net.TcpConn, mut app T, routes map[string]Route) {
 | 
				
			||||||
		static_mime_types: app.static_mime_types
 | 
							static_mime_types: app.static_mime_types
 | 
				
			||||||
		reader: reader
 | 
							reader: reader
 | 
				
			||||||
		logger: app.logger
 | 
							logger: app.logger
 | 
				
			||||||
 | 
							collector: app.collector
 | 
				
			||||||
		api_key: app.api_key
 | 
							api_key: app.api_key
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue