raindrops.git  about / heads / tags
real-time stats for preforking Rack servers
blob e6c47e158a57f2e3caaf01bb7921a6cbd92f71dd 3164 bytes (raw)
$ git show HEAD:lib/raindrops/last_data_recv.rb	# shows this blob on the CLI

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
 
# -*- encoding: binary -*-
# frozen_string_literal: false
require "raindrops"

# This is highly experimental!
#
# A self-contained Rack application for aggregating in the
# +tcpi_last_data_recv+ field in +struct+ +tcp_info+ defined in
# +/usr/include/linux/tcp.h+.  This is only useful for \Linux 2.6 and later.
# This primarily supports Unicorn and derived servers, but may also be
# used with any Ruby web server using the core TCPServer class in Ruby.
#
# Hitting the Rack endpoint configured for this application will return
# a an ASCII histogram response body with the following headers:
#
# - X-Count   - number of requests received
#
# The following headers are only present if X-Count is greater than one.
#
# - X-Min     - lowest last_data_recv time recorded (in milliseconds)
# - X-Max     - highest last_data_recv time recorded (in milliseconds)
# - X-Mean    - mean last_data_recv time recorded (rounded, in milliseconds)
# - X-Std-Dev - standard deviation of last_data_recv times
# - X-Outliers-Low - number of low outliers (hopefully many!)
# - X-Outliers-High - number of high outliers (hopefully zero!)
#
# == To use with Unicorn and derived servers (preload_app=false):
#
# Put the following in our Unicorn config file (not config.ru):
#
#   require "raindrops/last_data_recv"
#
# Then follow the instructions below for config.ru:
#
# == To use with any Rack server using TCPServer
#
# Setup a route for Raindrops::LastDataRecv in your Rackup config file
# (typically config.ru):
#
#   require "raindrops"
#   map "/raindrops/last_data_recv" do
#     run Raindrops::LastDataRecv.new
#   end
#   map "/" do
#     use SomeMiddleware
#     use MoreMiddleware
#     # ...
#     run YourAppHere.new
#   end
#
# == To use with any other Ruby web server that uses TCPServer
#
# Put the following in any piece of Ruby code loaded after the server has
# bound its TCP listeners:
#
#   ObjectSpace.each_object(TCPServer) do |s|
#     s.extend Raindrops::Aggregate::LastDataRecv
#   end
#
#   Thread.new do
#     Raindrops::Aggregate::LastDataRecv.default_aggregate.master_loop
#   end
#
# Then follow the above instructions for config.ru
#
class Raindrops::LastDataRecv
  # :stopdoc:

  # trigger autoloads
  if defined?(Unicorn)
    agg = Raindrops::Aggregate::LastDataRecv.default_aggregate
    AGGREGATE_THREAD = Thread.new { agg.master_loop }
  end
  # :startdoc

  def initialize(opts = {})
    if defined?(Unicorn::HttpServer::LISTENERS)
      Raindrops::Aggregate::LastDataRecv.cornify!
    end
    @aggregate =
      opts[:aggregate] || Raindrops::Aggregate::LastDataRecv.default_aggregate
  end

  def call(_)
    a = @aggregate
    count = a.count
    headers = {
      "Content-Type" => "text/plain",
      "X-Count" => count.to_s,
    }
    if count > 1
      headers["X-Min"] = a.min.to_s
      headers["X-Max"] = a.max.to_s
      headers["X-Mean"] = a.mean.round.to_s
      headers["X-Std-Dev"] = a.std_dev.round.to_s
      headers["X-Outliers-Low"] = a.outliers_low.to_s
      headers["X-Outliers-High"] = a.outliers_high.to_s
    end
    body = a.to_s
    headers["Content-Length"] = body.size.to_s
    [ 200, headers, [ body ] ]
  end
end

git clone https://yhbt.net/raindrops.git