diff --git a/NEWS.md b/NEWS.md
index 76896ab2bad24..053ed9e711ecb 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -206,6 +206,9 @@ Standard library changes
   function is provided to reproduce the mapping used in identifier normalization
   by the Julia parser ([#42561]).
 
+#### Test
+* `TestLogger` and `LogRecord` are now exported from the Test stdlib.  ([#44080])
+
 
 Deprecated or removed
 ---------------------
diff --git a/stdlib/Test/docs/src/index.md b/stdlib/Test/docs/src/index.md
index 0409c33a3fabf..077d350554775 100644
--- a/stdlib/Test/docs/src/index.md
+++ b/stdlib/Test/docs/src/index.md
@@ -200,6 +200,16 @@ Foo Tests     |    3     1      4  0.0s
 ERROR: Some tests did not pass: 3 passed, 1 failed, 0 errored, 0 broken.
 ```
 
+## Testing Log Statements
+
+One can use the [`@test_logs`](@ref) macro to test log statements, or use a [`TestLogger`](@ref).
+
+```@docs
+Test.@test_logs
+Test.TestLogger
+Test.LogRecord
+```
+
 ## Other Test Macros
 
 As calculations on floating-point values can be imprecise, you can perform approximate equality
@@ -226,7 +236,6 @@ Note that this is not a specific feature of the `≈` but rather a general featu
 
 ```@docs
 Test.@inferred
-Test.@test_logs
 Test.@test_deprecated
 Test.@test_warn
 Test.@test_nowarn
diff --git a/stdlib/Test/src/Test.jl b/stdlib/Test/src/Test.jl
index bd281e41b7ccd..bd5f9d3fbba5a 100644
--- a/stdlib/Test/src/Test.jl
+++ b/stdlib/Test/src/Test.jl
@@ -22,6 +22,7 @@ export @inferred
 export detect_ambiguities, detect_unbound_args
 export GenericString, GenericSet, GenericDict, GenericArray, GenericOrder
 export TestSetException
+export TestLogger, LogRecord
 
 using Random
 using Random: AbstractRNG, default_rng
diff --git a/stdlib/Test/src/logging.jl b/stdlib/Test/src/logging.jl
index b8e4d00e33b5b..d7146b121d47d 100644
--- a/stdlib/Test/src/logging.jl
+++ b/stdlib/Test/src/logging.jl
@@ -4,7 +4,20 @@ using Logging: Logging, AbstractLogger, LogLevel, Info, with_logger
 import Base: occursin
 
 #-------------------------------------------------------------------------------
-# Log records
+"""
+    LogRecord
+
+Stores the results of a single log event. Fields:
+
+* `level`: the [`LogLevel`](@ref) of the log message
+* `message`: the textual content of the log message
+* `_module`: the module of the log event
+* `group`: the logging group (by default, the name of the file containing the log event)
+* `id`: the ID of the log event
+* `file`: the file containing the log event
+* `line`: the line within the file of the log event
+* `kwargs`: any keyword arguments passed to the log event
+"""
 struct LogRecord
     level
     message
@@ -30,6 +43,42 @@ mutable struct TestLogger <: AbstractLogger
     respect_maxlog::Bool
 end
 
+"""
+    TestLogger(; min_level=Info, catch_exceptions=false)
+
+Create a `TestLogger` which captures logged messages in its `logs::Vector{LogRecord}` field.
+
+Set `min_level` to control the `LogLevel`, `catch_exceptions` for whether or not exceptions
+thrown as part of log event generation should be caught, and `respect_maxlog` for whether
+or not to follow the convention of logging messages with `maxlog=n` for some integer `n` at
+most `n` times.
+
+See also: [`LogRecord`](@ref).
+
+## Example
+
+```jldoctest
+julia> using Test, Logging
+
+julia> f() = @info "Hi" number=5;
+
+julia> test_logger = TestLogger();
+
+julia> with_logger(test_logger) do
+           f()
+           @info "Bye!"
+       end
+
+julia> @test test_logger.logs[1].message == "Hi"
+Test Passed
+
+julia> @test test_logger.logs[1].kwargs[:number] == 5
+Test Passed
+
+julia> @test test_logger.logs[2].message == "Bye!"
+Test Passed
+```
+"""
 TestLogger(; min_level=Info, catch_exceptions=false, respect_maxlog=true) =
     TestLogger(LogRecord[], min_level, catch_exceptions, nothing, Dict{Any, Int}(), respect_maxlog)
 Logging.min_enabled_level(logger::TestLogger) = logger.min_level