Splitting Registry for action and process-statistics and clean up repositry.
config.yml was only an example, so name it as config.yml.example and ignore any config.yml, that checkout could be used as local project-directory without conflicts. DnsblCollector will have singleton-behaviour like process configs and an own Registry. Config was loaded every request, yet. There was one Registry, which was reused for every request. Now every request will use his own Registry. Requests will get the content of both Registries.
This commit is contained in:
parent
a3e7b85a50
commit
392ac36312
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
*.sw[pomnqrst]
|
||||
*.gem
|
||||
|
||||
config.yml
|
||||
Gemfile.lock
|
|
@ -1,6 +1,9 @@
|
|||
# vim: set noet sw=2 ts=2 sts=2:
|
||||
require 'rack'
|
||||
require './dnsbl_exporter'
|
||||
require_relative 'dnsbl_exporter'
|
||||
require 'yaml'
|
||||
|
||||
DnsblCollector.load_config './config.yml'
|
||||
|
||||
run lambda {|env|
|
||||
begin
|
||||
|
@ -16,7 +19,8 @@ run lambda {|env|
|
|||
end
|
||||
collector.collect target
|
||||
[200, {"Content-Type" => "text/plain"}, [
|
||||
Prometheus::Client::Formats::Text.marshal( collector.prometheus)
|
||||
Prometheus::Client::Formats::Text.marshal( collector.registry),
|
||||
Prometheus::Client::Formats::Text.marshal( DnsblCollector.registry),
|
||||
]]
|
||||
else
|
||||
[404, {"Content-Type" => "text/plain"}, ["Not found.\nYou want to try /metrics?\n"]]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# vim: set et sw=2 ts=2 sts=2:
|
||||
---
|
||||
resolver:
|
||||
nameservers: 8.8.8.8
|
||||
nameservers: '::1'
|
||||
blacklists:
|
||||
- all.s5h.net
|
||||
- b.barracudacentral.org
|
||||
|
@ -17,7 +17,6 @@ blacklists:
|
|||
- dnsbl-1.uceprotect.net
|
||||
- dnsbl-2.uceprotect.net
|
||||
- dnsbl-3.uceprotect.net
|
||||
- dnsbl.anticaptcha.net
|
||||
- dnsbl.dronebl.org
|
||||
- dnsbl.inps.de
|
||||
- dnsbl.sorbs.net
|
|
@ -1,27 +1,22 @@
|
|||
# vim: set noet sw=2 ts=2 sts=2:
|
||||
require 'prometheus/client'
|
||||
require 'prometheus/client/formats/text'
|
||||
require 'net/dns'
|
||||
require 'yaml'
|
||||
require 'ostruct'
|
||||
|
||||
class DnsblCollector
|
||||
attr_reader :lists, :prometheus, :configfile, :resolver, :metrics
|
||||
class <<self
|
||||
attr_reader :blacklists, :resolver, :registry
|
||||
|
||||
def initialize prometheus: nil, configfile: nil
|
||||
@configfile = configfile || 'config.yml'
|
||||
@prometheus = prometheus || Prometheus::Client.registry
|
||||
%i[dnsbl_listed dnsbl_query_error].each {|m| @prometheus.unregister m }
|
||||
@metrics = {
|
||||
dnsbl_listed: @prometheus.gauge( :dnsbl_listed, 'IP listed currently on Blacklist'),
|
||||
dnsbl_query_error: @prometheus.counter( :dnsbl_query_error, 'Errors while query for blacklist'),
|
||||
}
|
||||
load_config
|
||||
def load_config file = nil
|
||||
config = YAML.load_file file || './config.yml'
|
||||
self.blacklists = config['blacklists']
|
||||
self.resolver = config['resolver']
|
||||
end
|
||||
|
||||
def load_config
|
||||
config = YAML.load_file @configfile
|
||||
@resolver = config['resolver']
|
||||
@lists =
|
||||
config['blacklists'].map do |bl|
|
||||
def blacklists= lists
|
||||
@blacklists =
|
||||
lists.map do |bl|
|
||||
case bl
|
||||
when String then {blacklist: bl}
|
||||
when Hash then bl
|
||||
|
@ -30,23 +25,52 @@ class DnsblCollector
|
|||
end
|
||||
end
|
||||
|
||||
def resolver= resolver_cnf
|
||||
@resolver =
|
||||
case resolver_cnf
|
||||
when Net::DNS::Resolver then resolver_cnf
|
||||
when Hash then Net::DNS::Resolver.new resolver_cnf
|
||||
else
|
||||
raise ConfigError, "DnsblCollector.resolver= expects a Net::DNS::Resolver or a resolver-config as Hash"
|
||||
end
|
||||
end
|
||||
|
||||
def registry= registry
|
||||
@registry = registry
|
||||
@registry.counter :dnsbl_query_error_count, docstring: 'Errors while query for blacklist', labels: %i[blacklist target]
|
||||
@registry.counter :dnsbl_query_blacklist_duration_sum, docstring: 'Total duration for querieng this blacklist', labels: %i[blacklist]
|
||||
@registry.counter :dnsbl_query_blacklist_count, docstring: 'Total count of queries this blacklist', labels: %i[blacklist]
|
||||
end
|
||||
end
|
||||
|
||||
self.registry = Prometheus::Client::Registry.new
|
||||
|
||||
attr_reader :lists, :registry, :configfile, :resolver, :metrics
|
||||
|
||||
def initialize registry: nil
|
||||
@registry = registry || Prometheus::Client::Registry.new
|
||||
@registry.gauge :dnsbl_listed, docstring: 'IP listed currently on Blacklist', labels: %i[blacklist target]
|
||||
@metrics = OpenStruct.new @registry.instance_variable_get( :@metrics).merge( self.class.registry.instance_variable_get( :@metrics))
|
||||
end
|
||||
|
||||
def collect ip
|
||||
prefix = ip.send :_reverse
|
||||
ip = ip.to_s
|
||||
dns = Net::DNS::Resolver.new @resolver
|
||||
todo = @lists.sort{|_|rand}
|
||||
durs = {}
|
||||
todo = self.class.blacklists.sort{|_|rand}
|
||||
resolver = self.class.resolver
|
||||
10.times.map do
|
||||
Thread.new do
|
||||
while bl = @lists.pop
|
||||
b = Time.now
|
||||
while bl = todo.pop
|
||||
name, b = bl[:blacklist], Time.now
|
||||
begin
|
||||
r = dns.search( "#{prefix}.#{bl[:blacklist]}", Net::DNS::A).answer.empty?
|
||||
@metrics[:dnsbl_listed].set( {blacklist: bl[:blacklist], target: ip}, r ? 0 : 1)
|
||||
r = resolver.search( "#{prefix}.#{name}", Net::DNS::A).answer.empty?
|
||||
@metrics.dnsbl_listed.set r ? 0 : 1, labels: {blacklist: name, target: ip}
|
||||
rescue Net::DNS::Resolver::NoResponseError
|
||||
@metrics[:dnsbl_query_error].increment( {blacklist: bl[:blacklist], target: ip})
|
||||
@metrics.dnsbl_query_error_count.increment labels: {blacklist: name, target: ip}
|
||||
end
|
||||
durs[bl[:blacklist]] = Time.now-b
|
||||
dur = Time.now-b
|
||||
@metrics.dnsbl_query_blacklist_duration_sum.increment by: dur, labels: {blacklist: name}
|
||||
@metrics.dnsbl_query_blacklist_count.increment labels: {blacklist: name}
|
||||
end
|
||||
end
|
||||
end.each &:join
|
||||
|
|
Loading…
Reference in a new issue