LogStashLogger 擴展了 Ruby 的Logger
類別以直接記錄到 Logstash。它支援以 Logstash JSON 格式寫入各種輸出。這是對寫入檔案或系統日誌的改進,因為 Logstash 可以直接接收結構化資料。
可透過 UDP 或 TCP/SSL 連線直接寫入 Logstash 偵聽器。
可寫入檔案、Redis、Kafka、Kinesis、Firehose、unix 套接字、syslog、stdout 或 stderr。
Logger 可以採用字串訊息、雜湊值、 LogStash::Event
、物件或 JSON 字串作為輸入。
事件會自動填入訊息、時間戳記、主機和嚴重性。
以 Logstash JSON 格式寫入,但也支援其他格式。
可以寫入多個輸出。
日誌訊息會被緩衝並在出現連線問題時自動重新傳送。
透過配置輕鬆與 Rails 整合。
將此行新增至應用程式的 Gemfile 中:
gem 'logstash-logger'
然後執行:
$ bundle
或自己安裝:
$ gem install logstash-logger
require 'logstash-logger'# 預設為0.0.0.0 上的UDPlogger = LogStashLogger.new(port: 5228)# 明確指定主機與型別(UDP 或TCP)udp_logger = LogStashLogger.new(type: :udp, host: ' localhost' , port: 5228)tcp_logger = LogStashLogger.new(type: :tcp, host: 'localhost', port: 5229)# 其他類型的記錄器file_logger = LogStashLogger.new(type: :file, path: 'log/ development.log' , 同步: true)unix_logger = LogStashLogger.new(類型: :unix, 路徑: '/tmp/sock')syslog_logger = LogStashLogger.new(類型: :syslog)redis_logger = LogStashLogger.new(類型: :redis )kafka_logger = LogStashLogger .new(type: :kafka)stdout_logger = LogStashLogger.new(type: :stdout)stderr_logger = LogStashLogger.new(type: :stderr)io_logger = LogStashLogger.new: Stash: type: .使用不同的格式tercee_logger = LogStashLogger.new( 類型::TCP, 主機:'logsene-receiver-syslog.sematext.com', 埠:514, 格式化程式: :cee_syslog)custom_formatted_logger = LogStashLogger.new( 類型::redis, 格式化程式:MyCustomFormatter)lambda_formatted_logger = LogStashLogger.new( 類型::標準輸出, 格式化程式:->(嚴重性、時間、程式名稱、訊息) { "[#{progname}] #{msg}" })ruby_default_formatter_logger = LogStashLogger.new( 類型::文件, 路徑: 'log/development.log', formatter: ::Logger::Formatter)# 將訊息傳送到多個輸出。每個輸出都會有相同的格式。 類型::multi_delegator, 輸出:[{ 類型::file,路徑:'log/development.log' },{ 類型::udp,主機:'localhost',連接埠:5228 } ])# 平衡多個輸出之間的訊息。 類型::平衡器, 輸出:[{類型::udp,主機:'host1',連接埠:5228},{類型::udp,主機:'host2',連接埠:5228} ])# 傳送訊息給多個記錄器。 類型::multi_logger, 輸出:[{ 類型::文件,路徑:'log/development.log',格式化程式:::Logger::Formatter },{ 類型::tcp,主機:'localhost',連接埠:5228,格式化程式::json } ])# 下列訊息寫入 UDP 連接埠 5228:logger.info 'test'# {"message":"test","@timestamp":"2014-05-22T09:37:19.204-07:00", "@ version":"1","severity":"INFO","host":"[主機名稱]"}logger.error '{"message": "error"}'# {"message":"error" , "@timestamp":"2014-05-22T10:10:55.877-07:00","@version":"1","severity":"ERROR","host":"[主機名稱]"}記錄器.debug message: 'test', foo: 'bar'# {"message":"test","foo":"bar","@timestamp":"2014-05-22T09:43:24.004-07: 00 ","@version":"1","severity":"DEBUG","host":"[主機名稱]"}logger.warn LogStash::Event.new(message: 'test', foo: ' bar' )# {"message":"test","foo":"bar","@timestamp":"2014-05-22T16:44:37.364Z","@version":"1","severity ": "WARN","host":"[主機名稱]"}# 已標記的logginglogger.tagged('foo') { logger.fatal('bar') }# {"message":"bar"," @timestamp":" 2014-05-26T20:35:14.685-07:00","@version":"1","嚴重性":"致命","主機":"[主機名稱]","標籤":["foo" ]}
您可以使用 URI 而不是雜湊來配置 Logstash 記錄器。這在 Heroku 等環境中非常有用,您可能想要從環境中讀取配置值。 URI 方案為type://host:port/path?key=value
。下面給出了一些範例 URI 配置。
udp://localhost:5228 tcp://localhost:5229 unix:///tmp/socket file:///path/to/file redis://localhost:6379 kafka://localhost:9092 stdout:/ stderr:/
將 URI 傳遞到您的 Logstash 記錄器中,如下所示:
# 從環境變數讀取 URIlogger = LogStashLogger.new(uri: ENV['LOGSTASH_URI'])
為了讓 Logstash 正確接收和解析事件,您需要設定並執行使用json_lines
編解碼器的偵聽器。例如,要在連接埠 5228 上透過 UDP 接收事件:
輸入 { udp {主機=>“0.0.0.0”連接埠=>5228codec=>json_lines }}
文件和 Redis 輸入應使用json
編解碼器。有關更多信息,請閱讀 Logstash 文件。
如需更多設定範例,請參閱範例目錄。
如果您使用 TCP,則可以選擇在初始化時將 SSL 憑證新增至選項雜湊。
LogStashLogger.new(類型::tcp,連接埠:5228,ssl_certificate:“/path/to/certificate.crt”)
SSL 憑證和金鑰可以使用以下方式產生
openssl req -x509 -batch -nodes -newkey rsa:2048 -keyout logstash.key -out logstash.crt
您也可以在沒有憑證的情況下啟用 SSL:
LogStashLogger.new(類型::tcp,連接埠:5228,ssl_enable:true)
指定 SSL 上下文以更好地控制行為。例如設定驗證模式:
ctx = OpenSSL::SSL::SSLContext.newctx.set_params(verify_mode: OpenSSL::SSL::VERIFY_NONE)LogStashLogger.new(類型::tcp,連接埠:5228,ssl_context:ctx)
SSL 需要以下 Logstash 配置:
輸入 { tcp {主機=>“0.0.0.0”連接埠=>5228codec=>json_inesssl_enable=>truessl_cert=>“/path/to/certificate.crt”ssl_key=>“/path/to/key.key” }}
預設情況下啟用主機名稱驗證。無需進一步配置,提供給:host
的主機名稱將用於驗證伺服器的憑證身分。
如果您不傳遞:ssl_context
或向:verify_hostname
選項傳遞 false 值,則不會進行主機名稱驗證。
透過:host
選項驗證主機名
ctx = OpenSSL::SSL::SSLContext.newctx.cert = '/path/to/cert.pem'ctx.verify_mode = OpenSSL::SSL::VERIFY_PEERLogStashLogger.new 類型::TCP, 主機:'logstash.example.com' 埠:5228, ssl_上下文:ctx
驗證主機名稱與:host
選項不同
LogStashLogger.new 類型::TCP, 主機:'1.2.3.4' 埠:5228, ssl_context:ctx, verify_hostname: 'server.example.com'
明確禁用主機名稱驗證
LogStashLogger.new 類型::TCP, 主機:'1.2.3.4' 埠:5228, ssl_context:ctx, 驗證主機名稱: false
預設情況下, LogStashLogger
將記錄以下格式的 JSON 物件。
{ "message":"一些訊息", "@timestamp":"2015-01-29T10:43:32.196-05:00", "@version":"1", "severity":"INFO", "host ":"主機名稱"}
某些應用程式可能需要將附加元資料附加到每個訊息。可以透過在LogStashLogger
配置中指定customize_event
區塊來直接從事LogStash::Event
。
config = LogStashLogger.configure 做 |config| config.customize_event do |event|event["other_field"] = "some_other_value" 結束
此配置將產生以下輸出。
{“message”:“一些訊息”,“@timestamp”:“2015-01-29T10:43:32.196-05:00”,“@version”:“1”,“嚴重性”:“INFO”,“主機": "主機名稱","other_field": "some_other_value"}
該區塊具有對事件的完全存取權限,因此您可以刪除欄位、修改現有欄位等。
config = LogStashLogger.configure 做 |config| config.customize_event do |event|event.remove('@timestamp') 結束
您也可以在建立記錄器時將可呼叫物件(lambda 或 proc)傳遞給customize_event
選項,從而在每個記錄器的基礎上自訂事件:
LogStashLogger.new(customize_event: ->(event){ event['other_field'] = 'other_field' })
對於與遠端服務建立連接的設備,日誌訊息在內部緩衝並在後台執行緒中刷新。如果出現連線問題,訊息將保存在緩衝區中並自動重新傳送,直到成功為止。支援批次寫入的輸出(Redis 和 Kafka)將從緩衝區批次寫入日誌訊息。此功能是使用 Stud::Buffer 的分支來實現的。您可以將以下選項傳遞給 LogStashLogger 來配置其行為:
:buffer_max_items - 刷新之前緩衝的最大項目數。預設為 50。
:buffer_max_interval - 刷新之間等待的最大秒數。預設為 5。
:drop_messages_on_flush_error - 出現刷新錯誤時刪除訊息。預設為 false。
:drop_messages_on_full_buffer - 當緩衝區已滿時刪除訊息。預設為 true。
:sync - 每次收到訊息時刷新緩衝區(阻塞)。預設為 false。
:buffer_flush_at_exit - 退出程式時刷新訊息。預設為 true。
:buffer_logger - 用於寫入緩衝區偵錯/錯誤訊息的記錄器。預設為無。
您可以透過設定sync = true
來關閉緩衝。
請注意此行為的以下警告:
重試時可能會發送重複的日誌訊息。對於像 Redis 和 Kafka 這樣批量寫入的輸出,整個批次可能會被重新發送。如果這是一個問題,您可以向每個事件添加 UUID 欄位以唯一標識它。您可以在customize_event
區塊中執行此操作,也可以使用logstash 的UUID 過濾器來執行此操作。
仍然有可能丟失日誌訊息。 Ruby 不會立即偵測到 TCP/UDP 連線問題。在我的測試中,Ruby 花了大約 4 秒的時間才注意到接收端已關閉並開始引發異常。由於 TCP/UDP 上的 Logstash 偵聽器不會確認收到的訊息,因此無法知道要重新傳送哪些日誌訊息。
當sync
關閉時,Ruby 可能會在寫入 IO 裝置之前在內部緩衝資料。這就是為什麼即使 LogStashLogger 的緩衝區定期刷新,您也可能看不到立即寫入 UDP 或 TCP 套接字的訊息。
預設情況下,當緩衝區已滿時,訊息將被丟棄。如果輸出來源關閉時間過長或接收日誌訊息的速度過快,則可能會發生這種情況。如果您的應用程式突然終止(例如,由於 SIGKILL 或斷電),則整個緩衝區將會遺失。
您可以透過增加buffer_max_items
(以便緩衝區中可以保存更多事件)和減少buffer_max_interval
(以減少刷新之間的等待時間)來降低訊息遺失的可能性。當日誌訊息在緩衝區中累積時,這會增加應用程式的記憶體壓力,因此請確保為進程分配了足夠的記憶體。
如果您不想在緩衝區滿時遺失訊息,可以設定drop_messages_on_full_buffer = false
。請注意,如果緩衝區已滿,任何傳入的日誌訊息都將被阻塞,這可能是不可取的。
所有記錄器輸出都支援sync
設定。這類似於 Ruby IO 物件上的「同步模式」設定。當設為true
時,輸出將立即刷新並且不會在內部緩衝。通常,對於連接到遠端服務的裝置來說,緩衝是一件好事,因為它可以提高效能並減少影響程式的錯誤的可能性。對於這些設備, sync
預設為false
,建議保留預設值。您可能需要開啟同步模式進行測試,例如,如果您想在寫入日誌訊息後立即查看日誌訊息。
建議為檔案和 Unix 套接字輸出開啟同步模式。這可確保來自不同執行緒或行程的日誌訊息正確寫入不同的行。
有關更多詳細信息,請參閱#44。
如果在寫入訊息到裝置時發生異常,則會使用內部記錄器記錄該異常。預設情況下,這會記錄到 $stderr。您可以透過設定LogStashLogger.configuration.default_error_logger
或在實例化 LogStashLogger 時在:error_logger
配置鍵中傳遞您自己的記錄器物件來變更錯誤記錄器。
LogStashLogger 提供對 Rails 風格的記錄器靜默的支援。該實作是從 Rails 中提取的,但沒有依賴項,因此可以在 Rails 應用程式之外使用。此介面與 Rails 中的介面相同:
logger.silence(temporary_level) 做 ……結尾
預設情況下,LogStashLogger 會建立一個擴充 Ruby 內建Logger
類別的記錄器。如果您需要不同的記錄器實現,則可以透過使用logger_class
選項傳入類別來使用不同的類別。
請注意,對於 syslog, Syslog::Logger
類別是必要的且無法變更。
支援 Rails 4.2 和 5.x。
預設情況下,每個 Rails 日誌訊息都會LogStash::Event
JSON 格式寫入logstash。
對於最少的、更結構化的 Logstash 事件,請嘗試以下 gem 之一:
記錄
碼高機
目前,這些 gem 輸出一個 JSON 字串,然後由 LogStashLogger 解析。這些 gem 的未來版本可能會與 LogStashLogger 進行更深入的整合(例如,透過直接編寫LogStash::Event
物件)。
將以下內容新增至您的config/environments/production.rb
:
# 可選,Rails 將預設為 :infoconfig.log_level = :debug# 可選,Rails 4 在開發中預設為 true,在生產中預設為 falseconfig.autoflush_log = true# 可選,使用 URI 進行設定。對 Herokuconfig.logstash.uri 很有用 = ENV['LOGSTASH_URI']# 可選。預設為:json_lines。如果有多個輸出,#它們將共用相同的格式化程式。預設記錄到 $stderrconfig.logstash.error_logger = Logger.new($stderr)# 可選,刷新之前要緩衝的最大項目數。預設為 50config.logstash.buffer_max_items = 50# 可選,刷新之間等待的最大秒數。預設為 5config.logstash.buffer_max_interval = 5# 可選,發生連線錯誤時丟棄訊息。預設為 falseconfig.logstash.drop_messages_on_flush_error = false# 可選,當緩衝區已滿時刪除訊息。預設為 trueconfig.logstash.drop_messages_on_full_buffer = true
# 可選,預設為 '0.0.0.0'config.logstash.host = 'localhost'# 可選,預設為 :udp.config.logstash.type = :udp# 必需,連接的連接埠config.logstash.port = 5228
# 可選,預設為'0.0.0.0'config.logstash.host = 'localhost'# 必需,連接的連接埠config.logstash.port = 5228# 必要config.logstash.type = :tcp# 可選,啟用SSLconfig. logstash。
# 必要的config.logstash.type = :unix# 必要的config.logstash.path = '/tmp/sock'
如果您使用的是 Ruby 1.9,請將Syslog::Logger
v2 加入您的 Gemfile 中:
gem 'SyslogLogger', '2.0'
如果您使用的是 Ruby 2+, Syslog::Logger
已內建到標準庫中。
# 必要的config.logstash.type = :syslog# 可選。預設為 'ruby'config.logstash.program_name = 'MyApp'# 可選的預設設施等級。僅適用於 Ruby 2+config.logstash.facility = Syslog::LOG_LOCAL0
將 redis gem 新增到您的 Gemfile 中:
gem 'redis'
# 必要config.logstash.type = :redis# 可選,預設為'logstash'列表config.logstash.list = 'logstash'# 所有其他選項都會傳入Redis用戶端# 支援的選項包括主機、連接埠、路徑、密碼, url# 範例:# 可選,Redis 將預設為 localhostconfig.logstash.host = 'localhost'# 可選,Redis 將預設為連接埠 6379config.logstash.port = 6379
將海神 gem 加入您的 Gemfile 中:
gem 'poseidon'
# 必要config.logstash.type = :kafka# 可選,預設為'logstash' topicconfig.logstash.path = 'logstash'# 可選,預設為'logstash-logger' Producerconfig.logstash. Producer = 'logstash-logger ' # 可選,預設為localhost:9092 host/portconfig.logstash.hosts = ['localhost:9092']# 可選,預設為1s backoffconfig.logstash.backoff = 1
將 aws-sdk gem 加入到您的 Gemfile 中:
# aws-sdk >= 3.0 gem 'aws-sdk-kinesis' # aws-sdk < 3.0 gem 'aws-sdk'
# 必要config.logstash.type = :kinesis# 可選,預設為「logstash」streamconfig.logstash.stream = 'my-stream-name'# 可選,預設為「us-east-1」config.logstash.aws_region = 'us-west-2'# 可選,預設為AWS_ACCESS_KEY_ID 環境變數config.logstash.aws_access_key_id = 'ASKASKHLD12341'# 可選,預設為AWS_SECRET_ACCESS_KEY 環境變數config.logstash.aws_sec34001
將 aws-sdk gem 加入到您的 Gemfile 中:
# aws-sdk >= 3.0 gem 'aws-sdk-firehose' # aws-sdk < 3.0 gem 'aws-sdk'
# 必要的config.logstash.type = :firehose# 可選,將預設為「logstash」傳輸流config.logstash.stream = 'my-stream-name'# 可選,將預設為AWS預設區域配置chainconfig.logstash .aws_region = ' us-west-2'# 可選,將預設為AWS 預設憑證提供者chainconfig.logstash.aws_access_key_id = 'ASKASKHLD12341'# 可選,將預設為AWS 預設憑證提供者chainconfig.logstash.aws_secret_access_bkey ASKASKHLD1234123412341234'
# 必填config.logstash.type = :file# 可選,預設為Rails日誌路徑config.logstash.path = 'log/Production.log'
# 必要的config.logstash.type = :io# 必要的config.logstash.io = io
# 必要的config.logstash.type = :multi_delegator# 必要的config.logstash.outputs = [ {類型::文件,路徑:'日誌/生產.log' }, {類型::udp,連接埠:5228,主機:'localhost' }]
# 必要的config.logstash.type = :multi_logger# 必需的。每個記錄器可能都有自己的 formatter.config.logstash.outputs = [ {類型::文件,路徑:'日誌/生產.log',格式化程式:::Logger::Formatter }, {類型::udp,連接埠:5228,主機:'localhost' }]
在 Web 應用程式中,您可以使用 RequestStore 中間件記錄來自 HTTP 請求的資料(例如標頭)。以下範例假設為 Rails。
# 在 Gemfilegem 'request_store' 中
# 在 application.rbLogStashLogger.configure 中執行 |config| config.customize_event do |event|event["session_id"] = RequestStore.store[:load_balancer_session_id] 結束
#在應用程式/控制器/application_controller.rbbefore_filter中:track_load_balancer_session_iddef track_load_balancer_session_id RequestStore.store[:load_balancer_session_id] = request.headers["X-LOADBALANCER-SESSIONID"]end
如果您的應用程式分叉(這在許多 Web 伺服器中很常見),您將需要管理 LogStashLogger 實例上的資源清理。實例方法#reset
可用於此目的。以下是與 Rails 一起使用的幾種常見 Web 伺服器的範例配置:
乘客:
::PhusionPassenger.on_event(:starting_worker_process) 做 |forked| Rails.logger.resetend
美洲獅:
# 在 config/puma.rbon_worker_boot 中執行 Rails.logger.resetend
獨角獸
# 在 config/unicorn.rbafter_fork 中執行 |server,worker| Rails.logger.resetend
已驗證可與:
核磁共振紅寶石 2.2 - 2.5
JRuby 9.x
魯比紐斯
Ruby 版本 < 2.2 已停產,不再支援。
這取決於您的特定需求,但大多數應用程式應使用預設值 (UDP)。以下是每種類型的優點和缺點:
UDP 比 TCP 更快,因為它是非同步的(即發即棄)。但是,這意味著日誌訊息可能會被丟棄。這對於許多應用程式來說都是可以的。
TCP 驗證是否已透過雙向通訊接收每個訊息。它還支援 SSL 透過網路安全傳輸日誌訊息。如果 TCP 偵聽器負載過重,這可能會減慢您的應用程式的速度。
文件使用起來很簡單,但您將不得不擔心日誌輪換和磁碟空間不足。
寫入 Unix 套接字比寫入 TCP 或 UDP 連接埠更快,但只能在本機上工作。
寫入 Redis 對於產生大量日誌的分散式設定很有用。然而,您將有另一個移動部分,並且必須擔心 Redis 內存不足。
僅建議出於調試目的寫入標準輸出。
有關 UDP 與 TCP 的更詳細討論,我建議閱讀這篇文章:UDP 與 TCP
如果您使用的是 Ruby IO 物件支援的裝置(例如檔案、UDP 套接字或 TCP 套接字),請注意 Ruby 保留其自己的內部緩衝區。儘管 LogStashLogger 會緩衝訊息並定期刷新它們,但寫入 IO 物件的資料可以由 Ruby 內部無限期地緩衝,甚至可能直到程式終止才寫入。如果這讓您煩惱或您需要立即查看日誌訊息,您唯一的辦法就是設定sync: true
選項。
您的應用程式可能正在嘗試記錄未以有效方式編碼的資料。當發生這種情況時,Ruby 的標準 JSON 庫將引發異常。您可以透過更換不同的 JSON 編碼器(例如 Oj)來克服這個問題。使用 oj_mimic_json gem 來使用 Oj 進行 JSON 產生。
Heroku 建議安裝rails_12factor,以便將日誌傳送到STDOUT。不幸的是,這會覆寫 LogStashLogger,從而阻止日誌傳送到其配置的目的地。解決方案是從 Gemfile 中刪除rails_12factor
。
這很可能不是 LogStashLogger 的問題,而是改變Rails.logger
日誌等級的不同 gem 的問題。如果您使用的是 Puma 等執行緒伺服器,這種情況尤其可能發生,因為 gem 經常以非執行緒安全的方式變更Rails.logger
的日誌等級。有關詳細信息,請參閱#17。
如果您使用 UDP 輸出並向 Logstash 偵聽器寫入數據,則很可能會在 Logstash 偵聽器的 UDP 實作中遇到錯誤。目前沒有已知的修復方法。有關詳細信息,請參閱#43。
使用 TCP 或 UDP 的一個已知缺點是總訊息大小限制為 65535 位元組。要解決此問題,您必須透過設定最大訊息大小來截斷訊息:
LogStashLogger.configure 執行 |config| config.max_message_size = 2000end
這將僅截斷 LogStash 事件的message
欄位。因此,請確保將最大訊息大小設定為明顯小於 65535 字節,以便為其他欄位騰出空間。
Rails 3.2、MRI Ruby < 2.2 和 JRuby 1.7 不再受支持,因為它們已停產。如果您使用的是較舊版本的 Ruby,則需要使用 0.24 或更低版本。
source
事件鍵已替換為host
,以更好地匹配最新的logstash。
(host, port, type)
建構函式已被棄用,取而代之的是選項雜湊建構函式。
LogStash::Event
從 1.2+ 版本開始使用 v1 格式。如果您使用的是 v1,則需要安裝 LogStashLogger 版本 0.4+。這與使用 v0 格式的舊LogStash::Event
v1.1.5 不向後相容。
這個 gem 的早期版本(<= 0.2.1)僅實作了 TCP 連線。較新的版本 (>= 0.3) 也實作了 UDP,並將其用作新的預設值。請注意,如果您使用預設建構函式並且仍然需要 TCP,則應該新增一個附加參數:
# 現在預設為 UDP 而非 TCPlogger = LogStashLogger.new('localhost', 5228)# 明確指定 TCP 而非 UDPlogger = LogStashLogger.new('localhost', 5228, :tcp)
大衛巴特勒
pctj101
加里·雷尼
尼克·埃蒂爾
阿倫·馬布里
簡·舒爾特
科特·普雷斯頓
克里斯·布拉奇利
菲利克斯·貝希斯坦
瓦季姆·卡扎科夫
阿尼爾·雷姆圖拉
尼基塔·沃羅貝
火男孩1919
麥克·岡德羅伊
維塔利·戈羅德茨基
考特蘭·考德威爾
比貝克·什雷斯塔
亞歷克斯·伊阿努斯
克雷格·里德
格拉齊格
蘭斌
若奧費爾南德斯
酷貓王
謝爾蓋·皮揚科夫
亞歷克·霍伊
阿列克謝·克拉斯諾佩羅夫
加布里埃爾·德·奧利維拉
弗拉迪斯拉夫·夏布魯克
馬圖斯·瓦庫拉
分叉它
建立您的功能分支( git checkout -b my-new-feature
)
提交您的更改( git commit -am 'Add some feature'
)
推送到分支( git push origin my-new-feature
)
建立新的拉取請求