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 build { BuildJobQueue }
 | 
			
		||||
import cron.expression
 | 
			
		||||
import metrics
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	log_file_name = 'vieter.log'
 | 
			
		||||
| 
						 | 
				
			
			@ -107,6 +108,7 @@ pub fn server(conf Config) ! {
 | 
			
		|||
		repo: repo
 | 
			
		||||
		db: db
 | 
			
		||||
		job_queue: build.new_job_queue(global_ce, conf.base_image)
 | 
			
		||||
		collector: metrics.new_default_collector()
 | 
			
		||||
	}
 | 
			
		||||
	app.init_job_queue() or {
 | 
			
		||||
		util.exit_with_message(1, 'Failed to inialize job queue: $err.msg()')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,7 @@ Module {
 | 
			
		|||
    dependencies: [
 | 
			
		||||
        'https://git.rustybever.be/vieter-v/conf',
 | 
			
		||||
        '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 json
 | 
			
		||||
import log
 | 
			
		||||
import metrics
 | 
			
		||||
 | 
			
		||||
// The Context struct represents the Context which hold the HTTP request and response.
 | 
			
		||||
// It has fields for the query, form, files.
 | 
			
		||||
| 
						 | 
				
			
			@ -27,6 +28,8 @@ pub mut:
 | 
			
		|||
	conn &net.TcpConn = unsafe { nil }
 | 
			
		||||
	// Gives access to a shared logger object
 | 
			
		||||
	logger shared log.Log
 | 
			
		||||
	// Used to collect metrics on the web server
 | 
			
		||||
	collector &metrics.MetricsCollector
 | 
			
		||||
	// time.ticks() from start of web connection handle.
 | 
			
		||||
	// You can use it to determine how much time is spent on your request.
 | 
			
		||||
	page_gen_start i64
 | 
			
		||||
| 
						 | 
				
			
			@ -145,6 +148,14 @@ pub fn (ctx &Context) is_authenticated() bool {
 | 
			
		|||
	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`
 | 
			
		||||
pub fn (mut ctx Context) json<T>(status http.Status, j T) Result {
 | 
			
		||||
	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()
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// 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 {
 | 
			
		||||
			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
 | 
			
		||||
		reader: reader
 | 
			
		||||
		logger: app.logger
 | 
			
		||||
		collector: app.collector
 | 
			
		||||
		api_key: app.api_key
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue