FEATURE: swap from hardcoded STDERR to logger (#177)

FEATURE: swap from hardcoded STDERR to logger (#177)

logger still defaults to STDERR, so there’s no change unless a user passes in their own logger

  • add documentation
  • add unit test for custom logger
diff --git a/README.md b/README.md
index cf3d1ea..69a1b32 100644
--- a/README.md
+++ b/README.md
@@ -28,6 +28,7 @@ To learn more see [Instrumenting Rails with Prometheus](https://samsaffron.com/a
   * [Client default host](#client-default-host)
 * [Transport concerns](#transport-concerns)
 * [JSON generation and parsing](#json-generation-and-parsing)
+* [Logging](#logging)
 * [Contributing](#contributing)
 * [License](#license)
 * [Code of Conduct](#code-of-conduct)
@@ -850,6 +851,19 @@ The `PrometheusExporter::Client` class has the method `#send-json`. This method,
 
 When `PrometheusExporter::Server::Collector` parses your JSON, by default it will use the faster Oj deserializer if available. This happens cause it only expects a simple Hash out of the box. You can opt in for the default JSON deserializer with `json_serializer: :json`.
 
+## Logging
+
+`PrometheusExporter::Client.default` will export to `STDERR`. To change this, you can pass your own logger:
+`‍``ruby
+PrometheusExporter::Client.new(logger: Rails.logger)
+PrometheusExporter::Client.new(logger: Logger.new(STDOUT))
+`‍``
+
+You can also pass a log level (default is [`Logger::WARN`](https://ruby-doc.org/stdlib-3.0.1/libdoc/logger/rdoc/Logger.html)):
+`‍``ruby
+PrometheusExporter::Client.new(log_level: Logger::DEBUG)
+`‍``
+
 ## Contributing
 
 Bug reports and pull requests are welcome on GitHub at https://github.com/discourse/prometheus_exporter. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
diff --git a/bin/prometheus_exporter b/bin/prometheus_exporter
index 2467270..e0e0594 100755
--- a/bin/prometheus_exporter
+++ b/bin/prometheus_exporter
@@ -3,12 +3,15 @@
 
 require 'optparse'
 require 'json'
+require 'logger'
 
 require_relative "./../lib/prometheus_exporter"
 require_relative "./../lib/prometheus_exporter/server"
 
 def run
-  options = {}
+  options = {
+    logger_path: STDERR
+  }
   custom_collector_filename = nil
   custom_type_collectors_filenames = []
 
@@ -61,15 +64,22 @@ def run
     opt.on('--unicorn-master PID_FILE', String, '(optional) PID file of unicorn master process to monitor unicorn') do |o|
       options[:unicorn_pid_file] = o
     end
+
+    opt.on('--logger-path PATH', String, '(optional) Path to file for logger output. Defaults to STDERR') do |o|
+      options[:logger_path] = o
+    end
   end.parse!
 
+  logger = Logger.new(options[:logger_path])
+  logger.level = Logger::WARN
+
   if options.has_key?(:realm) && !options.has_key?(:auth)
-    STDERR.puts "[Warn] Providing REALM without AUTH has no effect"
+    logger.warn "Providing REALM without AUTH has no effect"
   end
 
   if options.has_key?(:auth)
     unless File.exist?(options[:auth]) && File.readable?(options[:auth])
-      STDERR.puts "[Error] The AUTH file either doesn't exist or we don't have access to it"
+      logger.fatal "The AUTH file either doesn't exist or we don't have access to it"
       exit 1
     end
   end
@@ -88,7 +98,7 @@ def run
     end
 
     if !found
-      STDERR.puts "[Error] Can not find a class inheriting off PrometheusExporter::Server::CollectorBase"
+      logger.fatal "Can not find a class inheriting off PrometheusExporter::Server::CollectorBase"
       exit 1
     end
   end
diff --git a/lib/prometheus_exporter/client.rb b/lib/prometheus_exporter/client.rb
index 3b60c6d..aeca5e8 100644
--- a/lib/prometheus_exporter/client.rb
+++ b/lib/prometheus_exporter/client.rb
@@ -2,6 +2,7 @@
 
 require 'socket'
 require 'thread'
+require 'logger'
 
 module PrometheusExporter
   class Client
@@ -53,14 +54,20 @@ module PrometheusExporter
     MAX_SOCKET_AGE = 25
     MAX_QUEUE_SIZE = 10_000
 
+    attr_reader :logger
+
     def initialize(
       host: ENV.fetch('PROMETHEUS_EXPORTER_HOST', 'localhost'),
       port: ENV.fetch('PROMETHEUS_EXPORTER_PORT', PrometheusExporter::DEFAULT_PORT),
       max_queue_size: nil,
       thread_sleep: 0.5,
       json_serializer: nil,
-      custom_labels: nil
+      custom_labels: nil,
+      logger: Logger.new(STDERR),
+      log_level: Logger::WARN
     )
+      @logger = logger
+      @logger.level = log_level
       @metrics = []
 
       @queue = Queue.new
@@ -72,7 +79,7 @@ module PrometheusExporter
       max_queue_size ||= MAX_QUEUE_SIZE
       max_queue_size = max_queue_size.to_i
 
-      if max_queue_size.to_i <= 0
+      if max_queue_size <= 0
         raise ArgumentError, "max_queue_size must be larger than 0"
       end
 
@@ -125,7 +132,7 @@ module PrometheusExporter
     def send(str)
       @queue << str
       if @queue.length > @max_queue_size
-        STDERR.puts "Prometheus Exporter client is dropping message cause queue is full"
+        logger.warn "Prometheus Exporter client is dropping message cause queue is full"
         @queue.pop
       end
 
@@ -143,7 +150,7 @@ module PrometheusExporter
           @socket.write(message)
           @socket.write("\r\n")
         rescue => e
-          STDERR.puts "Prometheus Exporter is dropping a message: #{e}"
+          logger.warn "Prometheus Exporter is dropping a message: #{e}"
           @socket = nil
           raise
         end
@@ -168,7 +175,7 @@ module PrometheusExporter
       close_socket_if_old!
       process_queue
     rescue => e
-      STDERR.puts "Prometheus Exporter, failed to send message #{e}"
+      logger.error "Prometheus Exporter, failed to send message #{e}"
     end
 
     def ensure_worker_thread!
@@ -186,7 +193,7 @@ module PrometheusExporter
       end
     rescue ThreadError => e
       raise unless e.message =~ /can't alloc thread/
-      STDERR.puts "Prometheus Exporter, failed to send message ThreadError #{e}"
+      logger.error "Prometheus Exporter, failed to send message ThreadError #{e}"
     end
 
     def close_socket!
diff --git a/lib/prometheus_exporter/instrumentation/active_record.rb b/lib/prometheus_exporter/instrumentation/active_record.rb
index 3e49576..fcae167 100644
--- a/lib/prometheus_exporter/instrumentation/active_record.rb
+++ b/lib/prometheus_exporter/instrumentation/active_record.rb
@@ -7,9 +7,11 @@ module PrometheusExporter::Instrumentation
 
     def self.start(client: nil, frequency: 30, custom_labels: {}, config_labels: [])
 
-      # Not all rails versions support coonection pool stats
+      client ||= PrometheusExporter::Client.default
+
+      # Not all rails versions support connection pool stats
       unless ::ActiveRecord::Base.connection_pool.respond_to?(:stat)
-        STDERR.puts("ActiveRecord connection pool stats not supported in your rails version")
+        client.logger.error("ActiveRecord connection pool stats not supported in your rails version")
         return
       end
 
@@ -18,8 +20,6 @@ module PrometheusExporter::Instrumentation
 
       active_record_collector = new(custom_labels, config_labels)
 
-      client ||= PrometheusExporter::Client.default
-
       stop if @thread
 
       @thread = Thread.new do
@@ -28,7 +28,7 @@ module PrometheusExporter::Instrumentation
             metrics = active_record_collector.collect
             metrics.each { |metric| client.send_json metric }
           rescue => e
-            STDERR.puts("Prometheus Exporter Failed To Collect Process Stats #{e}")
+            client.logger.error("Prometheus Exporter Failed To Collect Process Stats #{e}")
           ensure
             sleep frequency
           end
diff --git a/lib/prometheus_exporter/instrumentation/process.rb b/lib/prometheus_exporter/instrumentation/process.rb
index 41aa302..9b2473e 100644
--- a/lib/prometheus_exporter/instrumentation/process.rb
+++ b/lib/prometheus_exporter/instrumentation/process.rb
@@ -27,7 +27,7 @@ module PrometheusExporter::Instrumentation
             metric = process_collector.collect
             client.send_json metric
           rescue => e
-            STDERR.puts("Prometheus Exporter Failed To Collect Process Stats #{e}")

[... diff too long, it was truncated ...]

GitHub sha: c3e26a827b59c225a2ffb34eec57d8541e6ee97f

This commit appears in #177 which was merged by SamSaffron.