onlylogs 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 37909543bef9f932a762a08b53c0dfbebe9094f41e96d0de8740e1e1b4b66614
4
- data.tar.gz: 1abced159b2385cd445b05196a6ac47801aeeaac96c8062729251aaf778733bd
3
+ metadata.gz: ca30039d330dc680af346b69a9d94e169f1d4e9f20c88901e8eadd7e31de4a22
4
+ data.tar.gz: 75ca252f9a28497cb229d44e2a0e27b54583913b034002a9fef3e591d92034c2
5
5
  SHA512:
6
- metadata.gz: 4def45bcdb6d9c301f3cb2d65de39f2e27247a4ae5fd7835325e8f80781279ce7ed5ac280fea95cf7d61af2d9713fae008485f9e702f4ab747a151712340bf56
7
- data.tar.gz: 74e0fa68229359024780f850dd2df95ab1d930b6a949ec85b63f20d7e8ff1253e79da81f384bb6057d588b10d67764dbaa7761db1212051c8e69c2841a8dce89
6
+ metadata.gz: 9486d5057bde025f77b2e5f66aa616b805dead3e136295341b9181622ae69277aca2f24f981820f48487cc0d7c7f17de4e2f24341160b448215398d9d87753f4
7
+ data.tar.gz: 9bbf4422321aa4d1cdcf690fa6ad597fd748b0f9c9d0f34e7291a015ec71ce091fee8ad05fb9eccbf8ea71adc768c48a2ed73bd8618c25fdff24aa9bb6478505
@@ -11,18 +11,12 @@
11
11
  border-bottom: 1px solid lightgray;
12
12
  }
13
13
 
14
- .logo {
15
- height: 20px;
16
- margin: 3px;
17
- }
18
-
19
14
  .log-file-dropdown {
20
15
  margin-left: 0.5rem;
21
16
  }
22
17
  </style>
23
18
  <div class="grid">
24
19
  <div class="grid-header">
25
- <%= image_tag "onlylogs/logo.png", class: "logo" %>
26
20
  <% if @available_log_files.any? %>
27
21
  <%= form_with url: root_path, method: :get, local: true, class: "log-file-dropdown" do %>
28
22
  <select id="log_file_path" name="log_file_path" onchange="this.form.submit()">
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "net/http"
4
+ require "uri"
5
+
6
+ # This logger sends messages to onlylogs.io (or any Vector-compatible sink) directly via HTTP.
7
+ # Unlike SocketLogger, it does not require a sidecar process or Puma plugin,
8
+ # so it works from any process: Puma, GoodJob, Sidekiq, rake tasks, migrations, etc.
9
+
10
+ module Onlylogs
11
+ class HttpLogger < Onlylogs::Logger
12
+ DEFAULT_BATCH_SIZE = 100
13
+ DEFAULT_FLUSH_INTERVAL = 0.5
14
+
15
+ def initialize(
16
+ local_fallback: $stdout,
17
+ drain_url: ENV["ONLYLOGS_DRAIN_URL"],
18
+ batch_size: ENV.fetch("ONLYLOGS_BATCH_SIZE", DEFAULT_BATCH_SIZE).to_i,
19
+ flush_interval: ENV.fetch("ONLYLOGS_FLUSH_INTERVAL", DEFAULT_FLUSH_INTERVAL).to_f
20
+ )
21
+ super(local_fallback)
22
+ @drain_url = drain_url
23
+ @batch_size = batch_size
24
+ @flush_interval = flush_interval
25
+ @queue = Queue.new
26
+ @mutex = Mutex.new
27
+
28
+ start_sender if @drain_url
29
+ end
30
+
31
+ def add(severity, message = nil, progname = nil, &block)
32
+ if message.nil?
33
+ if block_given?
34
+ message = block.call
35
+ else
36
+ message = progname
37
+ progname = nil
38
+ end
39
+ end
40
+
41
+ formatted = format_message(format_severity(severity), Time.now, progname, message.to_s)
42
+ @queue << formatted if formatted && @drain_url
43
+ super
44
+ end
45
+
46
+ def close
47
+ flush
48
+ @running = false
49
+ @sender_thread&.join(2)
50
+ end
51
+
52
+ def flush
53
+ send_batch(drain_queue)
54
+ end
55
+
56
+ private
57
+
58
+ def start_sender
59
+ @running = true
60
+
61
+ @sender_thread = Thread.new do
62
+ batch = []
63
+ last_flush = Time.now
64
+
65
+ while @running || !@queue.empty?
66
+ begin
67
+ line = @queue.pop(true)
68
+ batch << line if line
69
+ rescue ThreadError
70
+ # queue empty
71
+ end
72
+
73
+ if batch.any? && (batch.size >= @batch_size || (Time.now - last_flush) >= @flush_interval)
74
+ send_batch(batch)
75
+ batch = []
76
+ last_flush = Time.now
77
+ end
78
+
79
+ sleep 0.01 if batch.empty?
80
+ end
81
+
82
+ send_batch(batch) if batch.any?
83
+ end
84
+
85
+ at_exit { close }
86
+ end
87
+
88
+ def drain_queue
89
+ lines = []
90
+ lines << @queue.pop(true) until @queue.empty?
91
+ lines
92
+ rescue ThreadError
93
+ lines
94
+ end
95
+
96
+ def send_batch(lines)
97
+ return if lines.empty?
98
+
99
+ uri = URI.parse(@drain_url)
100
+ http = Net::HTTP.new(uri.host, uri.port)
101
+ http.use_ssl = (uri.scheme == "https")
102
+ http.read_timeout = 5
103
+ http.open_timeout = 2
104
+
105
+ request = Net::HTTP::Post.new(uri.path)
106
+ request.body = lines.join("\n")
107
+ request.content_type = "text/plain"
108
+
109
+ http.start { |h| h.request(request) }
110
+ rescue => e
111
+ warn "Onlylogs::HttpLogger error: #{e.class}: #{e.message}"
112
+ end
113
+ end
114
+ end
@@ -39,10 +39,10 @@ module Onlylogs
39
39
  socket = ensure_socket
40
40
  socket&.puts(payload)
41
41
  rescue Errno::EPIPE, Errno::ECONNREFUSED, Errno::ENOENT => e
42
- warn "Onlylogs::SocketLogger error: #{e.message}"
42
+ $stderr.puts "Onlylogs::SocketLogger error: #{e.message}" # rubocop:disable Style/StderrPuts
43
43
  reconnect_socket
44
44
  rescue => e
45
- warn "Onlylogs::SocketLogger unexpected error: #{e.class}: #{e.message}"
45
+ $stderr.puts "Onlylogs::SocketLogger unexpected error: #{e.class}: #{e.message}" # rubocop:disable Style/StderrPuts
46
46
  reconnect_socket
47
47
  end
48
48
 
@@ -52,7 +52,7 @@ module Onlylogs
52
52
  @socket_mutex.synchronize do
53
53
  @socket ||= UNIXSocket.new(@socket_path)
54
54
  rescue => e
55
- warn "Unable to connect to Onlylogs sidecar (#{@socket_path}): #{e.message}"
55
+ $stderr.puts "Unable to connect to Onlylogs sidecar (#{@socket_path}): #{e.message}" # rubocop:disable Style/StderrPuts
56
56
  @socket = nil
57
57
  end
58
58
 
@@ -1,3 +1,3 @@
1
1
  module Onlylogs
2
- VERSION = "0.4.0"
2
+ VERSION = "0.4.2"
3
3
  end
data/lib/onlylogs.rb CHANGED
@@ -4,6 +4,7 @@ require "onlylogs/engine"
4
4
  require "onlylogs/formatter"
5
5
  require "onlylogs/logger"
6
6
  require "onlylogs/socket_logger"
7
+ require "onlylogs/http_logger"
7
8
 
8
9
  # require "zeitwerk"
9
10
  #
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: onlylogs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alessandro Rodi
@@ -74,6 +74,7 @@ files:
74
74
  - lib/onlylogs/configuration.rb
75
75
  - lib/onlylogs/engine.rb
76
76
  - lib/onlylogs/formatter.rb
77
+ - lib/onlylogs/http_logger.rb
77
78
  - lib/onlylogs/logger.rb
78
79
  - lib/onlylogs/socket_logger.rb
79
80
  - lib/onlylogs/version.rb