discourse/spec/lib/discourse_logstash_logger_spec.rb
Alan Guo Xiang Tan af2bd4cc50
DEV: Add exception class and message fields to DiscourseLogstashLogger (#27787)
This commit updates `DiscourseLogstashlogger` to add the
`exception_class` and `exception_message` field to the log line when the
`progname` of the log message is `web-exception` which is Logster's
logging of exceptions during a web request.

The `exception_class` and `exception_message` fields allows consumers of
the logs to easily group logs together.
2024-07-10 08:54:39 +08:00

155 lines
5.0 KiB
Ruby

# frozen_string_literal: true
RSpec.describe DiscourseLogstashLogger do
let(:lograge_logstash_formatter_formatted_message) do
"{\"method\":\"GET\",\"path\":\"/\",\"format\":\"html\",\"controller\":\"ListController\",\"action\":\"latest\",\"status\":200,\"allocations\":242307,\"duration\":178.2,\"view\":78.36,\"db\":0.0,\"params\":\"\",\"ip\":\"127.0.0.1\",\"username\":null,\"@timestamp\":\"2024-07-01T07:51:11.283Z\",\"@version\":\"1\",\"message\":\"[200] GET / (ListController#latest)\"}"
end
let(:output) { StringIO.new }
let(:logger) { described_class.logger(logdev: output, type: "test") }
describe "#add" do
it "logs a JSON string with the right fields" do
logger.add(Logger::INFO, lograge_logstash_formatter_formatted_message)
output.rewind
expect(output.read.chomp).to eq(
{
"message" => "[200] GET / (ListController#latest)",
"severity" => 1,
"severity_name" => "INFO",
"pid" => described_class::PROCESS_PID,
"type" => "test",
"host" => described_class::HOST,
"method" => "GET",
"path" => "/",
"format" => "html",
"controller" => "ListController",
"action" => "latest",
"status" => 200,
"allocations" => 242_307,
"duration" => 178.2,
"view" => 78.36,
"db" => 0.0,
"params" => "",
"ip" => "127.0.0.1",
"username" => nil,
"@timestamp" => "2024-07-01T07:51:11.283Z",
"@version" => "1",
}.to_json,
)
end
it "accepts an error object as the message" do
logger = described_class.logger(logdev: output, type: "test")
logger.add(Logger::ERROR, StandardError.new("error message"))
output.rewind
parsed = JSON.parse(output.read.chomp)
expect(parsed["message"]).to eq("error message")
end
it "logs a JSON string with the `exception_class` and `exception_message` fields when `progname` is `web-exception`" do
logger = described_class.logger(logdev: output, type: "test")
logger.add(Logger::ERROR, "StandardError (some error message)\ntest", "web-exception")
output.rewind
parsed = JSON.parse(output.read.chomp)
expect(parsed["exception.class"]).to eq("StandardError")
expect(parsed["exception.message"]).to eq("some error message")
end
it "logs a JSON string with the right fields when `customize_event` attribute is set" do
logger =
described_class.logger(
logdev: output,
type: "test",
customize_event: ->(event) { event["custom"] = "custom" },
)
logger.add(Logger::INFO, lograge_logstash_formatter_formatted_message)
output.rewind
parsed = JSON.parse(output.read.chomp)
expect(parsed["custom"]).to eq("custom")
end
it "does not log a JSON string with the `backtrace` field when severity is less than `Logger::WARN`" do
logger.add(
Logger::INFO,
lograge_logstash_formatter_formatted_message,
nil,
backtrace: "backtrace",
)
output.rewind
parsed = JSON.parse(output.read.chomp)
expect(parsed).not_to have_key("backtrace")
end
it "logs a JSON string with the `backtrace` field when severity is at least `Logger::WARN`" do
logger.add(
Logger::ERROR,
lograge_logstash_formatter_formatted_message,
nil,
backtrace: "backtrace",
)
output.rewind
parsed = JSON.parse(output.read.chomp)
expect(parsed["backtrace"]).to eq("backtrace")
end
described_class::ALLOWED_HEADERS_FROM_ENV.each do |header|
it "does not include `#{header}` from `env` keyword argument in the logged JSON string when severity is less than `Logger::WARN`" do
logger.add(
Logger::INFO,
lograge_logstash_formatter_formatted_message,
nil,
env: {
header => "header",
},
)
output.rewind
parsed = JSON.parse(output.read.chomp)
expect(parsed).not_to have_key("request.headers.#{header.downcase}")
end
it "includes `#{header}` from `env` keyword argument in the logged JSON string when severity is at least `Logger::WARN`" do
logger.add(
Logger::ERROR,
lograge_logstash_formatter_formatted_message,
nil,
env: {
header => "header",
},
)
output.rewind
parsed = JSON.parse(output.read.chomp)
expect(parsed["request.headers.#{header.downcase}"]).to eq("header")
end
end
it "does not include keys from `env` keyword argument in the logged JSOn string which are not in the allow list" do
logger.add(
Logger::ERROR,
lograge_logstash_formatter_formatted_message,
nil,
env: {
"SOME_RANDOM_HEADER" => "header",
},
)
output.rewind
parsed = JSON.parse(output.read.chomp)
expect(parsed).not_to have_key("request.headers.some_random_header")
end
end
end