diff --git a/api/v01/api.rb b/api/v01/api.rb index 3207960..e1d4333 100644 --- a/api/v01/api.rb +++ b/api/v01/api.rb @@ -22,6 +22,7 @@ require './api/v01/matrix' require './api/v01/isoline' require './api/v01/capability' +require './api/v01/entities/metrics' require 'active_support/core_ext/string/conversions' @@ -57,19 +58,24 @@ def count_time end def count_base_key(operation, period = :daily) - count_date = if period == :daily - count_time.to_s[0..9] - elsif period == :monthly - count_time.to_s[0..6] - elsif period == :yearly - count_time.to_s[0..3] - end [ - [:router, operation, count_date].compact, + count_base_key_no_key(operation, period), [:key, params[:api_key]] ].map{ |a| a.join(':') }.join('_') end + def count_base_key_no_key(operation, period = :daily) + count_date = + if period == :daily + count_time.to_s[0..9] + elsif period == :monthly + count_time.to_s[0..6] + elsif period == :yearly + count_time.to_s[0..3] + end + [:router, operation, count_date].compact + end + def count_key(operation) @count_key ||= count_base_key(operation) + '_' + [ [:ip, (env['action_dispatch.remote_ip'] || request.ip).to_s], @@ -77,6 +83,28 @@ def count_key(operation) ].map{ |a| a.join(':') }.join('_') end + def split_key(key) + json = {} + key.split('_').each do |values| + rs = values.split(':') + + case rs[0] + when "router" + json['service'] = rs[0] + json['endpoint'] = rs[1] + json['date'] = rs[2] + when "key" + json['key'] = rs[1] + when "ip" + json['ip'] = rs[1] + when "asset" + json['asset'] = rs[1] + end + end + + json + end + def count(operation, raise_if_exceed = true, request_size = 1) return unless redis_count @@ -114,6 +142,31 @@ def count_incr(operation, options) end end if options[:transactions] end + + def metric(key) + hkey = split_key(key) + + if redis_count.type(key) == 'hash' + hredis = redis_count.hgetall(key) + + if hredis&.key?('hits') + { + count_asset: hkey['asset'], + count_date: hkey['date'], + count_endpoint: hkey['endpoint'], + count_hits: hredis['hits'], + count_ip: hkey['ip'], + count_key: hkey['key'], + count_service: hkey['service'], + count_transactions: hredis['transactions'], + } + else + ::Api::Root.logger.warn("Metrics: #{key} has no hits") && {} + end + else + ::Api::Root.logger.warn("Metrics: #{key} is not a hash") && {} + end + end end rescue_from :all, backtrace: ENV['APP_ENV'] != 'production' do |e| @@ -155,25 +208,11 @@ def count_incr(operation, options) resource :metrics do desc 'Return Prometheus metrics', {} get do - error!('Unauthorized', 401) unless OptimizerWrapper.access[params[:api_key]][:metrics] == true + error!('Unauthorized', 401) unless RouterWrapper.access[params[:api_key]][:metrics] == true status 200 present( - redis_count.keys("*#{count_base_key_no_key('optimize').join(':')}*").flat_map{ |key| - hkey = split_key(key) - hredis = redis_count.hgetall(key) - - { - count_asset: hkey['asset'], - count_date: hkey['date'], - count_endpoint: hkey['endpoint'], - count_hits: hredis['hits'], - count_ip: hkey['ip'], - count_key: hkey['key'], - count_service: hkey['service'], - count_transactions: hredis['transactions'], - } - }, with: Metrics + redis_count.keys("*#{count_base_key_no_key('*').join(':')}*").flat_map{ |key| metric(key) }, with: Metrics ) end end diff --git a/api/v01/entities/metrics.rb b/api/v01/entities/metrics.rb index c66f76a..200003c 100644 --- a/api/v01/entities/metrics.rb +++ b/api/v01/entities/metrics.rb @@ -1,4 +1,3 @@ -@@ -0,0 +1,36 @@ # Copyright © Mapotempo, 2015 # # This file is part of Mapotempo. diff --git a/test/api/v01/api_test.rb b/test/api/v01/api_test.rb index 5a60bc0..c670aec 100644 --- a/test/api/v01/api_test.rb +++ b/test/api/v01/api_test.rb @@ -37,25 +37,33 @@ def test_should_not_access_if_expired end def test_metrics - clear_optim_redis_count - post '/0.1/vrp/submit?asset=myAsset', { api_key: 'demo', vrp: VRP.toy }.to_json, \ - 'CONTENT_TYPE' => 'application/json' + clear_router_redis_count + post '/0.1/routes', { api_key: 'demo', locs: '43.2805,5.3806,43.2804,5.3806,43.330672,5.375404' } + assert last_response.ok?, last_response.body - get '0.1/metrics', { api_key: 'demo'} + get '0.1/metrics.json', { api_key: 'demo'} assert_equal 401, last_response.status - get '0.1/metrics', { api_key: 'metrics'} + get '0.1/metrics.json', { api_key: 'metrics'} assert last_response.ok?, last_response.body json = JSON.parse(last_response.body).first - assert_equal Date.today.strftime("%Y-%m-%d"), json["count_date"] - assert_equal "1", json["count_hits"] - assert_equal "1", json["count_transactions"] - assert_equal "127.0.0.1", json["count_ip"] - assert_equal "demo", json["count_key"] - assert_equal "myAsset", json["count_asset"] - assert_equal "optimizer", json["count_service"] - assert_equal "optimize", json["count_endpoint"] + assert_equal Date.today.strftime('%Y-%m-%d'), json['count_date'] + assert_equal '1', json['count_hits'] + assert_equal '2', json['count_transactions'] + assert_equal '127.0.0.1', json['count_ip'] + assert_equal 'demo', json['count_key'] + assert_equal 'router', json['count_service'] + assert_equal 'route', json['count_endpoint'] + + post '/0.1/matrix', {api_key: 'demo', src: '43.2804,5.3806,43.2804,5.3806' } + + get '0.1/metrics.json', { api_key: 'metrics'} + assert last_response.ok?, last_response.body + json = JSON.parse(last_response.body) + assert_equal 2, json.count + assert_equal '1', json[1]['count_hits'] + assert_equal '4', json[1]['count_transactions'] end end diff --git a/test/test_helper.rb b/test/test_helper.rb index b1e27ad..f099fdc 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -66,6 +66,12 @@ def random_location(centroid, max_radius) [random_lat.round(5), random_lng.round(5)] # meter precision end +def clear_router_redis_count + RouterWrapper.config[:redis_count].keys.select{ |key| key =~ /router:/ }.each do |to_remove| + RouterWrapper.config[:redis_count].del(to_remove) + end +end + module FakeRedis def teardown RouterWrapper.config[:redis_count].flushall