98 lines
3.3 KiB
Ruby
98 lines
3.3 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'spec_helper'
|
|
require 'securerandom'
|
|
require_relative '../../../e2e/lib/action_cable_client'
|
|
require_relative '../../../e2e/lib/api_client'
|
|
|
|
RSpec.describe 'Metrics HTTP E2E' do
|
|
primary_env_vars = %w[TURNIERE_E2E_EMAIL TURNIERE_E2E_PASSWORD].freeze
|
|
|
|
before do
|
|
missing_vars = primary_env_vars.reject { |name| ENV.key?(name) }
|
|
skip("HTTP E2E requires #{missing_vars.join(', ')}") unless missing_vars.empty?
|
|
end
|
|
|
|
let(:base_url) { ENV.fetch('TURNIERE_E2E_BASE_URL', 'http://127.0.0.1:3000') }
|
|
let(:owner_email) { ENV.fetch('TURNIERE_E2E_EMAIL') }
|
|
let(:owner_password) { ENV.fetch('TURNIERE_E2E_PASSWORD') }
|
|
let(:anonymous_client) { TurniereE2E::ApiClient.new(base_url:) }
|
|
|
|
it 'exposes HTTP request metrics and live websocket connection metrics' do
|
|
health_response = anonymous_client.get('/healthz')
|
|
metrics_response = anonymous_client.get('/metrics')
|
|
|
|
expect(health_response[:status]).to eq(200)
|
|
expect(metrics_response[:status]).to eq(200)
|
|
expect(metrics_response.dig(:headers, 'content-type')).to include('text/plain')
|
|
|
|
metrics_body = raw_body(metrics_response)
|
|
expect(metrics_body).to include('# TYPE turniere_http_requests_total counter')
|
|
expect(metrics_body).to match(
|
|
/turniere_http_requests_total\{
|
|
(?=[^}]*method="GET")
|
|
(?=[^}]*controller="health")
|
|
(?=[^}]*action="index")
|
|
(?=[^}]*status="200")
|
|
[^}]*
|
|
\}\ [1-9]\d*/x
|
|
)
|
|
expect(metrics_body).to include('# TYPE turniere_http_request_duration_seconds histogram')
|
|
|
|
tournament = create_playoff_tournament
|
|
cable_client = TurniereE2E::ActionCableClient.new(base_url:)
|
|
cable_client.subscribe_timer!(tournament_id: tournament.fetch(:id))
|
|
|
|
expect(metric_value('turniere_action_cable_connections')).to be >= 1
|
|
expect(metric_value('turniere_action_cable_connections_total')).to be >= 1
|
|
ensure
|
|
cable_client&.close
|
|
end
|
|
|
|
def create_playoff_tournament
|
|
owner_client = login_client
|
|
unique = SecureRandom.hex(3)
|
|
response = owner_client.post('/tournaments', body: {
|
|
name: "Metrics #{unique}",
|
|
public: false,
|
|
teams: Array.new(4) { |index| { name: "Metrics-#{unique}-#{index + 1}" } }
|
|
})
|
|
|
|
expect(response[:status]).to eq(201)
|
|
response.fetch(:json)
|
|
end
|
|
|
|
def login_client
|
|
client = TurniereE2E::ApiClient.new(base_url:)
|
|
response = client.login!(email: owner_email, password: owner_password)
|
|
|
|
expect(response[:status]).to eq(200)
|
|
client
|
|
end
|
|
|
|
def metric_value(metric_name)
|
|
deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + 10
|
|
loop do
|
|
value = latest_metrics_lines
|
|
.grep(/\A#{Regexp.escape(metric_name)}(?:\{| )/)
|
|
.map { |line| line.split.last.to_f }
|
|
.max
|
|
return value unless value.nil?
|
|
|
|
raise "#{metric_name} not reported" if Process.clock_gettime(Process::CLOCK_MONOTONIC) >= deadline
|
|
|
|
sleep 0.2
|
|
end
|
|
end
|
|
|
|
def latest_metrics_lines
|
|
response = anonymous_client.get('/metrics')
|
|
expect(response[:status]).to eq(200)
|
|
raw_body(response).lines.map(&:strip)
|
|
end
|
|
|
|
def raw_body(response)
|
|
response.dig(:json, :raw_body).to_s
|
|
end
|
|
end
|