Release the Abseil Logging library

PiperOrigin-RevId: 470080638
Change-Id: I8d9ddfabc7704c383ed5a73abf0411f4c58a4bf7
diff --git a/absl/CMakeLists.txt b/absl/CMakeLists.txt
index b171584..925be19 100644
--- a/absl/CMakeLists.txt
+++ b/absl/CMakeLists.txt
@@ -22,6 +22,7 @@
 add_subdirectory(flags)
 add_subdirectory(functional)
 add_subdirectory(hash)
+add_subdirectory(log)
 add_subdirectory(memory)
 add_subdirectory(meta)
 add_subdirectory(numeric)
diff --git a/absl/flags/BUILD.bazel b/absl/flags/BUILD.bazel
index 4ca687e..935d853 100644
--- a/absl/flags/BUILD.bazel
+++ b/absl/flags/BUILD.bazel
@@ -53,6 +53,7 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     visibility = [
         "//absl/flags:__pkg__",
+        "//absl/log:__pkg__",
     ],
     deps = [
         ":path_util",
diff --git a/absl/log/BUILD.bazel b/absl/log/BUILD.bazel
new file mode 100644
index 0000000..2a643c7
--- /dev/null
+++ b/absl/log/BUILD.bazel
@@ -0,0 +1,476 @@
+#
+# Copyright 2022 The Abseil Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+load(
+    "//absl:copts/configure_copts.bzl",
+    "ABSL_DEFAULT_COPTS",
+    "ABSL_DEFAULT_LINKOPTS",
+    "ABSL_TEST_COPTS",
+)
+
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"])
+
+# Public targets
+cc_library(
+    name = "check",
+    hdrs = ["check.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        "//absl/base:core_headers",
+        "//absl/log/internal:check_op",
+        "//absl/log/internal:conditions",
+        "//absl/log/internal:log_message",
+        "//absl/log/internal:strip",
+    ],
+)
+
+cc_library(
+    name = "die_if_null",
+    srcs = ["die_if_null.cc"],
+    hdrs = ["die_if_null.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":log",
+        "//absl/base:config",
+        "//absl/base:core_headers",
+        "//absl/strings",
+    ],
+)
+
+cc_library(
+    name = "flags",
+    srcs = ["flags.cc"],
+    hdrs = ["flags.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    visibility = ["//visibility:public"],
+    deps = [
+        ":globals",
+        "//absl/base:config",
+        "//absl/base:core_headers",
+        "//absl/base:log_severity",
+        "//absl/flags:flag",
+        "//absl/flags:marshalling",
+        "//absl/log/internal:config",
+        "//absl/log/internal:flags",
+        "//absl/strings",
+    ],
+    # Binaries which do not access these flags from C++ still want this library linked in.
+    alwayslink = True,
+)
+
+cc_library(
+    name = "globals",
+    srcs = ["globals.cc"],
+    hdrs = ["globals.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    visibility = ["//visibility:public"],
+    deps = [
+        "//absl/base:atomic_hook",
+        "//absl/base:config",
+        "//absl/base:core_headers",
+        "//absl/base:log_severity",
+        "//absl/hash",
+        "//absl/strings",
+    ],
+)
+
+cc_library(
+    name = "initialize",
+    srcs = ["initialize.cc"],
+    hdrs = ["initialize.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    visibility = ["//visibility:public"],
+    deps = [
+        ":globals",
+        "//absl/base:config",
+        "//absl/log/internal:globals",
+        "//absl/time",
+    ],
+)
+
+cc_library(
+    name = "log",
+    hdrs = ["log.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        "//absl/log/internal:conditions",
+        "//absl/log/internal:log_message",
+        "//absl/log/internal:strip",
+    ],
+)
+
+cc_library(
+    name = "log_entry",
+    srcs = ["log_entry.cc"],
+    hdrs = ["log_entry.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        "//absl/base:config",
+        "//absl/base:log_severity",
+        "//absl/log/internal:config",
+        "//absl/strings",
+        "//absl/time",
+        "//absl/types:span",
+    ],
+)
+
+cc_library(
+    name = "log_sink",
+    srcs = ["log_sink.cc"],
+    hdrs = ["log_sink.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":log_entry",
+        "//absl/base:config",
+    ],
+)
+
+cc_library(
+    name = "log_sink_registry",
+    hdrs = ["log_sink_registry.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":log_sink",
+        "//absl/base:config",
+        "//absl/log/internal:log_sink_set",
+    ],
+)
+
+cc_library(
+    name = "log_streamer",
+    hdrs = ["log_streamer.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":log",
+        "//absl/base:config",
+        "//absl/base:log_severity",
+        "//absl/memory",
+        "//absl/strings",
+        "//absl/strings:internal",
+    ],
+)
+
+cc_library(
+    name = "scoped_mock_log",
+    testonly = True,
+    srcs = ["scoped_mock_log.cc"],
+    hdrs = ["scoped_mock_log.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":log_entry",
+        ":log_sink",
+        ":log_sink_registry",
+        "//absl/base:config",
+        "//absl/base:log_severity",
+        "//absl/base:raw_logging_internal",
+        "//absl/strings",
+        "@com_google_googletest//:gtest",
+    ],
+)
+
+# Test targets
+cc_test(
+    name = "basic_log_test",
+    size = "small",
+    srcs = ["basic_log_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":globals",
+        ":log",
+        ":log_entry",
+        ":scoped_mock_log",
+        "//absl/base",
+        "//absl/base:log_severity",
+        "//absl/log/internal:test_actions",
+        "//absl/log/internal:test_helpers",
+        "//absl/log/internal:test_matchers",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "check_test",
+    size = "small",
+    srcs = ["check_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    tags = [
+        "no_test_ios",
+        "no_test_wasm",
+    ],
+    deps = [
+        ":check",
+        "//absl/base:config",
+        "//absl/base:core_headers",
+        "//absl/log/internal:test_helpers",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "die_if_null_test",
+    size = "small",
+    srcs = ["die_if_null_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":die_if_null",
+        "//absl/base:core_headers",
+        "//absl/log/internal:test_helpers",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "flags_test",
+    size = "small",
+    srcs = ["flags_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":flags",
+        ":globals",
+        ":log",
+        ":scoped_mock_log",
+        "//absl/base:core_headers",
+        "//absl/base:log_severity",
+        "//absl/flags:flag",
+        "//absl/flags:reflection",
+        "//absl/log/internal:flags",
+        "//absl/log/internal:test_helpers",
+        "//absl/log/internal:test_matchers",
+        "//absl/strings",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "globals_test",
+    size = "small",
+    srcs = ["globals_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":globals",
+        ":log",
+        ":scoped_mock_log",
+        "//absl/base:core_headers",
+        "//absl/base:log_severity",
+        "//absl/log/internal:globals",
+        "//absl/log/internal:test_helpers",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "log_entry_test",
+    size = "small",
+    srcs = ["log_entry_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":log_entry",
+        "//absl/base:config",
+        "//absl/base:core_headers",
+        "//absl/base:log_severity",
+        "//absl/log/internal:format",
+        "//absl/log/internal:test_helpers",
+        "//absl/strings",
+        "//absl/time",
+        "//absl/types:span",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "log_format_test",
+    size = "small",
+    srcs = ["log_format_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":log",
+        ":scoped_mock_log",
+        "//absl/log/internal:config",
+        "//absl/log/internal:test_matchers",
+        "//absl/strings",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "log_macro_hygiene_test",
+    size = "small",
+    srcs = ["log_macro_hygiene_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":log",
+        ":scoped_mock_log",
+        "//absl/base:core_headers",
+        "//absl/base:log_severity",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "log_sink_test",
+    size = "medium",
+    srcs = ["log_sink_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    tags = [
+        "no_test_ios",
+        "no_test_wasm",
+    ],
+    deps = [
+        ":log",
+        ":log_sink",
+        ":log_sink_registry",
+        ":scoped_mock_log",
+        "//absl/base:core_headers",
+        "//absl/base:raw_logging_internal",
+        "//absl/log/internal:test_actions",
+        "//absl/log/internal:test_helpers",
+        "//absl/log/internal:test_matchers",
+        "//absl/strings",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "log_streamer_test",
+    size = "medium",
+    srcs = ["log_streamer_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":log",
+        ":log_streamer",
+        ":scoped_mock_log",
+        "//absl/base",
+        "//absl/base:core_headers",
+        "//absl/base:log_severity",
+        "//absl/log/internal:test_actions",
+        "//absl/log/internal:test_helpers",
+        "//absl/log/internal:test_matchers",
+        "//absl/strings",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "log_modifier_methods_test",
+    size = "small",
+    srcs = ["log_modifier_methods_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":log",
+        ":log_sink",
+        ":scoped_mock_log",
+        "//absl/log/internal:test_actions",
+        "//absl/log/internal:test_helpers",
+        "//absl/log/internal:test_matchers",
+        "//absl/strings",
+        "//absl/time",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "scoped_mock_log_test",
+    size = "small",
+    srcs = ["scoped_mock_log_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    linkstatic = 1,
+    tags = [
+        "no_test_ios",
+        "no_test_wasm",
+    ],
+    deps = [
+        ":globals",
+        ":log",
+        ":scoped_mock_log",
+        "//absl/base:core_headers",
+        "//absl/base:log_severity",
+        "//absl/log/internal:test_helpers",
+        "//absl/log/internal:test_matchers",
+        "//absl/memory",
+        "//absl/strings",
+        "//absl/synchronization",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "stripping_test",
+    size = "small",
+    srcs = ["stripping_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    # This test requires all code live in the binary (instead of shared libraries)
+    # because we test for the existence of specific literals in the binary.
+    linkstatic = 1,
+    deps = [
+        ":check",
+        ":log",
+        "//absl/base:strerror",
+        "//absl/flags:program_name",
+        "//absl/log/internal:test_helpers",
+        "//absl/strings",
+        "//absl/strings:str_format",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_binary(
+    name = "log_benchmark",
+    testonly = 1,
+    srcs = ["log_benchmark.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    tags = ["benchmark"],
+    deps = [
+        ":check",
+        ":flags",
+        ":globals",
+        ":log",
+        ":log_entry",
+        ":log_sink",
+        ":log_sink_registry",
+        "//absl/base:core_headers",
+        "//absl/base:log_severity",
+        "//absl/flags:flag",
+        "//absl/log/internal:flags",
+        "@com_github_google_benchmark//:benchmark_main",
+    ],
+)
diff --git a/absl/log/CMakeLists.txt b/absl/log/CMakeLists.txt
new file mode 100644
index 0000000..a96e519
--- /dev/null
+++ b/absl/log/CMakeLists.txt
@@ -0,0 +1,836 @@
+#
+# Copyright 2022 The Abseil Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Internal targets
+absl_cc_library(
+  NAME
+    log_internal_check_op
+  SRCS
+    "internal/check_op.cc"
+  HDRS
+    "internal/check_op.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::config
+    absl::core_headers
+    absl::log_internal_nullguard
+    absl::log_internal_nullstream
+    absl::log_internal_strip
+    absl::strings
+)
+
+absl_cc_library(
+  NAME
+    log_internal_conditions
+  SRCS
+    "internal/conditions.cc"
+  HDRS
+    "internal/conditions.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::base
+    absl::config
+    absl::core_headers
+    absl::log_internal_voidify
+)
+
+absl_cc_library(
+  NAME
+    log_internal_config
+  SRCS
+  HDRS
+    "internal/config.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::config
+    absl::core_headers
+)
+
+absl_cc_library(
+  NAME
+    log_internal_flags
+  SRCS
+  HDRS
+    "internal/flags.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::flags
+)
+
+absl_cc_library(
+  NAME
+    log_internal_format
+  SRCS
+    "internal/log_format.cc"
+  HDRS
+    "internal/log_format.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::config
+    absl::core_headers
+    absl::log_internal_config
+    absl::log_internal_globals
+    absl::log_severity
+    absl::strings
+    absl::str_format
+    absl::time
+    absl::span
+)
+
+absl_cc_library(
+  NAME
+    log_internal_globals
+  SRCS
+    "internal/globals.cc"
+  HDRS
+    "internal/globals.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::config
+    absl::core_headers
+    absl::log_severity
+    absl::raw_logging_internal
+    absl::strings
+    absl::time
+)
+
+absl_cc_library(
+  NAME
+    log_internal_message
+  SRCS
+    "internal/log_message.cc"
+  HDRS
+    "internal/log_message.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::base
+    absl::config
+    absl::core_headers
+    absl::errno_saver
+    absl::inlined_vector
+    absl::examine_stack
+    absl::log_internal_config
+    absl::log_internal_format
+    absl::log_internal_globals
+    absl::log_internal_log_sink_set
+    absl::log_internal_nullguard
+    absl::log_globals
+    absl::log_entry
+    absl::log_severity
+    absl::log_sink
+    absl::log_sink_registry
+    absl::memory
+    absl::raw_logging_internal
+    absl::strings
+    absl::strerror
+    absl::str_format
+    absl::time
+    absl::span
+)
+
+absl_cc_library(
+  NAME
+    log_internal_log_sink_set
+  SRCS
+    "internal/log_sink_set.cc"
+  HDRS
+    "internal/log_sink_set.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::base
+    absl::cleanup
+    absl::config
+    absl::core_headers
+    absl::log_internal_config
+    absl::log_internal_globals
+    absl::log_globals
+    absl::log_entry
+    absl::log_severity
+    absl::log_sink
+    absl::raw_logging_internal
+    absl::synchronization
+    absl::span
+    absl::strings
+)
+
+absl_cc_library(
+  NAME
+    log_internal_nullguard
+  SRCS
+  HDRS
+    "internal/nullguard.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::config
+)
+
+absl_cc_library(
+  NAME
+    log_internal_nullstream
+  SRCS
+  HDRS
+    "internal/nullstream.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::config
+    absl::core_headers
+    absl::log_severity
+    absl::strings
+)
+
+absl_cc_library(
+  NAME
+    log_internal_strip
+  SRCS
+  HDRS
+    "internal/strip.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::log_internal_message
+    absl::log_internal_nullstream
+    absl::log_severity
+)
+
+absl_cc_library(
+  NAME
+    log_internal_test_actions
+  SRCS
+    "internal/test_actions.cc"
+  HDRS
+    "internal/test_actions.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::config
+    absl::log_entry
+    absl::log_internal_config
+    absl::log_severity
+    absl::strings
+    absl::time
+  TESTONLY
+)
+
+absl_cc_library(
+  NAME
+    log_internal_test_helpers
+  SRCS
+    "internal/test_helpers.cc"
+  HDRS
+    "internal/test_helpers.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::config
+    absl::log_globals
+    absl::log_initialize
+    absl::log_internal_globals
+    absl::log_severity
+    GTest::gtest
+  TESTONLY
+)
+
+absl_cc_library(
+  NAME
+    log_internal_test_matchers
+  SRCS
+    "internal/test_matchers.cc"
+  HDRS
+    "internal/test_matchers.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::config
+    absl::log_entry
+    absl::log_internal_config
+    absl::log_internal_test_helpers
+    absl::log_severity
+    absl::strings
+    absl::time
+    GTest::gtest
+    GTest::gmock
+  TESTONLY
+)
+
+absl_cc_library(
+  NAME
+    log_internal_voidify
+  SRCS
+  HDRS
+    "internal/voidify.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::config
+)
+
+# Public targets
+absl_cc_library(
+  NAME
+    check
+  SRCS
+  HDRS
+    "check.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::core_headers
+    absl::log_internal_check_op
+    absl::log_internal_conditions
+    absl::log_internal_message
+    absl::log_internal_strip
+  PUBLIC
+)
+
+absl_cc_library(
+  NAME
+    die_if_null
+  SRCS
+    "die_if_null.cc"
+  HDRS
+    "die_if_null.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::config
+    absl::core_headers
+    absl::log
+    absl::strings
+  PUBLIC
+)
+
+absl_cc_library(
+  NAME
+    log_flags
+  SRCS
+    "flags.cc"
+  HDRS
+    "flags.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::config
+    absl::core_headers
+    absl::log_globals
+    absl::log_severity
+    absl::log_internal_config
+    absl::log_internal_flags
+    absl::flags
+    absl::flags_marshalling
+    absl::strings
+  PUBLIC
+)
+
+absl_cc_library(
+  NAME
+    log_globals
+  SRCS
+    "globals.cc"
+  HDRS
+    "globals.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::atomic_hook
+    absl::config
+    absl::core_headers
+    absl::hash
+    absl::log_severity
+    absl::strings
+)
+
+absl_cc_library(
+  NAME
+    log_initialize
+  SRCS
+    "initialize.cc"
+  HDRS
+    "initialize.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::config
+    absl::log_globals
+    absl::log_internal_globals
+    absl::time
+  PUBLIC
+)
+
+absl_cc_library(
+  NAME
+    log
+  SRCS
+  HDRS
+    "log.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::log_internal_conditions
+    absl::log_internal_message
+    absl::log_internal_strip
+  PUBLIC
+)
+
+absl_cc_library(
+  NAME
+    log_entry
+  SRCS
+    "log_entry.cc"
+  HDRS
+    "log_entry.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::config
+    absl::log_internal_config
+    absl::log_severity
+    absl::span
+    absl::strings
+    absl::time
+  PUBLIC
+)
+
+absl_cc_library(
+  NAME
+    log_sink
+  SRCS
+    "log_sink.cc"
+  HDRS
+    "log_sink.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::config
+    absl::log_entry
+  PUBLIC
+)
+
+absl_cc_library(
+  NAME
+    log_sink_registry
+  SRCS
+  HDRS
+    "log_sink_registry.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::config
+    absl::log_sink
+    absl::log_internal_log_sink_set
+  PUBLIC
+)
+
+absl_cc_library(
+  NAME
+    log_streamer
+  SRCS
+  HDRS
+    "log_streamer.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::config
+    absl::log
+    absl::log_severity
+    absl::memory
+    absl::strings
+    absl::strings_internal
+  PUBLIC
+)
+
+absl_cc_library(
+  NAME
+    scoped_mock_log
+  SRCS
+    "scoped_mock_log.cc"
+  HDRS
+    "scoped_mock_log.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::config
+    absl::log_entry
+    absl::log_severity
+    absl::log_sink
+    absl::log_sink_registry
+    absl::raw_logging_internal
+    absl::strings
+    GTest::gmock
+    GTest::gtest
+  PUBLIC
+  TESTONLY
+)
+
+# Test targets
+absl_cc_test(
+  NAME
+    basic_log_test
+  SRCS
+    "basic_log_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::base
+    absl::log
+    absl::log_entry
+    absl::log_globals
+    absl::log_severity
+    absl::log_internal_test_actions
+    absl::log_internal_test_helpers
+    absl::log_internal_test_matchers
+    absl::scoped_mock_log
+    GTest::gmock
+    GTest::gtest_main
+)
+
+absl_cc_test(
+  NAME
+    check_test
+  SRCS
+    "check_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::check
+    absl::config
+    absl::core_headers
+    absl::log_internal_test_helpers
+    GTest::gmock
+    GTest::gtest_main
+)
+
+absl_cc_test(
+  NAME
+    die_if_null_test
+  SRCS
+    "die_if_null_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::core_headers
+    absl::die_if_null
+    absl::log_internal_test_helpers
+    GTest::gtest_main
+)
+
+absl_cc_test(
+  NAME
+    log_flags_test
+  SRCS
+    "flags_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::core_headers
+    absl::log
+    absl::log_flags
+    absl::log_globals
+    absl::log_internal_flags
+    absl::log_internal_test_helpers
+    absl::log_internal_test_matchers
+    absl::log_severity
+    absl::flags
+    absl::flags_reflection
+    absl::scoped_mock_log
+    absl::strings
+    GTest::gmock
+    GTest::gtest_main
+)
+
+absl_cc_test(
+  NAME
+    log_entry_test
+  SRCS
+    "log_entry_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::config
+    absl::core_headers
+    absl::log_entry
+    absl::log_internal_format
+    absl::log_internal_globals
+    absl::log_internal_test_helpers
+    absl::log_severity
+    absl::span
+    absl::strings
+    absl::time
+    GTest::gmock
+    GTest::gtest_main
+)
+
+absl_cc_test(
+  NAME
+    log_globals_test
+  SRCS
+    "globals_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::core_headers
+    absl::log
+    absl::log_globals
+    absl::log_internal_globals
+    absl::log_internal_test_helpers
+    absl::log_severity
+    absl::scoped_mock_log
+    GTest::gtest_main
+)
+
+absl_cc_test(
+  NAME
+    log_format_test
+  SRCS
+    "log_format_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::log
+    absl::log_internal_config
+    absl::log_internal_test_matchers
+    absl::scoped_mock_log
+    absl::strings
+    GTest::gmock
+    GTest::gtest_main
+)
+
+absl_cc_test(
+  NAME
+    log_macro_hygiene_test
+  SRCS
+    "log_macro_hygiene_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::core_headers
+    absl::log
+    absl::log_severity
+    absl::scoped_mock_log
+    GTest::gmock
+    GTest::gtest_main
+)
+
+absl_cc_test(
+  NAME
+    log_sink_test
+  SRCS
+    "log_sink_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::core_headers
+    absl::log
+    absl::log_internal_test_actions
+    absl::log_internal_test_helpers
+    absl::log_internal_test_matchers
+    absl::log_sink
+    absl::log_sink_registry
+    absl::log_severity
+    absl::raw_logging_internal
+    absl::scoped_mock_log
+    absl::strings
+    GTest::gtest_main
+)
+
+absl_cc_test(
+  NAME
+    log_streamer_test
+  SRCS
+    "log_streamer_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::base
+    absl::core_headers
+    absl::log
+    absl::log_internal_test_actions
+    absl::log_internal_test_helpers
+    absl::log_internal_test_matchers
+    absl::log_streamer
+    absl::log_severity
+    absl::scoped_mock_log
+    absl::strings
+    GTest::gtest_main
+)
+
+absl_cc_test(
+  NAME
+    log_modifier_methods_test
+  SRCS
+    "log_modifier_methods_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::log
+    absl::log_internal_test_actions
+    absl::log_internal_test_helpers
+    absl::log_internal_test_matchers
+    absl::log_sink
+    absl::scoped_mock_log
+    absl::strings
+    absl::time
+    GTest::gmock
+    GTest::gtest_main
+)
+
+absl_cc_test(
+  NAME
+    scoped_mock_log_test
+  SRCS
+    "scoped_mock_log_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::core_headers
+    absl::log
+    absl::log_globals
+    absl::log_internal_globals
+    absl::log_internal_test_helpers
+    absl::log_internal_test_matchers
+    absl::log_severity
+    absl::memory
+    absl::scoped_mock_log
+    absl::strings
+    absl::synchronization
+    GTest::gmock
+    GTest::gtest_main
+)
+
+absl_cc_test(
+  NAME
+    log_internal_stderr_log_sink_test
+  SRCS
+    "internal/stderr_log_sink_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::core_headers
+    absl::log
+    absl::log_globals
+    absl::log_internal_test_helpers
+    absl::log_severity
+    GTest::gmock
+    GTest::gtest_main
+)
+
+absl_cc_test(
+  NAME
+    log_stripping_test
+  SRCS
+    "stripping_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::check
+    absl::flags_program_name
+    absl::log
+    absl::log_internal_test_helpers
+    absl::strerror
+    absl::strings
+    absl::str_format
+    GTest::gmock
+    GTest::gtest_main
+)
diff --git a/absl/log/basic_log_test.cc b/absl/log/basic_log_test.cc
new file mode 100644
index 0000000..bc40f0d
--- /dev/null
+++ b/absl/log/basic_log_test.cc
@@ -0,0 +1,440 @@
+//
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// The testcases in this file are expected to pass or be skipped with any value
+// of ABSL_MIN_LOG_LEVEL
+
+#include <cerrno>
+#include <sstream>
+#include <string>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/internal/sysinfo.h"
+#include "absl/base/log_severity.h"
+#include "absl/log/globals.h"
+#include "absl/log/internal/test_actions.h"
+#include "absl/log/internal/test_helpers.h"
+#include "absl/log/internal/test_matchers.h"
+#include "absl/log/log.h"
+#include "absl/log/log_entry.h"
+#include "absl/log/scoped_mock_log.h"
+
+namespace {
+#if GTEST_HAS_DEATH_TEST
+using ::absl::log_internal::DeathTestExpectedLogging;
+using ::absl::log_internal::DeathTestUnexpectedLogging;
+using ::absl::log_internal::DeathTestValidateExpectations;
+using ::absl::log_internal::DiedOfFatal;
+using ::absl::log_internal::DiedOfQFatal;
+#endif
+using ::absl::log_internal::LoggingEnabledAt;
+using ::absl::log_internal::LogSeverity;
+using ::absl::log_internal::Prefix;
+using ::absl::log_internal::SourceBasename;
+using ::absl::log_internal::SourceFilename;
+using ::absl::log_internal::SourceLine;
+using ::absl::log_internal::Stacktrace;
+using ::absl::log_internal::TextMessage;
+using ::absl::log_internal::ThreadID;
+using ::absl::log_internal::TimestampInMatchWindow;
+using ::absl::log_internal::Verbosity;
+using ::testing::AnyNumber;
+using ::testing::Eq;
+using ::testing::IsEmpty;
+using ::testing::IsTrue;
+
+class BasicLogTest : public testing::TestWithParam<absl::LogSeverityAtLeast> {};
+
+std::string ThresholdName(
+    testing::TestParamInfo<absl::LogSeverityAtLeast> severity) {
+  std::stringstream ostr;
+  ostr << severity.param;
+  return ostr.str().substr(
+      severity.param == absl::LogSeverityAtLeast::kInfinity ? 0 : 2);
+}
+
+INSTANTIATE_TEST_SUITE_P(WithParam, BasicLogTest,
+                         testing::Values(absl::LogSeverityAtLeast::kInfo,
+                                         absl::LogSeverityAtLeast::kWarning,
+                                         absl::LogSeverityAtLeast::kError,
+                                         absl::LogSeverityAtLeast::kFatal,
+                                         absl::LogSeverityAtLeast::kInfinity),
+                         ThresholdName);
+
+TEST_P(BasicLogTest, Info) {
+  absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());
+
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const int log_line = __LINE__ + 1;
+  auto do_log = [] { LOG(INFO) << "hello world"; };
+
+  if (LoggingEnabledAt(absl::LogSeverity::kInfo)) {
+    EXPECT_CALL(
+        test_sink,
+        Send(AllOf(SourceFilename(Eq(__FILE__)),
+                   SourceBasename(Eq("basic_log_test.cc")),
+                   SourceLine(Eq(log_line)), Prefix(IsTrue()),
+                   LogSeverity(Eq(absl::LogSeverity::kInfo)),
+                   TimestampInMatchWindow(),
+                   ThreadID(Eq(absl::base_internal::GetTID())),
+                   TextMessage(Eq("hello world")),
+                   Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),
+                   ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                      literal: "hello world"
+                                                    })pb")),
+                   Stacktrace(IsEmpty()))));
+  }
+
+  test_sink.StartCapturingLogs();
+  do_log();
+}
+
+TEST_P(BasicLogTest, Warning) {
+  absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());
+
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const int log_line = __LINE__ + 1;
+  auto do_log = [] { LOG(WARNING) << "hello world"; };
+
+  if (LoggingEnabledAt(absl::LogSeverity::kWarning)) {
+    EXPECT_CALL(
+        test_sink,
+        Send(AllOf(SourceFilename(Eq(__FILE__)),
+                   SourceBasename(Eq("basic_log_test.cc")),
+                   SourceLine(Eq(log_line)), Prefix(IsTrue()),
+                   LogSeverity(Eq(absl::LogSeverity::kWarning)),
+                   TimestampInMatchWindow(),
+                   ThreadID(Eq(absl::base_internal::GetTID())),
+                   TextMessage(Eq("hello world")),
+                   Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),
+                   ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                      literal: "hello world"
+                                                    })pb")),
+                   Stacktrace(IsEmpty()))));
+  }
+
+  test_sink.StartCapturingLogs();
+  do_log();
+}
+
+TEST_P(BasicLogTest, Error) {
+  absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());
+
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const int log_line = __LINE__ + 1;
+  auto do_log = [] { LOG(ERROR) << "hello world"; };
+
+  if (LoggingEnabledAt(absl::LogSeverity::kError)) {
+    EXPECT_CALL(
+        test_sink,
+        Send(AllOf(SourceFilename(Eq(__FILE__)),
+                   SourceBasename(Eq("basic_log_test.cc")),
+                   SourceLine(Eq(log_line)), Prefix(IsTrue()),
+                   LogSeverity(Eq(absl::LogSeverity::kError)),
+                   TimestampInMatchWindow(),
+                   ThreadID(Eq(absl::base_internal::GetTID())),
+                   TextMessage(Eq("hello world")),
+                   Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),
+                   ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                      literal: "hello world"
+                                                    })pb")),
+                   Stacktrace(IsEmpty()))));
+  }
+
+  test_sink.StartCapturingLogs();
+  do_log();
+}
+
+#if GTEST_HAS_DEATH_TEST
+using BasicLogDeathTest = BasicLogTest;
+
+INSTANTIATE_TEST_SUITE_P(WithParam, BasicLogDeathTest,
+                         testing::Values(absl::LogSeverityAtLeast::kInfo,
+                                         absl::LogSeverityAtLeast::kFatal,
+                                         absl::LogSeverityAtLeast::kInfinity),
+                         ThresholdName);
+
+TEST_P(BasicLogDeathTest, Fatal) {
+  absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());
+
+  const int log_line = __LINE__ + 1;
+  auto do_log = [] { LOG(FATAL) << "hello world"; };
+
+  EXPECT_EXIT(
+      {
+        absl::ScopedMockLog test_sink(
+            absl::MockLogDefault::kDisallowUnexpected);
+
+        EXPECT_CALL(test_sink, Send)
+            .Times(AnyNumber())
+            .WillRepeatedly(DeathTestUnexpectedLogging());
+
+        ::testing::InSequence s;
+
+        // Note the logic in DeathTestValidateExpectations() caters for the case
+        // of logging being disabled at FATAL level.
+
+        if (LoggingEnabledAt(absl::LogSeverity::kFatal)) {
+          // The first call without the stack trace.
+          EXPECT_CALL(
+              test_sink,
+              Send(AllOf(SourceFilename(Eq(__FILE__)),
+                         SourceBasename(Eq("basic_log_test.cc")),
+                         SourceLine(Eq(log_line)), Prefix(IsTrue()),
+                         LogSeverity(Eq(absl::LogSeverity::kFatal)),
+                         TimestampInMatchWindow(),
+                         ThreadID(Eq(absl::base_internal::GetTID())),
+                         TextMessage(Eq("hello world")),
+                         Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),
+                         ENCODED_MESSAGE(EqualsProto(
+                             R"pb(value { literal: "hello world" })pb")),
+                         Stacktrace(IsEmpty()))))
+              .WillOnce(DeathTestExpectedLogging());
+
+          // The second call with the stack trace.
+          EXPECT_CALL(
+              test_sink,
+              Send(AllOf(SourceFilename(Eq(__FILE__)),
+                         SourceBasename(Eq("basic_log_test.cc")),
+                         SourceLine(Eq(log_line)), Prefix(IsTrue()),
+                         LogSeverity(Eq(absl::LogSeverity::kFatal)),
+                         TimestampInMatchWindow(),
+                         ThreadID(Eq(absl::base_internal::GetTID())),
+                         TextMessage(Eq("hello world")),
+                         Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),
+                         ENCODED_MESSAGE(EqualsProto(
+                             R"pb(value { literal: "hello world" })pb")),
+                         Stacktrace(Not(IsEmpty())))))
+              .WillOnce(DeathTestExpectedLogging());
+        }
+
+        test_sink.StartCapturingLogs();
+        do_log();
+      },
+      DiedOfFatal, DeathTestValidateExpectations());
+}
+
+TEST_P(BasicLogDeathTest, QFatal) {
+  absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());
+
+  const int log_line = __LINE__ + 1;
+  auto do_log = [] { LOG(QFATAL) << "hello world"; };
+
+  EXPECT_EXIT(
+      {
+        absl::ScopedMockLog test_sink(
+            absl::MockLogDefault::kDisallowUnexpected);
+
+        EXPECT_CALL(test_sink, Send)
+            .Times(AnyNumber())
+            .WillRepeatedly(DeathTestUnexpectedLogging());
+
+        if (LoggingEnabledAt(absl::LogSeverity::kFatal)) {
+          EXPECT_CALL(
+              test_sink,
+              Send(AllOf(SourceFilename(Eq(__FILE__)),
+                         SourceBasename(Eq("basic_log_test.cc")),
+                         SourceLine(Eq(log_line)), Prefix(IsTrue()),
+                         LogSeverity(Eq(absl::LogSeverity::kFatal)),
+                         TimestampInMatchWindow(),
+                         ThreadID(Eq(absl::base_internal::GetTID())),
+                         TextMessage(Eq("hello world")),
+                         Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),
+                         ENCODED_MESSAGE(EqualsProto(
+                             R"pb(value { literal: "hello world" })pb")),
+                         Stacktrace(IsEmpty()))))
+              .WillOnce(DeathTestExpectedLogging());
+        }
+
+        test_sink.StartCapturingLogs();
+        do_log();
+      },
+      DiedOfQFatal, DeathTestValidateExpectations());
+}
+#endif
+
+TEST_P(BasicLogTest, Level) {
+  absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());
+
+  for (auto severity : {absl::LogSeverity::kInfo, absl::LogSeverity::kWarning,
+                        absl::LogSeverity::kError}) {
+    absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+    const int log_line = __LINE__ + 1;
+    auto do_log = [severity] { LOG(LEVEL(severity)) << "hello world"; };
+
+    if (LoggingEnabledAt(severity)) {
+      EXPECT_CALL(
+          test_sink,
+          Send(AllOf(SourceFilename(Eq(__FILE__)),
+                     SourceBasename(Eq("basic_log_test.cc")),
+                     SourceLine(Eq(log_line)), Prefix(IsTrue()),
+                     LogSeverity(Eq(severity)), TimestampInMatchWindow(),
+                     ThreadID(Eq(absl::base_internal::GetTID())),
+                     TextMessage(Eq("hello world")),
+                     Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),
+                     ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                        literal: "hello world"
+                                                      })pb")),
+                     Stacktrace(IsEmpty()))));
+    }
+    test_sink.StartCapturingLogs();
+    do_log();
+  }
+}
+
+#if GTEST_HAS_DEATH_TEST
+TEST_P(BasicLogDeathTest, Level) {
+  // TODO(b/242568884): re-enable once bug is fixed.
+  // absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());
+
+  // Ensure that `severity` is not a compile-time constant to prove that
+  // `LOG(LEVEL(severity))` works regardless:
+  auto volatile severity = absl::LogSeverity::kFatal;
+
+  const int log_line = __LINE__ + 1;
+  auto do_log = [severity] { LOG(LEVEL(severity)) << "hello world"; };
+
+  EXPECT_EXIT(
+      {
+        absl::ScopedMockLog test_sink(
+            absl::MockLogDefault::kDisallowUnexpected);
+
+        EXPECT_CALL(test_sink, Send)
+            .Times(AnyNumber())
+            .WillRepeatedly(DeathTestUnexpectedLogging());
+
+        ::testing::InSequence s;
+
+        if (LoggingEnabledAt(absl::LogSeverity::kFatal)) {
+          EXPECT_CALL(
+              test_sink,
+              Send(AllOf(SourceFilename(Eq(__FILE__)),
+                         SourceBasename(Eq("basic_log_test.cc")),
+                         SourceLine(Eq(log_line)), Prefix(IsTrue()),
+                         LogSeverity(Eq(absl::LogSeverity::kFatal)),
+                         TimestampInMatchWindow(),
+                         ThreadID(Eq(absl::base_internal::GetTID())),
+                         TextMessage(Eq("hello world")),
+                         Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),
+                         ENCODED_MESSAGE(EqualsProto(
+                             R"pb(value { literal: "hello world" })pb")),
+                         Stacktrace(IsEmpty()))))
+              .WillOnce(DeathTestExpectedLogging());
+
+          EXPECT_CALL(
+              test_sink,
+              Send(AllOf(SourceFilename(Eq(__FILE__)),
+                         SourceBasename(Eq("basic_log_test.cc")),
+                         SourceLine(Eq(log_line)), Prefix(IsTrue()),
+                         LogSeverity(Eq(absl::LogSeverity::kFatal)),
+                         TimestampInMatchWindow(),
+                         ThreadID(Eq(absl::base_internal::GetTID())),
+                         TextMessage(Eq("hello world")),
+                         Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),
+                         ENCODED_MESSAGE(EqualsProto(
+                             R"pb(value { literal: "hello world" })pb")),
+                         Stacktrace(Not(IsEmpty())))))
+              .WillOnce(DeathTestExpectedLogging());
+        }
+
+        test_sink.StartCapturingLogs();
+        do_log();
+      },
+      DiedOfFatal, DeathTestValidateExpectations());
+}
+#endif
+
+TEST_P(BasicLogTest, LevelClampsNegativeValues) {
+  absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());
+
+  if (!LoggingEnabledAt(absl::LogSeverity::kInfo)) {
+    GTEST_SKIP() << "This test cases required INFO log to be enabled";
+    return;
+  }
+
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(test_sink, Send(LogSeverity(Eq(absl::LogSeverity::kInfo))));
+
+  test_sink.StartCapturingLogs();
+  LOG(LEVEL(-1)) << "hello world";
+}
+
+TEST_P(BasicLogTest, LevelClampsLargeValues) {
+  absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());
+
+  if (!LoggingEnabledAt(absl::LogSeverity::kError)) {
+    GTEST_SKIP() << "This test cases required ERROR log to be enabled";
+    return;
+  }
+
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(test_sink, Send(LogSeverity(Eq(absl::LogSeverity::kError))));
+
+  test_sink.StartCapturingLogs();
+  LOG(LEVEL(static_cast<int>(absl::LogSeverity::kFatal) + 1)) << "hello world";
+}
+
+TEST(ErrnoPreservationTest, InSeverityExpression) {
+  errno = 77;
+  int saved_errno;
+  LOG(LEVEL((saved_errno = errno, absl::LogSeverity::kInfo)));
+  EXPECT_THAT(saved_errno, Eq(77));
+}
+
+TEST(ErrnoPreservationTest, InStreamedExpression) {
+  if (!LoggingEnabledAt(absl::LogSeverity::kInfo)) {
+    GTEST_SKIP() << "This test cases required INFO log to be enabled";
+    return;
+  }
+
+  errno = 77;
+  int saved_errno = 0;
+  LOG(INFO) << (saved_errno = errno, "hello world");
+  EXPECT_THAT(saved_errno, Eq(77));
+}
+
+TEST(ErrnoPreservationTest, AfterStatement) {
+  errno = 77;
+  LOG(INFO);
+  const int saved_errno = errno;
+  EXPECT_THAT(saved_errno, Eq(77));
+}
+
+// Tests that using a variable/parameter in a logging statement suppresses
+// unused-variable/parameter warnings.
+// -----------------------------------------------------------------------
+class UnusedVariableWarningCompileTest {
+  // These four don't prove anything unless `ABSL_MIN_LOG_LEVEL` is greater than
+  // `kInfo`.
+  static void LoggedVariable() {
+    const int x = 0;
+    LOG(INFO) << x;
+  }
+  static void LoggedParameter(const int x) { LOG(INFO) << x; }
+  static void SeverityVariable() {
+    const int x = 0;
+    LOG(LEVEL(x)) << "hello world";
+  }
+  static void SeverityParameter(const int x) { LOG(LEVEL(x)) << "hello world"; }
+};
+
+}  // namespace
diff --git a/absl/log/check.h b/absl/log/check.h
new file mode 100644
index 0000000..30bf76a
--- /dev/null
+++ b/absl/log/check.h
@@ -0,0 +1,227 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/check.h
+// -----------------------------------------------------------------------------
+//
+// This header declares a family of `CHECK` macros.
+//
+// `CHECK` macros terminate the program with a fatal error if the specified
+// condition is not true.
+//
+// Except for those whose names begin with `DCHECK`, these macros are not
+// controlled by `NDEBUG` (cf. `assert`), so the check will be executed
+// regardless of compilation mode. `CHECK` and friends are thus useful for
+// confirming invariants in situations where continuing to run would be worse
+// than terminating, e.g., due to risk of data corruption or security
+// compromise.  It is also more robust and portable to deliberately terminate
+// at a particular place with a useful message and backtrace than to assume some
+// ultimately unspecified and unreliable crashing behavior (such as a
+// "segmentation fault").
+
+#ifndef ABSL_LOG_CHECK_H_
+#define ABSL_LOG_CHECK_H_
+
+#include "absl/base/optimization.h"
+#include "absl/log/internal/check_op.h"     // IWYU pragma: export
+#include "absl/log/internal/conditions.h"   // IWYU pragma: export
+#include "absl/log/internal/log_message.h"  // IWYU pragma: export
+#include "absl/log/internal/strip.h"        // IWYU pragma: export
+
+// CHECK()
+//
+// `CHECK` terminates the program with a fatal error if `condition` is not true.
+//
+// The message may include additional information such as stack traces, when
+// available.
+//
+// Example:
+//
+//   CHECK(!cheese.empty()) << "Out of Cheese";
+//
+// Might produce a message like:
+//
+//   Check failed: !cheese.empty() Out of Cheese
+#define CHECK(condition)                                              \
+  ABSL_LOG_INTERNAL_CONDITION_FATAL(STATELESS,                        \
+                                    ABSL_PREDICT_FALSE(!(condition))) \
+  ABSL_LOG_INTERNAL_CHECK(#condition).InternalStream()
+
+// QCHECK()
+//
+// `QCHECK` behaves like `CHECK` but does not print a full stack trace and does
+// not run registered error handlers (as `QFATAL`).  It is useful when the
+// problem is definitely unrelated to program flow, e.g. when validating user
+// input.
+#define QCHECK(condition)                                              \
+  ABSL_LOG_INTERNAL_CONDITION_QFATAL(STATELESS,                        \
+                                     ABSL_PREDICT_FALSE(!(condition))) \
+  ABSL_LOG_INTERNAL_QCHECK(#condition).InternalStream()
+
+// PCHECK()
+//
+// `PCHECK` behaves like `CHECK` but appends a description of the current state
+// of `errno` to the failure message.
+//
+// Example:
+//
+//   int fd = open("/var/empty/missing", O_RDONLY);
+//   PCHECK(fd != -1) << "posix is difficult";
+//
+// Might produce a message like:
+//
+//   Check failed: fd != -1 posix is difficult: No such file or directory [2]
+#define PCHECK(condition) CHECK(condition).WithPerror()
+
+// DCHECK()
+//
+// `DCHECK` behaves like `CHECK` in debug mode and does nothing otherwise (as
+// `DLOG`).  Unlike with `CHECK` (but as with `assert`), it is not safe to rely
+// on evaluation of `condition`: when `NDEBUG` is enabled, DCHECK does not
+// evaluate the condition.
+#ifndef NDEBUG
+#define DCHECK(condition) CHECK(condition)
+#else
+#define DCHECK(condition) CHECK(true || (condition))
+#endif
+
+// `CHECK_EQ` and friends are syntactic sugar for `CHECK(x == y)` that
+// automatically output the expression being tested and the evaluated values on
+// either side.
+//
+// Example:
+//
+//   int x = 3, y = 5;
+//   CHECK_EQ(2 * x, y) << "oops!";
+//
+// Might produce a message like:
+//
+//   Check failed: 2 * x == y (6 vs. 5) oops!
+//
+// The values must implement the appropriate comparison operator as well as
+// `operator<<(std::ostream&, ...)`.  Care is taken to ensure that each
+// argument is evaluated exactly once, and that anything which is legal to pass
+// as a function argument is legal here.  In particular, the arguments may be
+// temporary expressions which will end up being destroyed at the end of the
+// statement,
+//
+// Example:
+//
+//   CHECK_EQ(std::string("abc")[1], 'b');
+//
+// WARNING: Passing `NULL` as an argument to `CHECK_EQ` and similar macros does
+// not compile.  Use `nullptr` instead.
+#define CHECK_EQ(val1, val2) \
+  ABSL_LOG_INTERNAL_CHECK_OP(Check_EQ, ==, val1, val2)
+#define CHECK_NE(val1, val2) \
+  ABSL_LOG_INTERNAL_CHECK_OP(Check_NE, !=, val1, val2)
+#define CHECK_LE(val1, val2) \
+  ABSL_LOG_INTERNAL_CHECK_OP(Check_LE, <=, val1, val2)
+#define CHECK_LT(val1, val2) ABSL_LOG_INTERNAL_CHECK_OP(Check_LT, <, val1, val2)
+#define CHECK_GE(val1, val2) \
+  ABSL_LOG_INTERNAL_CHECK_OP(Check_GE, >=, val1, val2)
+#define CHECK_GT(val1, val2) ABSL_LOG_INTERNAL_CHECK_OP(Check_GT, >, val1, val2)
+#define QCHECK_EQ(val1, val2) \
+  ABSL_LOG_INTERNAL_QCHECK_OP(Check_EQ, ==, val1, val2)
+#define QCHECK_NE(val1, val2) \
+  ABSL_LOG_INTERNAL_QCHECK_OP(Check_NE, !=, val1, val2)
+#define QCHECK_LE(val1, val2) \
+  ABSL_LOG_INTERNAL_QCHECK_OP(Check_LE, <=, val1, val2)
+#define QCHECK_LT(val1, val2) \
+  ABSL_LOG_INTERNAL_QCHECK_OP(Check_LT, <, val1, val2)
+#define QCHECK_GE(val1, val2) \
+  ABSL_LOG_INTERNAL_QCHECK_OP(Check_GE, >=, val1, val2)
+#define QCHECK_GT(val1, val2) \
+  ABSL_LOG_INTERNAL_QCHECK_OP(Check_GT, >, val1, val2)
+#ifndef NDEBUG
+#define DCHECK_EQ(val1, val2) CHECK_EQ(val1, val2)
+#define DCHECK_NE(val1, val2) CHECK_NE(val1, val2)
+#define DCHECK_LE(val1, val2) CHECK_LE(val1, val2)
+#define DCHECK_LT(val1, val2) CHECK_LT(val1, val2)
+#define DCHECK_GE(val1, val2) CHECK_GE(val1, val2)
+#define DCHECK_GT(val1, val2) CHECK_GT(val1, val2)
+#else  // ndef NDEBUG
+#define DCHECK_EQ(val1, val2) ABSL_LOG_INTERNAL_DCHECK_NOP(val1, val2)
+#define DCHECK_NE(val1, val2) ABSL_LOG_INTERNAL_DCHECK_NOP(val1, val2)
+#define DCHECK_LE(val1, val2) ABSL_LOG_INTERNAL_DCHECK_NOP(val1, val2)
+#define DCHECK_LT(val1, val2) ABSL_LOG_INTERNAL_DCHECK_NOP(val1, val2)
+#define DCHECK_GE(val1, val2) ABSL_LOG_INTERNAL_DCHECK_NOP(val1, val2)
+#define DCHECK_GT(val1, val2) ABSL_LOG_INTERNAL_DCHECK_NOP(val1, val2)
+#endif  // def NDEBUG
+
+// `CHECK_OK` and friends validate that the provided `absl::Status` or
+// `absl::StatusOr<T>` is OK.  If it isn't, they print a failure message that
+// includes the actual status.
+//
+// As with all `DCHECK` variants, `DCHECK_OK` has no effect (not even
+// evaluating its argument) if `NDEBUG` is enabled.
+//
+// Example:
+//
+//   CHECK_OK(FunctionReturnsStatus(x, y, z)) << "oops!";
+//
+// Might produce a message like:
+//
+//   Check failed: FunctionReturnsStatus(x, y, z) is OK (ABORTED: timeout) oops!
+#define CHECK_OK(status) ABSL_LOG_INTERNAL_CHECK_OK(status)
+#define QCHECK_OK(status) ABSL_LOG_INTERNAL_QCHECK_OK(status)
+#ifndef NDEBUG
+#define DCHECK_OK(status) ABSL_LOG_INTERNAL_CHECK_OK(status)
+#else
+#define DCHECK_OK(status) ABSL_LOG_INTERNAL_DCHECK_NOP(status, nullptr)
+#endif
+
+// `CHECK_STREQ` and friends provide `CHECK_EQ` functionality for C strings,
+// i.e., nul-terminated char arrays.  The `CASE` versions are case-insensitive.
+//
+// Example:
+//
+//   CHECK_STREQ(argv[0], "./skynet");
+//
+// Note that both arguments may be temporary strings which are destroyed by the
+// compiler at the end of the current full expression.
+//
+// Example:
+//
+//   CHECK_STREQ(Foo().c_str(), Bar().c_str());
+#define CHECK_STREQ(s1, s2) \
+  ABSL_LOG_INTERNAL_CHECK_STROP(strcmp, ==, true, s1, s2)
+#define CHECK_STRNE(s1, s2) \
+  ABSL_LOG_INTERNAL_CHECK_STROP(strcmp, !=, false, s1, s2)
+#define CHECK_STRCASEEQ(s1, s2) \
+  ABSL_LOG_INTERNAL_CHECK_STROP(strcasecmp, ==, true, s1, s2)
+#define CHECK_STRCASENE(s1, s2) \
+  ABSL_LOG_INTERNAL_CHECK_STROP(strcasecmp, !=, false, s1, s2)
+#define QCHECK_STREQ(s1, s2) \
+  ABSL_LOG_INTERNAL_QCHECK_STROP(strcmp, ==, true, s1, s2)
+#define QCHECK_STRNE(s1, s2) \
+  ABSL_LOG_INTERNAL_QCHECK_STROP(strcmp, !=, false, s1, s2)
+#define QCHECK_STRCASEEQ(s1, s2) \
+  ABSL_LOG_INTERNAL_QCHECK_STROP(strcasecmp, ==, true, s1, s2)
+#define QCHECK_STRCASENE(s1, s2) \
+  ABSL_LOG_INTERNAL_QCHECK_STROP(strcasecmp, !=, false, s1, s2)
+#ifndef NDEBUG
+#define DCHECK_STREQ(s1, s2) CHECK_STREQ(s1, s2)
+#define DCHECK_STRCASEEQ(s1, s2) CHECK_STRCASEEQ(s1, s2)
+#define DCHECK_STRNE(s1, s2) CHECK_STRNE(s1, s2)
+#define DCHECK_STRCASENE(s1, s2) CHECK_STRCASENE(s1, s2)
+#else  // ndef NDEBUG
+#define DCHECK_STREQ(s1, s2) ABSL_LOG_INTERNAL_DCHECK_NOP(s1, s2)
+#define DCHECK_STRCASEEQ(s1, s2) ABSL_LOG_INTERNAL_DCHECK_NOP(s1, s2)
+#define DCHECK_STRNE(s1, s2) ABSL_LOG_INTERNAL_DCHECK_NOP(s1, s2)
+#define DCHECK_STRCASENE(s1, s2) ABSL_LOG_INTERNAL_DCHECK_NOP(s1, s2)
+#endif  // def NDEBUG
+
+#endif  // ABSL_LOG_CHECK_H_
diff --git a/absl/log/check_test.cc b/absl/log/check_test.cc
new file mode 100644
index 0000000..4ce9d87
--- /dev/null
+++ b/absl/log/check_test.cc
@@ -0,0 +1,433 @@
+//
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/check.h"
+
+#include <ostream>
+#include <string>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/log/internal/test_helpers.h"
+
+namespace {
+using ::testing::AllOf;
+using ::testing::HasSubstr;
+using ::testing::Not;
+
+auto* test_env ABSL_ATTRIBUTE_UNUSED = ::testing::AddGlobalTestEnvironment(
+    new absl::log_internal::LogTestEnvironment);
+
+#if GTEST_HAS_DEATH_TEST
+
+TEST(CHECKDeathTest, TestBasicValues) {
+  CHECK(true);
+
+  EXPECT_DEATH(CHECK(false), "Check failed: false");
+
+  int i = 2;
+  CHECK(i != 3);  // NOLINT
+}
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+TEST(CHECKTest, TestLogicExpressions) {
+  int i = 5;
+  CHECK(i > 0 && i < 10);
+  CHECK(i < 0 || i > 3);
+}
+
+#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
+ABSL_CONST_INIT const auto global_var_check = [](int i) {
+  CHECK(i > 0);  // NOLINT
+  return i + 1;
+}(3);
+
+ABSL_CONST_INIT const auto global_var = [](int i) {
+  CHECK_GE(i, 0);  // NOLINT
+  return i + 1;
+}(global_var_check);
+#endif  // ABSL_INTERNAL_CPLUSPLUS_LANG
+
+TEST(CHECKTest, TestPlacementsInCompoundStatements) {
+  // check placement inside if/else clauses
+  if (true) CHECK(true);
+
+  if (false)
+    ;  // NOLINT
+  else
+    CHECK(true);
+
+  switch (0)
+  case 0:
+    CHECK(true);  // NOLINT
+
+#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
+  constexpr auto var = [](int i) {
+    CHECK(i > 0);  // NOLINT
+    return i + 1;
+  }(global_var);
+  (void)var;
+#endif  // ABSL_INTERNAL_CPLUSPLUS_LANG
+}
+
+TEST(CHECKTest, TestBoolConvertible) {
+  struct Tester {
+  } tester;
+  CHECK([&]() { return &tester; }());
+}
+
+#if GTEST_HAS_DEATH_TEST
+
+TEST(CHECKDeathTest, TestChecksWithSideeffects) {
+  int var = 0;
+  CHECK([&var]() {
+    ++var;
+    return true;
+  }());
+  EXPECT_EQ(var, 1);
+
+  EXPECT_DEATH(CHECK([&var]() {
+                 ++var;
+                 return false;
+               }()) << var,
+               "Check failed: .* 2");
+}
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+#if GTEST_HAS_DEATH_TEST
+
+TEST(CHECKDeachTest, TestOrderOfInvocationsBetweenCheckAndMessage) {
+  int counter = 0;
+
+  auto GetStr = [&counter]() -> std::string {
+    return counter++ == 0 ? "" : "non-empty";
+  };
+
+  EXPECT_DEATH(CHECK(!GetStr().empty()) << GetStr(), HasSubstr("non-empty"));
+}
+
+TEST(CHECKTest, TestSecondaryFailure) {
+  auto FailingRoutine = []() {
+    CHECK(false) << "Secondary";
+    return false;
+  };
+  EXPECT_DEATH(CHECK(FailingRoutine()) << "Primary",
+               AllOf(HasSubstr("Secondary"), Not(HasSubstr("Primary"))));
+}
+
+TEST(CHECKTest, TestSecondaryFailureInMessage) {
+  auto MessageGen = []() {
+    CHECK(false) << "Secondary";
+    return "Primary";
+  };
+  EXPECT_DEATH(CHECK(false) << MessageGen(),
+               AllOf(HasSubstr("Secondary"), Not(HasSubstr("Primary"))));
+}
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+TEST(CHECKTest, TestBinaryChecksWithPrimitives) {
+  CHECK_EQ(1, 1);
+  CHECK_NE(1, 2);
+  CHECK_GE(1, 1);
+  CHECK_GE(2, 1);
+  CHECK_LE(1, 1);
+  CHECK_LE(1, 2);
+  CHECK_GT(2, 1);
+  CHECK_LT(1, 2);
+}
+
+// For testing using CHECK*() on anonymous enums.
+enum { CASE_A, CASE_B };
+
+TEST(CHECKTest, TestBinaryChecksWithEnumValues) {
+  // Tests using CHECK*() on anonymous enums.
+  CHECK_EQ(CASE_A, CASE_A);
+  CHECK_NE(CASE_A, CASE_B);
+  CHECK_GE(CASE_A, CASE_A);
+  CHECK_GE(CASE_B, CASE_A);
+  CHECK_LE(CASE_A, CASE_A);
+  CHECK_LE(CASE_A, CASE_B);
+  CHECK_GT(CASE_B, CASE_A);
+  CHECK_LT(CASE_A, CASE_B);
+}
+
+TEST(CHECKTest, TestBinaryChecksWithNullptr) {
+  const void* p_null = nullptr;
+  const void* p_not_null = &p_null;
+  CHECK_EQ(p_null, nullptr);
+  CHECK_EQ(nullptr, p_null);
+  CHECK_NE(p_not_null, nullptr);
+  CHECK_NE(nullptr, p_not_null);
+}
+
+#if GTEST_HAS_DEATH_TEST
+
+// Test logging of various char-typed values by failing CHECK*().
+TEST(CHECKDeathTest, TestComparingCharsValues) {
+  {
+    char a = ';';
+    char b = 'b';
+    EXPECT_DEATH(CHECK_EQ(a, b), "Check failed: a == b \\(';' vs. 'b'\\)");
+    b = 1;
+    EXPECT_DEATH(CHECK_EQ(a, b),
+                 "Check failed: a == b \\(';' vs. char value 1\\)");
+  }
+  {
+    signed char a = ';';
+    signed char b = 'b';
+    EXPECT_DEATH(CHECK_EQ(a, b), "Check failed: a == b \\(';' vs. 'b'\\)");
+    b = -128;
+    EXPECT_DEATH(CHECK_EQ(a, b),
+                 "Check failed: a == b \\(';' vs. signed char value -128\\)");
+  }
+  {
+    unsigned char a = ';';
+    unsigned char b = 'b';
+    EXPECT_DEATH(CHECK_EQ(a, b), "Check failed: a == b \\(';' vs. 'b'\\)");
+    b = 128;
+    EXPECT_DEATH(CHECK_EQ(a, b),
+                 "Check failed: a == b \\(';' vs. unsigned char value 128\\)");
+  }
+}
+
+TEST(CHECKDeathTest, TestNullValuesAreReportedCleanly) {
+  const char* a = nullptr;
+  const char* b = nullptr;
+  EXPECT_DEATH(CHECK_NE(a, b),
+               "Check failed: a != b \\(\\(null\\) vs. \\(null\\)\\)");
+
+  a = "xx";
+  EXPECT_DEATH(CHECK_EQ(a, b), "Check failed: a == b \\(xx vs. \\(null\\)\\)");
+  EXPECT_DEATH(CHECK_EQ(b, a), "Check failed: b == a \\(\\(null\\) vs. xx\\)");
+
+  std::nullptr_t n{};
+  EXPECT_DEATH(CHECK_NE(n, nullptr),
+               "Check failed: n != nullptr \\(\\(null\\) vs. \\(null\\)\\)");
+}
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+TEST(CHECKTest, TestSTREQ) {
+  CHECK_STREQ("this", "this");
+  CHECK_STREQ(nullptr, nullptr);
+  CHECK_STRCASEEQ("this", "tHiS");
+  CHECK_STRCASEEQ(nullptr, nullptr);
+  CHECK_STRNE("this", "tHiS");
+  CHECK_STRNE("this", nullptr);
+  CHECK_STRCASENE("this", "that");
+  CHECK_STRCASENE(nullptr, "that");
+  CHECK_STREQ((std::string("a") + "b").c_str(), "ab");
+  CHECK_STREQ(std::string("test").c_str(),
+              (std::string("te") + std::string("st")).c_str());
+}
+
+TEST(CHECKTest, TestComparisonPlacementsInCompoundStatements) {
+  // check placement inside if/else clauses
+  if (true) CHECK_EQ(1, 1);
+  if (true) CHECK_STREQ("c", "c");
+
+  if (false)
+    ;  // NOLINT
+  else
+    CHECK_LE(0, 1);
+
+  if (false)
+    ;  // NOLINT
+  else
+    CHECK_STRNE("a", "b");
+
+  switch (0)
+  case 0:
+    CHECK_NE(1, 0);
+
+  switch (0)
+  case 0:
+    CHECK_STRCASEEQ("A", "a");
+
+#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
+  constexpr auto var = [](int i) {
+    CHECK_GT(i, 0);
+    return i + 1;
+  }(global_var);
+  (void)var;
+
+  // CHECK_STR... checks are not supported in constexpr routines.
+  // constexpr auto var2 = [](int i) {
+  //  CHECK_STRNE("c", "d");
+  //  return i + 1;
+  // }(global_var);
+
+#if defined(__GNUC__)
+  int var3 = (({ CHECK_LE(1, 2); }), global_var < 10) ? 1 : 0;
+  (void)var3;
+
+  int var4 = (({ CHECK_STREQ("a", "a"); }), global_var < 10) ? 1 : 0;
+  (void)var4;
+#endif  // __GNUC__
+#endif  // ABSL_INTERNAL_CPLUSPLUS_LANG
+}
+
+TEST(CHECKTest, TestDCHECK) {
+#ifdef NDEBUG
+  DCHECK(1 == 2) << " DCHECK's shouldn't be compiled in normal mode";
+#endif
+  DCHECK(1 == 1);  // NOLINT(readability/check)
+  DCHECK_EQ(1, 1);
+  DCHECK_NE(1, 2);
+  DCHECK_GE(1, 1);
+  DCHECK_GE(2, 1);
+  DCHECK_LE(1, 1);
+  DCHECK_LE(1, 2);
+  DCHECK_GT(2, 1);
+  DCHECK_LT(1, 2);
+
+  // Test DCHECK on std::nullptr_t
+  const void* p_null = nullptr;
+  const void* p_not_null = &p_null;
+  DCHECK_EQ(p_null, nullptr);
+  DCHECK_EQ(nullptr, p_null);
+  DCHECK_NE(p_not_null, nullptr);
+  DCHECK_NE(nullptr, p_not_null);
+}
+
+TEST(CHECKTest, TestQCHECK) {
+  // The tests that QCHECK does the same as CHECK
+  QCHECK(1 == 1);  // NOLINT(readability/check)
+  QCHECK_EQ(1, 1);
+  QCHECK_NE(1, 2);
+  QCHECK_GE(1, 1);
+  QCHECK_GE(2, 1);
+  QCHECK_LE(1, 1);
+  QCHECK_LE(1, 2);
+  QCHECK_GT(2, 1);
+  QCHECK_LT(1, 2);
+
+  // Tests using QCHECK*() on anonymous enums.
+  QCHECK_EQ(CASE_A, CASE_A);
+  QCHECK_NE(CASE_A, CASE_B);
+  QCHECK_GE(CASE_A, CASE_A);
+  QCHECK_GE(CASE_B, CASE_A);
+  QCHECK_LE(CASE_A, CASE_A);
+  QCHECK_LE(CASE_A, CASE_B);
+  QCHECK_GT(CASE_B, CASE_A);
+  QCHECK_LT(CASE_A, CASE_B);
+}
+
+TEST(CHECKTest, TestQCHECKPlacementsInCompoundStatements) {
+  // check placement inside if/else clauses
+  if (true) QCHECK(true);
+
+  if (false)
+    ;  // NOLINT
+  else
+    QCHECK(true);
+
+  if (false)
+    ;  // NOLINT
+  else
+    QCHECK(true);
+
+  switch (0)
+  case 0:
+    QCHECK(true);
+
+#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
+  constexpr auto var = [](int i) {
+    QCHECK(i > 0);  // NOLINT
+    return i + 1;
+  }(global_var);
+  (void)var;
+
+#if defined(__GNUC__)
+  int var2 = (({ CHECK_LE(1, 2); }), global_var < 10) ? 1 : 0;
+  (void)var2;
+#endif  // __GNUC__
+#endif  // ABSL_INTERNAL_CPLUSPLUS_LANG
+}
+
+class ComparableType {
+ public:
+  explicit ComparableType(int v) : v_(v) {}
+
+  void MethodWithCheck(int i) {
+    CHECK_EQ(*this, i);
+    CHECK_EQ(i, *this);
+  }
+
+  int Get() const { return v_; }
+
+ private:
+  friend bool operator==(const ComparableType& lhs, const ComparableType& rhs) {
+    return lhs.v_ == rhs.v_;
+  }
+  friend bool operator!=(const ComparableType& lhs, const ComparableType& rhs) {
+    return lhs.v_ != rhs.v_;
+  }
+  friend bool operator<(const ComparableType& lhs, const ComparableType& rhs) {
+    return lhs.v_ < rhs.v_;
+  }
+  friend bool operator<=(const ComparableType& lhs, const ComparableType& rhs) {
+    return lhs.v_ <= rhs.v_;
+  }
+  friend bool operator>(const ComparableType& lhs, const ComparableType& rhs) {
+    return lhs.v_ > rhs.v_;
+  }
+  friend bool operator>=(const ComparableType& lhs, const ComparableType& rhs) {
+    return lhs.v_ >= rhs.v_;
+  }
+  friend bool operator==(const ComparableType& lhs, int rhs) {
+    return lhs.v_ == rhs;
+  }
+  friend bool operator==(int lhs, const ComparableType& rhs) {
+    return lhs == rhs.v_;
+  }
+
+  friend std::ostream& operator<<(std::ostream& out, const ComparableType& v) {
+    return out << "ComparableType{" << v.Get() << "}";
+  }
+
+  int v_;
+};
+
+TEST(CHECKTest, TestUserDefinedCompOp) {
+  CHECK_EQ(ComparableType{0}, ComparableType{0});
+  CHECK_NE(ComparableType{1}, ComparableType{2});
+  CHECK_LT(ComparableType{1}, ComparableType{2});
+  CHECK_LE(ComparableType{1}, ComparableType{2});
+  CHECK_GT(ComparableType{2}, ComparableType{1});
+  CHECK_GE(ComparableType{2}, ComparableType{2});
+}
+
+TEST(CHECKTest, TestCheckInMethod) {
+  ComparableType v{1};
+  v.MethodWithCheck(1);
+}
+
+TEST(CHECKDeathTest, TestUserDefinedStreaming) {
+  ComparableType v1{1};
+  ComparableType v2{2};
+
+  EXPECT_DEATH(
+      CHECK_EQ(v1, v2),
+      HasSubstr(
+          "Check failed: v1 == v2 (ComparableType{1} vs. ComparableType{2})"));
+}
+
+}  // namespace
diff --git a/absl/log/die_if_null.cc b/absl/log/die_if_null.cc
new file mode 100644
index 0000000..19c6a28
--- /dev/null
+++ b/absl/log/die_if_null.cc
@@ -0,0 +1,32 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/die_if_null.h"
+
+#include "absl/base/config.h"
+#include "absl/log/log.h"
+#include "absl/strings/str_cat.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+void DieBecauseNull(const char* file, int line, const char* exprtext) {
+  LOG(FATAL).AtLocation(file, line)
+      << absl::StrCat("Check failed: '", exprtext, "' Must be non-null");
+}
+
+}  // namespace log_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/log/die_if_null.h b/absl/log/die_if_null.h
new file mode 100644
index 0000000..127a9ac
--- /dev/null
+++ b/absl/log/die_if_null.h
@@ -0,0 +1,76 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/die_if_null.h
+// -----------------------------------------------------------------------------
+//
+// This header declares macro `ABSL_DIE_IF_NULL`.
+
+#ifndef ABSL_LOG_DIE_IF_NULL_H_
+#define ABSL_LOG_DIE_IF_NULL_H_
+
+#include <stdint.h>
+
+#include <utility>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/optimization.h"
+
+// ABSL_DIE_IF_NULL()
+//
+// `ABSL_DIE_IF_NULL` behaves as `CHECK_NE` against `nullptr` but *also*
+// "returns" its argument.  It is useful in initializers where statements (like
+// `CHECK_NE`) can't be used.  Outside initializers, prefer `CHECK` or
+// `CHECK_NE`. `ABSL_DIE_IF_NULL` works for both raw pointers and (compatible)
+// smart pointers including `std::unique_ptr` and `std::shared_ptr`; more
+// generally, it works for any type that can be compared to nullptr_t.  For
+// types that aren't raw pointers, `ABSL_DIE_IF_NULL` returns a reference to
+// its argument, preserving the value category. Example:
+//
+//   Foo() : bar_(ABSL_DIE_IF_NULL(MethodReturningUniquePtr())) {}
+//
+// Use `CHECK(ptr)` or `CHECK(ptr != nullptr)` if the returned pointer is
+// unused.
+#define ABSL_DIE_IF_NULL(val) \
+  ::absl::log_internal::DieIfNull(__FILE__, __LINE__, #val, (val))
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+// Crashes the process after logging `exprtext` annotated at the `file` and
+// `line` location. Called when `ABSL_DIE_IF_NULL` fails. Calling this function
+// generates less code than its implementation would if inlined, for a slight
+// code size reduction each time `ABSL_DIE_IF_NULL` is called.
+ABSL_ATTRIBUTE_NORETURN ABSL_ATTRIBUTE_NOINLINE void DieBecauseNull(
+    const char* file, int line, const char* exprtext);
+
+// Helper for `ABSL_DIE_IF_NULL`.
+template <typename T>
+ABSL_MUST_USE_RESULT T DieIfNull(const char* file, int line,
+                                 const char* exprtext, T&& t) {
+  if (ABSL_PREDICT_FALSE(t == nullptr)) {
+    // Call a non-inline helper function for a small code size improvement.
+    DieBecauseNull(file, line, exprtext);
+  }
+  return std::forward<T>(t);
+}
+
+}  // namespace log_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_LOG_DIE_IF_NULL_H_
diff --git a/absl/log/die_if_null_test.cc b/absl/log/die_if_null_test.cc
new file mode 100644
index 0000000..b0aab78
--- /dev/null
+++ b/absl/log/die_if_null_test.cc
@@ -0,0 +1,107 @@
+//
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/die_if_null.h"
+
+#include <stdint.h>
+
+#include <memory>
+#include <utility>
+
+#include "gtest/gtest.h"
+#include "absl/base/attributes.h"
+#include "absl/log/internal/test_helpers.h"
+
+namespace {
+
+auto* test_env ABSL_ATTRIBUTE_UNUSED = ::testing::AddGlobalTestEnvironment(
+    new absl::log_internal::LogTestEnvironment);
+
+// TODO(b/69907837): Revisit these tests with the goal of making them less
+// convoluted.
+TEST(AbslDieIfNull, Simple) {
+  int64_t t;
+  void* ptr = static_cast<void*>(&t);
+  void* ref = ABSL_DIE_IF_NULL(ptr);
+  ASSERT_EQ(ptr, ref);
+
+  char* t_as_char;
+  t_as_char = ABSL_DIE_IF_NULL(reinterpret_cast<char*>(&t));
+  (void)t_as_char;
+
+  unsigned char* t_as_uchar;
+  t_as_uchar = ABSL_DIE_IF_NULL(reinterpret_cast<unsigned char*>(&t));
+  (void)t_as_uchar;
+
+  int* t_as_int;
+  t_as_int = ABSL_DIE_IF_NULL(reinterpret_cast<int*>(&t));
+  (void)t_as_int;
+
+  int64_t* t_as_int64_t;
+  t_as_int64_t = ABSL_DIE_IF_NULL(reinterpret_cast<int64_t*>(&t));
+  (void)t_as_int64_t;
+
+  std::unique_ptr<int64_t> sptr(new int64_t);
+  EXPECT_EQ(sptr.get(), ABSL_DIE_IF_NULL(sptr).get());
+  ABSL_DIE_IF_NULL(sptr).reset();
+
+  int64_t* int_ptr = new int64_t();
+  EXPECT_EQ(int_ptr, ABSL_DIE_IF_NULL(std::unique_ptr<int64_t>(int_ptr)).get());
+}
+
+#if GTEST_HAS_DEATH_TEST
+TEST(DeathCheckAbslDieIfNull, Simple) {
+  void* ptr;
+  ASSERT_DEATH({ ptr = ABSL_DIE_IF_NULL(nullptr); }, "");
+  (void)ptr;
+
+  std::unique_ptr<int64_t> sptr;
+  ASSERT_DEATH(ptr = ABSL_DIE_IF_NULL(sptr).get(), "");
+}
+#endif
+
+// Ensures that ABSL_DIE_IF_NULL works with C++11's std::unique_ptr and
+// std::shared_ptr.
+TEST(AbslDieIfNull, DoesNotCompareSmartPointerToNULL) {
+  std::unique_ptr<int> up(new int);
+  EXPECT_EQ(&up, &ABSL_DIE_IF_NULL(up));
+  ABSL_DIE_IF_NULL(up).reset();
+
+  std::shared_ptr<int> sp(new int);
+  EXPECT_EQ(&sp, &ABSL_DIE_IF_NULL(sp));
+  ABSL_DIE_IF_NULL(sp).reset();
+}
+
+// Verifies that ABSL_DIE_IF_NULL returns an rvalue reference if its argument is
+// an rvalue reference.
+TEST(AbslDieIfNull, PreservesRValues) {
+  int64_t* ptr = new int64_t();
+  auto uptr = ABSL_DIE_IF_NULL(std::unique_ptr<int64_t>(ptr));
+  EXPECT_EQ(ptr, uptr.get());
+}
+
+// Verifies that ABSL_DIE_IF_NULL returns an lvalue if its argument is an
+// lvalue.
+TEST(AbslDieIfNull, PreservesLValues) {
+  int64_t array[2] = {0};
+  int64_t* a = array + 0;
+  int64_t* b = array + 1;
+  using std::swap;
+  swap(ABSL_DIE_IF_NULL(a), ABSL_DIE_IF_NULL(b));
+  EXPECT_EQ(array + 1, a);
+  EXPECT_EQ(array + 0, b);
+}
+
+}  // namespace
diff --git a/absl/log/flags.cc b/absl/log/flags.cc
new file mode 100644
index 0000000..b530888
--- /dev/null
+++ b/absl/log/flags.cc
@@ -0,0 +1,112 @@
+//
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/internal/flags.h"
+
+#include <stddef.h>
+
+#include <algorithm>
+#include <cstdlib>
+#include <string>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/log_severity.h"
+#include "absl/flags/flag.h"
+#include "absl/flags/marshalling.h"
+#include "absl/log/globals.h"
+#include "absl/log/internal/config.h"
+#include "absl/strings/numbers.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+namespace {
+
+void SyncLoggingFlags() {
+  absl::SetFlag(&FLAGS_minloglevel, static_cast<int>(absl::MinLogLevel()));
+  absl::SetFlag(&FLAGS_log_prefix, absl::ShouldPrependLogPrefix());
+}
+
+bool RegisterSyncLoggingFlags() {
+  log_internal::SetLoggingGlobalsListener(&SyncLoggingFlags);
+  return true;
+}
+
+ABSL_ATTRIBUTE_UNUSED const bool unused = RegisterSyncLoggingFlags();
+
+template <typename T>
+T GetFromEnv(const char* varname, T dflt) {
+  const char* val = ::getenv(varname);
+  if (val != nullptr) {
+    std::string err;
+    ABSL_INTERNAL_CHECK(absl::ParseFlag(val, &dflt, &err), err.c_str());
+  }
+  return dflt;
+}
+
+constexpr absl::LogSeverityAtLeast StderrThresholdDefault() {
+  return absl::LogSeverityAtLeast::kError;
+}
+
+}  // namespace
+}  // namespace log_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+ABSL_FLAG(int, stderrthreshold,
+          static_cast<int>(absl::log_internal::StderrThresholdDefault()),
+          "Log messages at or above this threshold level are copied to stderr.")
+    .OnUpdate([] {
+      absl::log_internal::RawSetStderrThreshold(
+          static_cast<absl::LogSeverityAtLeast>(
+              absl::GetFlag(FLAGS_stderrthreshold)));
+    });
+
+ABSL_FLAG(int, minloglevel, static_cast<int>(absl::LogSeverityAtLeast::kInfo),
+          "Messages logged at a lower level than this don't actually "
+          "get logged anywhere")
+    .OnUpdate([] {
+      absl::log_internal::RawSetMinLogLevel(
+          static_cast<absl::LogSeverityAtLeast>(
+              absl::GetFlag(FLAGS_minloglevel)));
+    });
+
+ABSL_FLAG(std::string, log_backtrace_at, "",
+          "Emit a backtrace when logging at file:linenum.")
+    .OnUpdate([] {
+      const std::string log_backtrace_at =
+          absl::GetFlag(FLAGS_log_backtrace_at);
+      if (log_backtrace_at.empty()) return;
+
+      const size_t last_colon = log_backtrace_at.rfind(':');
+      if (last_colon == log_backtrace_at.npos) return;
+
+      const absl::string_view file =
+          absl::string_view(log_backtrace_at).substr(0, last_colon);
+      int line;
+      if (absl::SimpleAtoi(
+              absl::string_view(log_backtrace_at).substr(last_colon + 1),
+              &line)) {
+        absl::SetLogBacktraceLocation(file, line);
+      }
+    });
+
+ABSL_FLAG(bool, log_prefix, true,
+          "Prepend the log prefix to the start of each log line")
+    .OnUpdate([] {
+      absl::log_internal::RawEnableLogPrefix(absl::GetFlag(FLAGS_log_prefix));
+    });
diff --git a/absl/log/flags.h b/absl/log/flags.h
new file mode 100644
index 0000000..146cfdd
--- /dev/null
+++ b/absl/log/flags.h
@@ -0,0 +1,43 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/flags.h
+// -----------------------------------------------------------------------------
+//
+
+#ifndef ABSL_LOG_FLAGS_H_
+#define ABSL_LOG_FLAGS_H_
+
+// The Abseil Logging library supports the following command line flags to
+// configure logging behavior at runtime:
+//
+// --stderrthreshold=<value>
+// Log messages at or above this threshold level are copied to stderr.
+//
+// --minloglevel=<value>
+// Messages logged at a lower level than this are discarded and don't actually
+// get logged anywhere.
+//
+// --log_backtrace_at=<file:linenum>
+// Emit a backtrace (stack trace) when logging at file:linenum.
+//
+// To use these commandline flags, the //absl/log:flags library must be
+// explicitly linked, and absl::ParseCommandLine() must be called before the
+// call to absl::InitializeLog().
+//
+// To configure the Log library programmatically, use the interfaces defined in
+// absl/log/globals.h.
+
+#endif  // ABSL_LOG_FLAGS_H_
diff --git a/absl/log/flags_test.cc b/absl/log/flags_test.cc
new file mode 100644
index 0000000..7a80315
--- /dev/null
+++ b/absl/log/flags_test.cc
@@ -0,0 +1,181 @@
+//
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/internal/flags.h"
+
+#include <string>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/attributes.h"
+#include "absl/base/log_severity.h"
+#include "absl/flags/flag.h"
+#include "absl/flags/reflection.h"
+#include "absl/log/globals.h"
+#include "absl/log/internal/test_helpers.h"
+#include "absl/log/internal/test_matchers.h"
+#include "absl/log/log.h"
+#include "absl/log/scoped_mock_log.h"
+#include "absl/strings/str_cat.h"
+
+namespace {
+using ::absl::log_internal::TextMessage;
+
+using ::testing::HasSubstr;
+using ::testing::Not;
+
+auto* test_env ABSL_ATTRIBUTE_UNUSED = ::testing::AddGlobalTestEnvironment(
+    new absl::log_internal::LogTestEnvironment);
+
+constexpr static absl::LogSeverityAtLeast DefaultStderrThreshold() {
+  return absl::LogSeverityAtLeast::kError;
+}
+
+class LogFlagsTest : public ::testing::Test {
+ protected:
+  absl::FlagSaver flag_saver_;
+};
+
+TEST_F(LogFlagsTest, StderrKnobsDefault) {
+  EXPECT_EQ(absl::StderrThreshold(), DefaultStderrThreshold());
+}
+
+TEST_F(LogFlagsTest, SetStderrThreshold) {
+  absl::SetFlag(&FLAGS_stderrthreshold,
+                static_cast<int>(absl::LogSeverityAtLeast::kInfo));
+
+  EXPECT_EQ(absl::StderrThreshold(), absl::LogSeverityAtLeast::kInfo);
+
+  absl::SetFlag(&FLAGS_stderrthreshold,
+                static_cast<int>(absl::LogSeverityAtLeast::kError));
+
+  EXPECT_EQ(absl::StderrThreshold(), absl::LogSeverityAtLeast::kError);
+}
+
+TEST_F(LogFlagsTest, SetMinLogLevel) {
+  absl::SetFlag(&FLAGS_minloglevel,
+                static_cast<int>(absl::LogSeverityAtLeast::kError));
+
+  EXPECT_EQ(absl::MinLogLevel(), absl::LogSeverityAtLeast::kError);
+
+  absl::log_internal::ScopedMinLogLevel scoped_min_log_level(
+      absl::LogSeverityAtLeast::kWarning);
+
+  EXPECT_EQ(absl::GetFlag(FLAGS_minloglevel),
+            static_cast<int>(absl::LogSeverityAtLeast::kWarning));
+}
+
+TEST_F(LogFlagsTest, PrependLogPrefix) {
+  absl::SetFlag(&FLAGS_log_prefix, false);
+
+  EXPECT_EQ(absl::ShouldPrependLogPrefix(), false);
+
+  absl::EnableLogPrefix(true);
+
+  EXPECT_EQ(absl::GetFlag(FLAGS_log_prefix), true);
+}
+
+TEST_F(LogFlagsTest, EmptyBacktraceAtFlag) {
+  absl::SetMinLogLevel(absl::LogSeverityAtLeast::kInfo);
+  absl::SetFlag(&FLAGS_log_backtrace_at, "");
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(test_sink, Send(TextMessage(Not(HasSubstr("(stacktrace:")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << "hello world";
+}
+
+TEST_F(LogFlagsTest, BacktraceAtNonsense) {
+  absl::SetMinLogLevel(absl::LogSeverityAtLeast::kInfo);
+  absl::SetFlag(&FLAGS_log_backtrace_at, "gibberish");
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(test_sink, Send(TextMessage(Not(HasSubstr("(stacktrace:")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << "hello world";
+}
+
+TEST_F(LogFlagsTest, BacktraceAtWrongFile) {
+  absl::SetMinLogLevel(absl::LogSeverityAtLeast::kInfo);
+  const int log_line = __LINE__ + 1;
+  auto do_log = [] { LOG(INFO) << "hello world"; };
+  absl::SetFlag(&FLAGS_log_backtrace_at,
+                absl::StrCat("some_other_file.cc:", log_line));
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(test_sink, Send(TextMessage(Not(HasSubstr("(stacktrace:")))));
+
+  test_sink.StartCapturingLogs();
+  do_log();
+}
+
+TEST_F(LogFlagsTest, BacktraceAtWrongLine) {
+  absl::SetMinLogLevel(absl::LogSeverityAtLeast::kInfo);
+  const int log_line = __LINE__ + 1;
+  auto do_log = [] { LOG(INFO) << "hello world"; };
+  absl::SetFlag(&FLAGS_log_backtrace_at,
+                absl::StrCat("flags_test.cc:", log_line + 1));
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(test_sink, Send(TextMessage(Not(HasSubstr("(stacktrace:")))));
+
+  test_sink.StartCapturingLogs();
+  do_log();
+}
+
+TEST_F(LogFlagsTest, BacktraceAtWholeFilename) {
+  absl::SetMinLogLevel(absl::LogSeverityAtLeast::kInfo);
+  const int log_line = __LINE__ + 1;
+  auto do_log = [] { LOG(INFO) << "hello world"; };
+  absl::SetFlag(&FLAGS_log_backtrace_at, absl::StrCat(__FILE__, ":", log_line));
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(test_sink, Send(TextMessage(Not(HasSubstr("(stacktrace:")))));
+
+  test_sink.StartCapturingLogs();
+  do_log();
+}
+
+TEST_F(LogFlagsTest, BacktraceAtNonmatchingSuffix) {
+  absl::SetMinLogLevel(absl::LogSeverityAtLeast::kInfo);
+  const int log_line = __LINE__ + 1;
+  auto do_log = [] { LOG(INFO) << "hello world"; };
+  absl::SetFlag(&FLAGS_log_backtrace_at,
+                absl::StrCat("flags_test.cc:", log_line, "gibberish"));
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(test_sink, Send(TextMessage(Not(HasSubstr("(stacktrace:")))));
+
+  test_sink.StartCapturingLogs();
+  do_log();
+}
+
+TEST_F(LogFlagsTest, LogsBacktrace) {
+  absl::SetMinLogLevel(absl::LogSeverityAtLeast::kInfo);
+  const int log_line = __LINE__ + 1;
+  auto do_log = [] { LOG(INFO) << "hello world"; };
+  absl::SetFlag(&FLAGS_log_backtrace_at,
+                absl::StrCat("flags_test.cc:", log_line));
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(test_sink, Send(TextMessage(HasSubstr("(stacktrace:"))));
+
+  test_sink.StartCapturingLogs();
+  do_log();
+}
+
+}  // namespace
diff --git a/absl/log/globals.cc b/absl/log/globals.cc
new file mode 100644
index 0000000..6dfe81f
--- /dev/null
+++ b/absl/log/globals.cc
@@ -0,0 +1,148 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/globals.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <atomic>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/internal/atomic_hook.h"
+#include "absl/base/log_severity.h"
+#include "absl/hash/hash.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace {
+
+// These atomics represent logging library configuration.
+// Integer types are used instead of absl::LogSeverity to ensure that a
+// lock-free std::atomic is used when possible.
+ABSL_CONST_INIT std::atomic<int> min_log_level{
+    static_cast<int>(absl::LogSeverityAtLeast::kInfo)};
+ABSL_CONST_INIT std::atomic<int> stderrthreshold{
+    static_cast<int>(absl::LogSeverityAtLeast::kError)};
+// We evaluate this value as a hash comparison to avoid having to
+// hold a mutex or make a copy (to access the value of a string-typed flag) in
+// very hot codepath.
+ABSL_CONST_INIT std::atomic<size_t> log_backtrace_at_hash{0};
+ABSL_CONST_INIT std::atomic<bool> prepend_log_prefix{true};
+
+ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
+absl::base_internal::AtomicHook<log_internal::LoggingGlobalsListener>
+    logging_globals_listener;
+
+size_t HashSiteForLogBacktraceAt(absl::string_view file, int line) {
+  return absl::HashOf(file, line);
+}
+
+void TriggerLoggingGlobalsListener() {
+  auto* listener = logging_globals_listener.Load();
+  if (listener != nullptr) listener();
+}
+
+}  // namespace
+
+namespace log_internal {
+
+void RawSetMinLogLevel(absl::LogSeverityAtLeast severity) {
+  min_log_level.store(static_cast<int>(severity), std::memory_order_release);
+}
+
+void RawSetStderrThreshold(absl::LogSeverityAtLeast severity) {
+  stderrthreshold.store(static_cast<int>(severity), std::memory_order_release);
+}
+
+void RawEnableLogPrefix(bool on_off) {
+  prepend_log_prefix.store(on_off, std::memory_order_release);
+}
+
+void SetLoggingGlobalsListener(LoggingGlobalsListener l) {
+  logging_globals_listener.Store(l);
+}
+
+}  // namespace log_internal
+
+absl::LogSeverityAtLeast MinLogLevel() {
+  return static_cast<absl::LogSeverityAtLeast>(
+      min_log_level.load(std::memory_order_acquire));
+}
+
+void SetMinLogLevel(absl::LogSeverityAtLeast severity) {
+  log_internal::RawSetMinLogLevel(severity);
+  TriggerLoggingGlobalsListener();
+}
+
+namespace log_internal {
+
+ScopedMinLogLevel::ScopedMinLogLevel(absl::LogSeverityAtLeast severity)
+    : saved_severity_(absl::MinLogLevel()) {
+  absl::SetMinLogLevel(severity);
+}
+ScopedMinLogLevel::~ScopedMinLogLevel() {
+  absl::SetMinLogLevel(saved_severity_);
+}
+
+}  // namespace log_internal
+
+absl::LogSeverityAtLeast StderrThreshold() {
+  return static_cast<absl::LogSeverityAtLeast>(
+      stderrthreshold.load(std::memory_order_acquire));
+}
+
+void SetStderrThreshold(absl::LogSeverityAtLeast severity) {
+  log_internal::RawSetStderrThreshold(severity);
+  TriggerLoggingGlobalsListener();
+}
+
+ScopedStderrThreshold::ScopedStderrThreshold(absl::LogSeverityAtLeast severity)
+    : saved_severity_(absl::StderrThreshold()) {
+  absl::SetStderrThreshold(severity);
+}
+
+ScopedStderrThreshold::~ScopedStderrThreshold() {
+  absl::SetStderrThreshold(saved_severity_);
+}
+
+namespace log_internal {
+
+bool ShouldLogBacktraceAt(absl::string_view file, int line) {
+  const size_t flag_hash =
+      log_backtrace_at_hash.load(std::memory_order_acquire);
+
+  return flag_hash != 0 && flag_hash == HashSiteForLogBacktraceAt(file, line);
+}
+
+}  // namespace log_internal
+
+void SetLogBacktraceLocation(absl::string_view file, int line) {
+  log_backtrace_at_hash.store(HashSiteForLogBacktraceAt(file, line),
+                              std::memory_order_release);
+}
+
+bool ShouldPrependLogPrefix() {
+  return prepend_log_prefix.load(std::memory_order_acquire);
+}
+
+void EnableLogPrefix(bool on_off) {
+  log_internal::RawEnableLogPrefix(on_off);
+  TriggerLoggingGlobalsListener();
+}
+
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/log/globals.h b/absl/log/globals.h
new file mode 100644
index 0000000..32b87db
--- /dev/null
+++ b/absl/log/globals.h
@@ -0,0 +1,165 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/globals.h
+// -----------------------------------------------------------------------------
+//
+// This header declares global logging library configuration knobs.
+
+#ifndef ABSL_LOG_GLOBALS_H_
+#define ABSL_LOG_GLOBALS_H_
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/log_severity.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+//------------------------------------------------------------------------------
+//  Minimum Log Level
+//------------------------------------------------------------------------------
+//
+// Messages logged at or above this severity are directed to all registered log
+// sinks or skipped otherwise. This parameter can also be modified using
+// command line flag --minloglevel.
+// See absl/base/log_severity.h for descriptions of severity levels.
+
+// MinLogLevel()
+//
+// Returns the value of the Minimum Log Level parameter.
+// This function is async-signal-safe.
+ABSL_MUST_USE_RESULT absl::LogSeverityAtLeast MinLogLevel();
+
+// SetMinLogLevel()
+//
+// Updates the value of Minimum Log Level parameter.
+// This function is async-signal-safe.
+void SetMinLogLevel(absl::LogSeverityAtLeast severity);
+
+namespace log_internal {
+
+// ScopedMinLogLevel
+//
+// RAII type used to temporarily update the Min Log Level parameter.
+class ScopedMinLogLevel final {
+ public:
+  explicit ScopedMinLogLevel(absl::LogSeverityAtLeast severity);
+  ScopedMinLogLevel(const ScopedMinLogLevel&) = delete;
+  ScopedMinLogLevel& operator=(const ScopedMinLogLevel&) = delete;
+  ~ScopedMinLogLevel();
+
+ private:
+  absl::LogSeverityAtLeast saved_severity_;
+};
+
+}  // namespace log_internal
+
+//------------------------------------------------------------------------------
+// Stderr Threshold
+//------------------------------------------------------------------------------
+//
+// Messages logged at or above this level are directed to stderr in
+// addition to other registered log sinks. This parameter can also be modified
+// using command line flag --stderrthreshold.
+// See absl/base/log_severity.h for descriptions of severity levels.
+
+// StderrThreshold()
+//
+// Returns the value of the Stderr Threshold parameter.
+// This function is async-signal-safe.
+ABSL_MUST_USE_RESULT absl::LogSeverityAtLeast StderrThreshold();
+
+// SetStderrThreshold()
+//
+// Updates the Stderr Threshold parameter.
+// This function is async-signal-safe.
+void SetStderrThreshold(absl::LogSeverityAtLeast severity);
+inline void SetStderrThreshold(absl::LogSeverity severity) {
+  absl::SetStderrThreshold(static_cast<absl::LogSeverityAtLeast>(severity));
+}
+
+// ScopedStderrThreshold
+//
+// RAII type used to temporarily update the Stderr Threshold parameter.
+class ScopedStderrThreshold final {
+ public:
+  explicit ScopedStderrThreshold(absl::LogSeverityAtLeast severity);
+  ScopedStderrThreshold(const ScopedStderrThreshold&) = delete;
+  ScopedStderrThreshold& operator=(const ScopedStderrThreshold&) = delete;
+  ~ScopedStderrThreshold();
+
+ private:
+  absl::LogSeverityAtLeast saved_severity_;
+};
+
+//------------------------------------------------------------------------------
+// Log Backtrace At
+//------------------------------------------------------------------------------
+//
+// Users can request backtrace to be logged at specific locations, specified
+// by file and line number.
+
+// ShouldLogBacktraceAt()
+//
+// Returns true if we should log a backtrace at the specified location.
+namespace log_internal {
+ABSL_MUST_USE_RESULT bool ShouldLogBacktraceAt(absl::string_view file,
+                                               int line);
+}  // namespace log_internal
+
+// SetLogBacktraceLocation()
+//
+// Sets the location the backtrace should be logged at.
+void SetLogBacktraceLocation(absl::string_view file, int line);
+
+//------------------------------------------------------------------------------
+// Prepend Log Prefix
+//------------------------------------------------------------------------------
+//
+// This option tells the logging library that every logged message
+// should include the prefix (severity, date, time, PID, etc.)
+
+// ShouldPrependLogPrefix()
+//
+// Returns the value of the Prepend Log Prefix option.
+// This function is async-signal-safe.
+ABSL_MUST_USE_RESULT bool ShouldPrependLogPrefix();
+
+// EnableLogPrefix()
+//
+// Updates the value of the Prepend Log Prefix option.
+// This function is async-signal-safe.
+void EnableLogPrefix(bool on_off);
+
+namespace log_internal {
+
+using LoggingGlobalsListener = void (*)();
+void SetLoggingGlobalsListener(LoggingGlobalsListener l);
+
+// Internal implementation for the setter routines. These are used
+// to break circular dependencies between flags and globals. Each "Raw"
+// routine corresponds to the non-"Raw" counterpart and used to set the
+// configuration parameter directly without calling back to the listener.
+void RawSetMinLogLevel(absl::LogSeverityAtLeast severity);
+void RawSetStderrThreshold(absl::LogSeverityAtLeast severity);
+void RawEnableLogPrefix(bool on_off);
+
+}  // namespace log_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_LOG_GLOBALS_H_
diff --git a/absl/log/globals_test.cc b/absl/log/globals_test.cc
new file mode 100644
index 0000000..6710c5a
--- /dev/null
+++ b/absl/log/globals_test.cc
@@ -0,0 +1,91 @@
+//
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/globals.h"
+
+#include <string>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/attributes.h"
+#include "absl/base/log_severity.h"
+#include "absl/log/internal/globals.h"
+#include "absl/log/internal/test_helpers.h"
+#include "absl/log/log.h"
+#include "absl/log/scoped_mock_log.h"
+
+namespace {
+
+auto* test_env ABSL_ATTRIBUTE_UNUSED = ::testing::AddGlobalTestEnvironment(
+    new absl::log_internal::LogTestEnvironment);
+
+constexpr static absl::LogSeverityAtLeast DefaultMinLogLevel() {
+  return absl::LogSeverityAtLeast::kInfo;
+}
+constexpr static absl::LogSeverityAtLeast DefaultStderrThreshold() {
+  return absl::LogSeverityAtLeast::kError;
+}
+
+TEST(TestGlobals, MinLogLevel) {
+  EXPECT_EQ(absl::MinLogLevel(), DefaultMinLogLevel());
+  absl::SetMinLogLevel(absl::LogSeverityAtLeast::kError);
+  EXPECT_EQ(absl::MinLogLevel(), absl::LogSeverityAtLeast::kError);
+  absl::SetMinLogLevel(DefaultMinLogLevel());
+}
+
+TEST(TestGlobals, ScopedMinLogLevel) {
+  EXPECT_EQ(absl::MinLogLevel(), DefaultMinLogLevel());
+  {
+    absl::log_internal::ScopedMinLogLevel scoped_stderr_threshold(
+        absl::LogSeverityAtLeast::kError);
+    EXPECT_EQ(absl::MinLogLevel(), absl::LogSeverityAtLeast::kError);
+  }
+  EXPECT_EQ(absl::MinLogLevel(), DefaultMinLogLevel());
+}
+
+TEST(TestGlobals, StderrThreshold) {
+  EXPECT_EQ(absl::StderrThreshold(), DefaultStderrThreshold());
+  absl::SetStderrThreshold(absl::LogSeverityAtLeast::kError);
+  EXPECT_EQ(absl::StderrThreshold(), absl::LogSeverityAtLeast::kError);
+  absl::SetStderrThreshold(DefaultStderrThreshold());
+}
+
+TEST(TestGlobals, ScopedStderrThreshold) {
+  EXPECT_EQ(absl::StderrThreshold(), DefaultStderrThreshold());
+  {
+    absl::ScopedStderrThreshold scoped_stderr_threshold(
+        absl::LogSeverityAtLeast::kError);
+    EXPECT_EQ(absl::StderrThreshold(), absl::LogSeverityAtLeast::kError);
+  }
+  EXPECT_EQ(absl::StderrThreshold(), DefaultStderrThreshold());
+}
+
+TEST(TestGlobals, LogBacktraceAt) {
+  EXPECT_FALSE(absl::log_internal::ShouldLogBacktraceAt("some_file.cc", 111));
+  absl::SetLogBacktraceLocation("some_file.cc", 111);
+  EXPECT_TRUE(absl::log_internal::ShouldLogBacktraceAt("some_file.cc", 111));
+  EXPECT_FALSE(
+      absl::log_internal::ShouldLogBacktraceAt("another_file.cc", 222));
+}
+
+TEST(TestGlobals, LogPrefix) {
+  EXPECT_TRUE(absl::ShouldPrependLogPrefix());
+  absl::EnableLogPrefix(false);
+  EXPECT_FALSE(absl::ShouldPrependLogPrefix());
+  absl::EnableLogPrefix(true);
+  EXPECT_TRUE(absl::ShouldPrependLogPrefix());
+}
+
+}  // namespace
diff --git a/absl/log/initialize.cc b/absl/log/initialize.cc
new file mode 100644
index 0000000..a3f6d6c
--- /dev/null
+++ b/absl/log/initialize.cc
@@ -0,0 +1,34 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/initialize.h"
+
+#include "absl/base/config.h"
+#include "absl/log/internal/globals.h"
+#include "absl/time/time.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+void InitializeLog() {
+  // This comes first since it is used by RAW_LOG.
+  absl::log_internal::SetTimeZone(absl::LocalTimeZone());
+
+  // Note that initialization is complete, so logs can now be sent to their
+  // proper destinations rather than stderr.
+  log_internal::SetInitialized();
+}
+
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/log/initialize.h b/absl/log/initialize.h
new file mode 100644
index 0000000..f600eb6
--- /dev/null
+++ b/absl/log/initialize.h
@@ -0,0 +1,45 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/initialize.h
+// -----------------------------------------------------------------------------
+//
+// This header declares the Abseil Log initialization routine InitializeLog().
+
+#ifndef ABSL_LOG_INITIALIZE_H_
+#define ABSL_LOG_INITIALIZE_H_
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// InitializeLog()
+//
+// Initializes the Abseil logging library.
+//
+// Before this function is called, all log messages are directed only to stderr.
+// After initialization is finished, log messages are directed to all registered
+// `LogSink`s.
+//
+// It is an error to call this function twice.
+//
+// There is no corresponding function to shut down the logging library.
+void InitializeLog();
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_LOG_INITIALIZE_H_
diff --git a/absl/log/internal/BUILD.bazel b/absl/log/internal/BUILD.bazel
new file mode 100644
index 0000000..c674f28
--- /dev/null
+++ b/absl/log/internal/BUILD.bazel
@@ -0,0 +1,302 @@
+#
+# Copyright 2022 The Abseil Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+load(
+    "//absl:copts/configure_copts.bzl",
+    "ABSL_DEFAULT_COPTS",
+    "ABSL_DEFAULT_LINKOPTS",
+    "ABSL_TEST_COPTS",
+)
+
+package(default_visibility = [
+    "//absl/log:__pkg__",
+])
+
+licenses(["notice"])
+
+cc_library(
+    name = "check_op",
+    srcs = ["check_op.cc"],
+    hdrs = ["check_op.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    visibility = [
+        "//absl/log:__pkg__",
+    ],
+    deps = [
+        ":nullguard",
+        ":nullstream",
+        ":strip",
+        "//absl/base:config",
+        "//absl/base:core_headers",
+        "//absl/strings",
+    ],
+)
+
+cc_library(
+    name = "conditions",
+    srcs = ["conditions.cc"],
+    hdrs = ["conditions.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":voidify",
+        "//absl/base",
+        "//absl/base:config",
+        "//absl/base:core_headers",
+    ],
+)
+
+cc_library(
+    name = "config",
+    hdrs = ["config.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    visibility = [
+        "//absl/log:__pkg__",
+    ],
+    deps = [
+        "//absl/base:config",
+        "//absl/base:core_headers",
+    ],
+)
+
+cc_library(
+    name = "flags",
+    hdrs = ["flags.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        "//absl/flags:flag",
+    ],
+)
+
+cc_library(
+    name = "format",
+    srcs = ["log_format.cc"],
+    hdrs = ["log_format.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":config",
+        ":globals",
+        "//absl/base:config",
+        "//absl/base:core_headers",
+        "//absl/base:log_severity",
+        "//absl/strings",
+        "//absl/strings:str_format",
+        "//absl/time",
+        "//absl/types:span",
+    ],
+)
+
+cc_library(
+    name = "globals",
+    srcs = ["globals.cc"],
+    hdrs = ["globals.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    visibility = [
+        "//absl/log:__pkg__",
+    ],
+    deps = [
+        "//absl/base:config",
+        "//absl/base:core_headers",
+        "//absl/base:log_severity",
+        "//absl/base:raw_logging_internal",
+        "//absl/strings",
+        "//absl/time",
+    ],
+)
+
+cc_library(
+    name = "log_message",
+    srcs = ["log_message.cc"],
+    hdrs = ["log_message.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    visibility = [
+        "//absl/log:__pkg__",
+    ],
+    deps = [
+        ":config",
+        ":format",
+        ":globals",
+        ":log_sink_set",
+        ":nullguard",
+        "//absl/base",
+        "//absl/base:config",
+        "//absl/base:core_headers",
+        "//absl/base:errno_saver",
+        "//absl/base:log_severity",
+        "//absl/base:raw_logging_internal",
+        "//absl/base:strerror",
+        "//absl/container:inlined_vector",
+        "//absl/debugging:examine_stack",
+        "//absl/log:globals",
+        "//absl/log:log_entry",
+        "//absl/log:log_sink",
+        "//absl/log:log_sink_registry",
+        "//absl/memory",
+        "//absl/strings",
+        "//absl/strings:str_format",
+        "//absl/time",
+        "//absl/types:span",
+    ],
+)
+
+cc_library(
+    name = "log_sink_set",
+    srcs = ["log_sink_set.cc"],
+    hdrs = ["log_sink_set.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":config",
+        ":globals",
+        "//absl/base",
+        "//absl/base:config",
+        "//absl/base:core_headers",
+        "//absl/base:log_severity",
+        "//absl/base:raw_logging_internal",
+        "//absl/cleanup",
+        "//absl/log:globals",
+        "//absl/log:log_entry",
+        "//absl/log:log_sink",
+        "//absl/strings",
+        "//absl/synchronization",
+        "//absl/types:span",
+    ],
+)
+
+cc_library(
+    name = "nullguard",
+    hdrs = ["nullguard.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        "//absl/base:config",
+    ],
+)
+
+cc_library(
+    name = "nullstream",
+    hdrs = ["nullstream.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        "//absl/base:config",
+        "//absl/base:core_headers",
+        "//absl/base:log_severity",
+        "//absl/strings",
+    ],
+)
+
+cc_library(
+    name = "strip",
+    hdrs = ["strip.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":log_message",
+        ":nullstream",
+        "//absl/base:log_severity",
+    ],
+)
+
+cc_library(
+    name = "test_actions",
+    testonly = True,
+    srcs = ["test_actions.cc"],
+    hdrs = ["test_actions.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":config",
+        "//absl/base:config",
+        "//absl/base:log_severity",
+        "//absl/log:log_entry",
+        "//absl/strings",
+        "//absl/time",
+    ],
+)
+
+cc_library(
+    name = "test_helpers",
+    testonly = True,
+    srcs = ["test_helpers.cc"],
+    hdrs = ["test_helpers.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":globals",
+        "//absl/base:config",
+        "//absl/base:log_severity",
+        "//absl/log:globals",
+        "//absl/log:initialize",
+        "@com_google_googletest//:gtest",
+    ],
+)
+
+cc_library(
+    name = "test_matchers",
+    testonly = True,
+    srcs = ["test_matchers.cc"],
+    hdrs = ["test_matchers.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":config",
+        ":test_helpers",
+        "//absl/base:config",
+        "//absl/base:log_severity",
+        "//absl/log:log_entry",
+        "//absl/strings",
+        "//absl/time",
+        "@com_google_googletest//:gtest",
+    ],
+)
+
+cc_library(
+    name = "voidify",
+    hdrs = ["voidify.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = ["//absl/base:config"],
+)
+
+# Test targets
+cc_test(
+    name = "stderr_log_sink_test",
+    size = "small",
+    srcs = ["stderr_log_sink_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    tags = [
+        "no_test_android",
+        "no_test_darwin_x86_64",
+        "no_test_ios",
+        "no_test_wasm",
+    ],
+    deps = [
+        ":test_helpers",
+        "//absl/base:core_headers",
+        "//absl/base:log_severity",
+        "//absl/log",
+        "//absl/log:globals",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
diff --git a/absl/log/internal/check_op.cc b/absl/log/internal/check_op.cc
new file mode 100644
index 0000000..f4b6764
--- /dev/null
+++ b/absl/log/internal/check_op.cc
@@ -0,0 +1,118 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/internal/check_op.h"
+
+#include <string.h>
+
+#ifdef _MSC_VER
+#define strcasecmp _stricmp
+#else
+#include <strings.h>  // for strcasecmp, but msvc does not have this header
+#endif
+
+#include <sstream>
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/strings/str_cat.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+#define ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(x) \
+  template std::string* MakeCheckOpString(x, x, const char*)
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(bool);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(int64_t);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(uint64_t);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(float);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(double);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(char);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(unsigned char);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const std::string&);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const absl::string_view&);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const char*);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const signed char*);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const unsigned char*);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const void*);
+#undef ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING
+
+CheckOpMessageBuilder::CheckOpMessageBuilder(const char* exprtext) {
+  stream_ << exprtext << " (";
+}
+
+std::ostream& CheckOpMessageBuilder::ForVar2() {
+  stream_ << " vs. ";
+  return stream_;
+}
+
+std::string* CheckOpMessageBuilder::NewString() {
+  stream_ << ")";
+  return new std::string(stream_.str());
+}
+
+void MakeCheckOpValueString(std::ostream& os, const char v) {
+  if (v >= 32 && v <= 126) {
+    os << "'" << v << "'";
+  } else {
+    os << "char value " << int{v};
+  }
+}
+
+void MakeCheckOpValueString(std::ostream& os, const signed char v) {
+  if (v >= 32 && v <= 126) {
+    os << "'" << v << "'";
+  } else {
+    os << "signed char value " << int{v};
+  }
+}
+
+void MakeCheckOpValueString(std::ostream& os, const unsigned char v) {
+  if (v >= 32 && v <= 126) {
+    os << "'" << v << "'";
+  } else {
+    os << "unsigned char value " << int{v};
+  }
+}
+
+void MakeCheckOpValueString(std::ostream& os, const void* p) {
+  if (p == nullptr) {
+    os << "(null)";
+  } else {
+    os << p;
+  }
+}
+
+// Helper functions for string comparisons.
+#define DEFINE_CHECK_STROP_IMPL(name, func, expected)                      \
+  std::string* Check##func##expected##Impl(const char* s1, const char* s2, \
+                                           const char* exprtext) {         \
+    bool equal = s1 == s2 || (s1 && s2 && !func(s1, s2));                  \
+    if (equal == expected) {                                               \
+      return nullptr;                                                      \
+    } else {                                                               \
+      return new std::string(                                              \
+          absl::StrCat(exprtext, " (", s1, " vs. ", s2, ")"));             \
+    }                                                                      \
+  }
+DEFINE_CHECK_STROP_IMPL(CHECK_STREQ, strcmp, true)
+DEFINE_CHECK_STROP_IMPL(CHECK_STRNE, strcmp, false)
+DEFINE_CHECK_STROP_IMPL(CHECK_STRCASEEQ, strcasecmp, true)
+DEFINE_CHECK_STROP_IMPL(CHECK_STRCASENE, strcasecmp, false)
+#undef DEFINE_CHECK_STROP_IMPL
+
+}  // namespace log_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/log/internal/check_op.h b/absl/log/internal/check_op.h
new file mode 100644
index 0000000..559e5af
--- /dev/null
+++ b/absl/log/internal/check_op.h
@@ -0,0 +1,385 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/check_op.h
+// -----------------------------------------------------------------------------
+//
+// This file declares helpers routines and macros used to implement `CHECK`
+// macros.
+
+#ifndef ABSL_LOG_INTERNAL_CHECK_OP_H_
+#define ABSL_LOG_INTERNAL_CHECK_OP_H_
+
+#include <stdint.h>
+
+#include <ostream>
+#include <sstream>
+#include <string>
+#include <utility>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/optimization.h"
+#include "absl/log/internal/nullguard.h"
+#include "absl/log/internal/nullstream.h"
+#include "absl/log/internal/strip.h"
+
+// `ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL` wraps string literals that
+// should be stripped when `ABSL_MIN_LOG_LEVEL` exceeds `kFatal`.
+#ifdef ABSL_MIN_LOG_LEVEL
+#define ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(literal)         \
+  (::absl::LogSeverity::kFatal >=                               \
+           static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) \
+       ? (literal)                                              \
+       : "")
+#else
+#define ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(literal) (literal)
+#endif
+
+#ifdef NDEBUG
+// `NDEBUG` is defined, so `DCHECK_EQ(x, y)` and so on do nothing.  However, we
+// still want the compiler to parse `x` and `y`, because we don't want to lose
+// potentially useful errors and warnings.
+#define ABSL_LOG_INTERNAL_DCHECK_NOP(x, y)   \
+  while (false && ((void)(x), (void)(y), 0)) \
+  ::absl::log_internal::NullStream().InternalStream()
+#endif
+
+#define ABSL_LOG_INTERNAL_CHECK_OP(name, op, val1, val2)                       \
+  while (                                                                      \
+      ::std::string* absl_log_internal_check_op_result ABSL_ATTRIBUTE_UNUSED = \
+          ::absl::log_internal::name##Impl(                                    \
+              ::absl::log_internal::GetReferenceableValue(val1),               \
+              ::absl::log_internal::GetReferenceableValue(val2),               \
+              ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(#val1 " " #op             \
+                                                           " " #val2)))        \
+  ABSL_LOG_INTERNAL_CHECK(*absl_log_internal_check_op_result).InternalStream()
+#define ABSL_LOG_INTERNAL_QCHECK_OP(name, op, val1, val2)                  \
+  while (::std::string* absl_log_internal_qcheck_op_result =               \
+             ::absl::log_internal::name##Impl(                             \
+                 ::absl::log_internal::GetReferenceableValue(val1),        \
+                 ::absl::log_internal::GetReferenceableValue(val2),        \
+                 ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(#val1 " " #op      \
+                                                              " " #val2))) \
+  ABSL_LOG_INTERNAL_QCHECK(*absl_log_internal_qcheck_op_result).InternalStream()
+#define ABSL_LOG_INTERNAL_CHECK_STROP(func, op, expected, s1, s2)              \
+  while (::std::string* absl_log_internal_check_strop_result =                 \
+             ::absl::log_internal::Check##func##expected##Impl(                \
+                 (s1), (s2),                                                   \
+                 ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(#s1 " " #op " " #s2))) \
+  ABSL_LOG_INTERNAL_CHECK(*absl_log_internal_check_strop_result)               \
+      .InternalStream()
+#define ABSL_LOG_INTERNAL_QCHECK_STROP(func, op, expected, s1, s2)             \
+  while (::std::string* absl_log_internal_qcheck_strop_result =                \
+             ::absl::log_internal::Check##func##expected##Impl(                \
+                 (s1), (s2),                                                   \
+                 ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(#s1 " " #op " " #s2))) \
+  ABSL_LOG_INTERNAL_QCHECK(*absl_log_internal_qcheck_strop_result)             \
+      .InternalStream()
+// This one is tricky:
+// * We must evaluate `val` exactly once, yet we need to do two things with it:
+//   evaluate `.ok()` and (sometimes) `.ToString()`.
+// * `val` might be an `absl::Status` or some `absl::StatusOr<T>`.
+// * `val` might be e.g. `ATemporary().GetStatus()`, which may return a
+//   reference to a member of `ATemporary` that is only valid until the end of
+//   the full expression.
+// * We don't want this file to depend on `absl::Status` `#include`s or linkage,
+//   nor do we want to move the definition to status and introduce a dependency
+//   in the other direction.  We can be assured that callers must already have a
+//   `Status` and the necessary `#include`s and linkage.
+// * Callsites should be small and fast (at least when `val.ok()`): one branch,
+//   minimal stack footprint.
+//   * In particular, the string concat stuff should be out-of-line and emitted
+//     in only one TU to save linker input size
+// * We want the `val.ok()` check inline so static analyzers and optimizers can
+//   see it.
+// * As usual, no braces so we can stream into the expansion with `operator<<`.
+// * Also as usual, it must expand to a single (partial) statement with no
+//   ambiguous-else problems.
+#define ABSL_LOG_INTERNAL_CHECK_OK(val)                                      \
+  for (::std::pair<const ::absl::Status*, ::std::string*>                    \
+           absl_log_internal_check_ok_goo;                                   \
+       absl_log_internal_check_ok_goo.first =                                \
+           ::absl::log_internal::AsStatus(val),                              \
+       absl_log_internal_check_ok_goo.second =                               \
+           ABSL_PREDICT_TRUE(absl_log_internal_check_ok_goo.first->ok())     \
+               ? nullptr                                                     \
+               : ::absl::status_internal::MakeCheckFailString(               \
+                     absl_log_internal_check_ok_goo.first,                   \
+                     ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(#val " is OK")), \
+       !ABSL_PREDICT_TRUE(absl_log_internal_check_ok_goo.first->ok());)      \
+  ABSL_LOG_INTERNAL_CHECK(*absl_log_internal_check_ok_goo.second)            \
+      .InternalStream()
+#define ABSL_LOG_INTERNAL_QCHECK_OK(val)                                     \
+  for (::std::pair<const ::absl::Status*, ::std::string*>                    \
+           absl_log_internal_check_ok_goo;                                   \
+       absl_log_internal_check_ok_goo.first =                                \
+           ::absl::log_internal::AsStatus(val),                              \
+       absl_log_internal_check_ok_goo.second =                               \
+           ABSL_PREDICT_TRUE(absl_log_internal_check_ok_goo.first->ok())     \
+               ? nullptr                                                     \
+               : ::absl::status_internal::MakeCheckFailString(               \
+                     absl_log_internal_check_ok_goo.first,                   \
+                     ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(#val " is OK")), \
+       !ABSL_PREDICT_TRUE(absl_log_internal_check_ok_goo.first->ok());)      \
+  ABSL_LOG_INTERNAL_QCHECK(*absl_log_internal_check_ok_goo.second)           \
+      .InternalStream()
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+class Status;
+template <typename T>
+class StatusOr;
+
+namespace status_internal {
+std::string* MakeCheckFailString(const absl::Status* status,
+                                 const char* prefix);
+}  // namespace status_internal
+
+namespace log_internal {
+
+// Convert a Status or a StatusOr to its underlying status value.
+//
+// (This implementation does not require a dep on absl::Status to work.)
+inline const absl::Status* AsStatus(const absl::Status& s) { return &s; }
+template <typename T>
+const absl::Status* AsStatus(const absl::StatusOr<T>& s) {
+  return &s.status();
+}
+
+// A helper class for formatting `expr (V1 vs. V2)` in a `CHECK_XX` statement.
+// See `MakeCheckOpString` for sample usage.
+class CheckOpMessageBuilder final {
+ public:
+  // Inserts `exprtext` and ` (` to the stream.
+  explicit CheckOpMessageBuilder(const char* exprtext);
+  ~CheckOpMessageBuilder() = default;
+  // For inserting the first variable.
+  std::ostream& ForVar1() { return stream_; }
+  // For inserting the second variable (adds an intermediate ` vs. `).
+  std::ostream& ForVar2();
+  // Get the result (inserts the closing `)`).
+  std::string* NewString();
+
+ private:
+  std::ostringstream stream_;
+};
+
+// This formats a value for a failing `CHECK_XX` statement.  Ordinarily, it uses
+// the definition for `operator<<`, with a few special cases below.
+template <typename T>
+inline void MakeCheckOpValueString(std::ostream& os, const T& v) {
+  os << log_internal::NullGuard<T>::Guard(v);
+}
+
+// Overloads for char types provide readable values for unprintable characters.
+void MakeCheckOpValueString(std::ostream& os, char v);
+void MakeCheckOpValueString(std::ostream& os, signed char v);
+void MakeCheckOpValueString(std::ostream& os, unsigned char v);
+void MakeCheckOpValueString(std::ostream& os, const void* p);
+
+namespace detect_specialization {
+
+// MakeCheckOpString is being specialized for every T and U pair that is being
+// passed to the CHECK_op macros. However, there is a lot of redundancy in these
+// specializations that creates unnecessary library and binary bloat.
+// The number of instantiations tends to be O(n^2) because we have two
+// independent inputs. This technique works by reducing `n`.
+//
+// Most user-defined types being passed to CHECK_op end up being printed as a
+// builtin type. For example, enums tend to be implicitly converted to its
+// underlying type when calling operator<<, and pointers are printed with the
+// `const void*` overload.
+// To reduce the number of instantiations we coerce these values before calling
+// MakeCheckOpString instead of inside it.
+//
+// To detect if this coercion is needed, we duplicate all the relevant
+// operator<< overloads as specified in the standard, just in a different
+// namespace. If the call to `stream << value` becomes ambiguous, it means that
+// one of these overloads is the one selected by overload resolution. We then
+// do overload resolution again just with our overload set to see which one gets
+// selected. That tells us which type to coerce to.
+// If the augmented call was not ambiguous, it means that none of these were
+// selected and we can't coerce the input.
+//
+// As a secondary step to reduce code duplication, we promote integral types to
+// their 64-bit variant. This does not change the printed value, but reduces the
+// number of instantiations even further. Promoting an integer is very cheap at
+// the call site.
+int64_t operator<<(std::ostream&, short value);           // NOLINT
+int64_t operator<<(std::ostream&, unsigned short value);  // NOLINT
+int64_t operator<<(std::ostream&, int value);
+int64_t operator<<(std::ostream&, unsigned int value);
+int64_t operator<<(std::ostream&, long value);                 // NOLINT
+uint64_t operator<<(std::ostream&, unsigned long value);       // NOLINT
+int64_t operator<<(std::ostream&, long long value);            // NOLINT
+uint64_t operator<<(std::ostream&, unsigned long long value);  // NOLINT
+float operator<<(std::ostream&, float value);
+double operator<<(std::ostream&, double value);
+long double operator<<(std::ostream&, long double value);
+bool operator<<(std::ostream&, bool value);
+const void* operator<<(std::ostream&, const void* value);
+const void* operator<<(std::ostream&, std::nullptr_t);
+
+// These `char` overloads are specified like this in the standard, so we have to
+// write them exactly the same to ensure the call is ambiguous.
+// If we wrote it in a different way (eg taking std::ostream instead of the
+// template) then one call might have a higher rank than the other and it would
+// not be ambiguous.
+template <typename Traits>
+char operator<<(std::basic_ostream<char, Traits>&, char);
+template <typename Traits>
+signed char operator<<(std::basic_ostream<char, Traits>&, signed char);
+template <typename Traits>
+unsigned char operator<<(std::basic_ostream<char, Traits>&, unsigned char);
+template <typename Traits>
+const char* operator<<(std::basic_ostream<char, Traits>&, const char*);
+template <typename Traits>
+const signed char* operator<<(std::basic_ostream<char, Traits>&,
+                              const signed char*);
+template <typename Traits>
+const unsigned char* operator<<(std::basic_ostream<char, Traits>&,
+                                const unsigned char*);
+
+// This overload triggers when the call is not ambiguous.
+// It means that T is being printed with some overload not on this list.
+// We keep the value as `const T&`.
+template <typename T, typename = decltype(std::declval<std::ostream&>()
+                                          << std::declval<const T&>())>
+const T& Detect(int);
+
+// This overload triggers when the call is ambiguous.
+// It means that T is either one from this list or printed as one from this
+// list. Eg an enum that decays to `int` for printing.
+// We ask the overload set to give us the type we want to convert it to.
+template <typename T>
+decltype(detect_specialization::operator<<(std::declval<std::ostream&>(),
+                                           std::declval<const T&>()))
+Detect(char);
+
+}  // namespace detect_specialization
+
+template <typename T>
+using CheckOpStreamType = decltype(detect_specialization::Detect<T>(0));
+
+// Build the error message string.  Specify no inlining for code size.
+template <typename T1, typename T2>
+ABSL_ATTRIBUTE_RETURNS_NONNULL std::string* MakeCheckOpString(
+    T1 v1, T2 v2, const char* exprtext) ABSL_ATTRIBUTE_NOINLINE;
+
+template <typename T1, typename T2>
+std::string* MakeCheckOpString(T1 v1, T2 v2, const char* exprtext) {
+  CheckOpMessageBuilder comb(exprtext);
+  MakeCheckOpValueString(comb.ForVar1(), v1);
+  MakeCheckOpValueString(comb.ForVar2(), v2);
+  return comb.NewString();
+}
+
+// Add a few commonly used instantiations as extern to reduce size of objects
+// files.
+#define ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(x) \
+  extern template std::string* MakeCheckOpString(x, x, const char*)
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(bool);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(int64_t);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(uint64_t);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(float);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(double);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(char);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(unsigned char);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const std::string&);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const absl::string_view&);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const char*);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const signed char*);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const unsigned char*);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const void*);
+#undef ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN
+
+// Helper functions for `ABSL_LOG_INTERNAL_CHECK_OP` macro family.  The
+// `(int, int)` override works around the issue that the compiler will not
+// instantiate the template version of the function on values of unnamed enum
+// type.
+#define ABSL_LOG_INTERNAL_CHECK_OP_IMPL(name, op)                        \
+  template <typename T1, typename T2>                                    \
+  inline constexpr ::std::string* name##Impl(const T1& v1, const T2& v2, \
+                                             const char* exprtext) {     \
+    using U1 = CheckOpStreamType<T1>;                                    \
+    using U2 = CheckOpStreamType<T2>;                                    \
+    return ABSL_PREDICT_TRUE(v1 op v2)                                   \
+               ? nullptr                                                 \
+               : MakeCheckOpString<U1, U2>(v1, v2, exprtext);            \
+  }                                                                      \
+  inline constexpr ::std::string* name##Impl(int v1, int v2,             \
+                                             const char* exprtext) {     \
+    return name##Impl<int, int>(v1, v2, exprtext);                       \
+  }
+
+ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_EQ, ==)
+ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_NE, !=)
+ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_LE, <=)
+ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_LT, <)
+ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_GE, >=)
+ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_GT, >)
+#undef ABSL_LOG_INTERNAL_CHECK_OP_IMPL
+
+std::string* CheckstrcmptrueImpl(const char* s1, const char* s2,
+                                 const char* exprtext);
+std::string* CheckstrcmpfalseImpl(const char* s1, const char* s2,
+                                  const char* exprtext);
+std::string* CheckstrcasecmptrueImpl(const char* s1, const char* s2,
+                                     const char* exprtext);
+std::string* CheckstrcasecmpfalseImpl(const char* s1, const char* s2,
+                                      const char* exprtext);
+
+// `CHECK_EQ` and friends want to pass their arguments by reference, however
+// this winds up exposing lots of cases where people have defined and
+// initialized static const data members but never declared them (i.e. in a .cc
+// file), meaning they are not referenceable.  This function avoids that problem
+// for integers (the most common cases) by overloading for every primitive
+// integer type, even the ones we discourage, and returning them by value.
+template <typename T>
+inline constexpr const T& GetReferenceableValue(const T& t) {
+  return t;
+}
+inline constexpr char GetReferenceableValue(char t) { return t; }
+inline constexpr unsigned char GetReferenceableValue(unsigned char t) {
+  return t;
+}
+inline constexpr signed char GetReferenceableValue(signed char t) { return t; }
+inline constexpr short GetReferenceableValue(short t) { return t; }  // NOLINT
+inline constexpr unsigned short GetReferenceableValue(               // NOLINT
+    unsigned short t) {                                              // NOLINT
+  return t;
+}
+inline constexpr int GetReferenceableValue(int t) { return t; }
+inline unsigned int GetReferenceableValue(unsigned int t) { return t; }
+inline constexpr long GetReferenceableValue(long t) { return t; }  // NOLINT
+inline constexpr unsigned long GetReferenceableValue(              // NOLINT
+    unsigned long t) {                                             // NOLINT
+  return t;
+}
+inline constexpr long long GetReferenceableValue(long long t) {  // NOLINT
+  return t;
+}
+inline constexpr unsigned long long GetReferenceableValue(  // NOLINT
+    unsigned long long t) {                                 // NOLINT
+  return t;
+}
+
+}  // namespace log_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_LOG_INTERNAL_CHECK_OP_H_
diff --git a/absl/log/internal/conditions.cc b/absl/log/internal/conditions.cc
new file mode 100644
index 0000000..70f2ace
--- /dev/null
+++ b/absl/log/internal/conditions.cc
@@ -0,0 +1,83 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/internal/conditions.h"
+
+#include <atomic>
+#include <cstdint>
+
+#include "absl/base/config.h"
+#include "absl/base/internal/cycleclock.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+namespace {
+
+// The following code behaves like AtomicStatsCounter::LossyAdd() for
+// speed since it is fine to lose occasional updates.
+// Returns old value of *counter.
+uint32_t LossyIncrement(std::atomic<uint32_t>* counter) {
+  const uint32_t value = counter->load(std::memory_order_relaxed);
+  counter->store(value + 1, std::memory_order_relaxed);
+  return value;
+}
+
+}  // namespace
+
+bool LogEveryNState::ShouldLog(int n) {
+  return n != 0 && (LossyIncrement(&counter_) % n) == 0;
+}
+
+bool LogFirstNState::ShouldLog(int n) {
+  const uint32_t counter_value = counter_.load(std::memory_order_relaxed);
+  if (static_cast<int64_t>(counter_value) < n) {
+    counter_.store(counter_value + 1, std::memory_order_relaxed);
+    return true;
+  }
+  return false;
+}
+
+bool LogEveryPow2State::ShouldLog() {
+  const uint32_t new_value = LossyIncrement(&counter_) + 1;
+  return (new_value & (new_value - 1)) == 0;
+}
+
+bool LogEveryNSecState::ShouldLog(double seconds) {
+  using absl::base_internal::CycleClock;
+  LossyIncrement(&counter_);
+  const int64_t now_cycles = CycleClock::Now();
+  int64_t next_cycles = next_log_time_cycles_.load(std::memory_order_relaxed);
+#if defined(__myriad2__)
+  // myriad2 does not have 8-byte compare and exchange.  Use a racy version that
+  // is "good enough" but will over-log in the face of concurrent logging.
+  if (now_cycles > next_cycles) {
+    next_log_time_cycles_.store(now_cycles + seconds * CycleClock::Frequency(),
+                                std::memory_order_relaxed);
+    return true;
+  }
+  return false;
+#else
+  do {
+    if (now_cycles <= next_cycles) return false;
+  } while (!next_log_time_cycles_.compare_exchange_weak(
+      next_cycles, now_cycles + seconds * CycleClock::Frequency(),
+      std::memory_order_relaxed, std::memory_order_relaxed));
+  return true;
+#endif
+}
+
+}  // namespace log_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/log/internal/conditions.h b/absl/log/internal/conditions.h
new file mode 100644
index 0000000..b89f1df
--- /dev/null
+++ b/absl/log/internal/conditions.h
@@ -0,0 +1,222 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/conditions.h
+// -----------------------------------------------------------------------------
+//
+// This file contains implementation of conditional log statements, like LOG_IF
+// including all the ABSL_LOG_INTERNAL_..._CONDITION_... macros and
+// various condition classes like LogEveryNState.
+
+#ifndef ABSL_LOG_INTERNAL_CONDITIONS_H_
+#define ABSL_LOG_INTERNAL_CONDITIONS_H_
+
+#ifdef _WIN32
+#include <cstdlib>
+#else
+#include <unistd.h>
+#endif
+#include <stdlib.h>
+
+#include <atomic>
+#include <cstdint>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/log/internal/voidify.h"
+
+// `ABSL_LOG_INTERNAL_CONDITION` prefixes another macro that expands to a
+// temporary `LogMessage` instantiation followed by zero or more streamed
+// expressions.  This definition is tricky to read correctly.  It evaluates to
+// either
+//
+//   (void)0;
+//
+// or
+//
+//   ::absl::log_internal::Voidify() &&
+//       ::absl::log_internal::LogMessage(...) << "the user's message";
+//
+// If the condition is evaluable at compile time, as is often the case, it
+// compiles away to just one side or the other.
+//
+// Although this is not used anywhere a statement (e.g. `if`) could not go,
+// the ternary expression does a better job avoiding spurious diagnostics
+// (dangling else, missing switch case) and preserving noreturn semantics (e.g.
+// on `LOG(FATAL)`) without requiring braces.
+#define ABSL_LOG_INTERNAL_STATELESS_CONDITION(condition) \
+  switch (0)                                             \
+  case 0:                                                \
+    !(condition) ? (void)0 : ::absl::log_internal::Voidify()&&
+
+// `ABSL_LOG_INTERNAL_STATEFUL_CONDITION` applies a condition like
+// `ABSL_LOG_INTERNAL_CONDITION` but adds to that a series of variable
+// declarations, including a local static object which stores the state needed
+// to implement the stateful macros like `LOG_EVERY_N`.
+//
+// `for`-loops are used to declare scoped variables without braces (to permit
+// streaming into the macro's expansion) and without the dangling-`else`
+// problems/diagnostics that come with `if`.
+//
+// Two more variables are declared in separate `for`-loops:
+//
+// * `COUNTER` implements a streamable token whose value when streamed is the
+//   number of times execution has passed through the macro.
+// * A boolean flag is used to prevent any of the `for`-loops from ever actually
+//   looping.
+#define ABSL_LOG_INTERNAL_STATEFUL_CONDITION(condition)             \
+  for (bool absl_log_internal_stateful_condition_do_log(condition); \
+       absl_log_internal_stateful_condition_do_log;                 \
+       absl_log_internal_stateful_condition_do_log = false)         \
+  ABSL_LOG_INTERNAL_STATEFUL_CONDITION_IMPL
+#define ABSL_LOG_INTERNAL_STATEFUL_CONDITION_IMPL(kind, ...)              \
+  for (static ::absl::log_internal::Log##kind##State                      \
+           absl_log_internal_stateful_condition_state;                    \
+       absl_log_internal_stateful_condition_do_log &&                     \
+       absl_log_internal_stateful_condition_state.ShouldLog(__VA_ARGS__); \
+       absl_log_internal_stateful_condition_do_log = false)               \
+    for (const uint32_t COUNTER ABSL_ATTRIBUTE_UNUSED =                   \
+             absl_log_internal_stateful_condition_state.counter();        \
+         absl_log_internal_stateful_condition_do_log;                     \
+         absl_log_internal_stateful_condition_do_log = false)
+
+// `ABSL_LOG_INTERNAL_CONDITION_*` serve to combine any conditions from the
+// macro (e.g. `LOG_IF` or `VLOG`) with inherent conditions (e.g.
+// `ABSL_MIN_LOG_LEVEL`) into a single boolean expression.  We could chain
+// ternary operators instead, however some versions of Clang sometimes issue
+// spurious diagnostics after such expressions due to a control flow analysis
+// bug.
+#ifdef ABSL_MIN_LOG_LEVEL
+#define ABSL_LOG_INTERNAL_CONDITION_INFO(type, condition) \
+  ABSL_LOG_INTERNAL_##type##_CONDITION(                   \
+      (condition) && ::absl::LogSeverity::kInfo >=        \
+                         static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL))
+#define ABSL_LOG_INTERNAL_CONDITION_WARNING(type, condition) \
+  ABSL_LOG_INTERNAL_##type##_CONDITION(                      \
+      (condition) && ::absl::LogSeverity::kWarning >=        \
+                         static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL))
+#define ABSL_LOG_INTERNAL_CONDITION_ERROR(type, condition) \
+  ABSL_LOG_INTERNAL_##type##_CONDITION(                    \
+      (condition) && ::absl::LogSeverity::kError >=        \
+                         static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL))
+// NOTE: Use ternary operators instead of short-circuiting to mitigate
+// https://bugs.llvm.org/show_bug.cgi?id=51928.
+#define ABSL_LOG_INTERNAL_CONDITION_FATAL(type, condition)                 \
+  ABSL_LOG_INTERNAL_##type##_CONDITION(                                    \
+      ((condition)                                                         \
+           ? (::absl::LogSeverity::kFatal >=                               \
+                      static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) \
+                  ? true                                                   \
+                  : (::absl::log_internal::AbortQuietly(), false))         \
+           : false))
+// NOTE: Use ternary operators instead of short-circuiting to mitigate
+// https://bugs.llvm.org/show_bug.cgi?id=51928.
+#define ABSL_LOG_INTERNAL_CONDITION_QFATAL(type, condition)                \
+  ABSL_LOG_INTERNAL_##type##_CONDITION(                                    \
+      ((condition)                                                         \
+           ? (::absl::LogSeverity::kFatal >=                               \
+                      static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) \
+                  ? true                                                   \
+                  : (::absl::log_internal::ExitQuietly(), false))          \
+           : false))
+
+#define ABSL_LOG_INTERNAL_CONDITION_LEVEL(severity)                    \
+  for (int log_internal_severity_loop = 1; log_internal_severity_loop; \
+       log_internal_severity_loop = 0)                                 \
+    for (const absl::LogSeverity log_internal_severity =               \
+             ::absl::NormalizeLogSeverity(severity);                   \
+         log_internal_severity_loop; log_internal_severity_loop = 0)   \
+  ABSL_LOG_INTERNAL_CONDITION_LEVEL_IMPL
+#define ABSL_LOG_INTERNAL_CONDITION_LEVEL_IMPL(type, condition)    \
+  ABSL_LOG_INTERNAL_##type##_CONDITION(                            \
+      (condition) &&                                               \
+      (log_internal_severity >=                                    \
+           static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) || \
+       (log_internal_severity == ::absl::LogSeverity::kFatal &&    \
+        (::absl::log_internal::AbortQuietly(), false))))
+#else  // ndef ABSL_MIN_LOG_LEVEL
+#define ABSL_LOG_INTERNAL_CONDITION_INFO(type, condition) \
+  ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
+#define ABSL_LOG_INTERNAL_CONDITION_WARNING(type, condition) \
+  ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
+#define ABSL_LOG_INTERNAL_CONDITION_ERROR(type, condition) \
+  ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
+#define ABSL_LOG_INTERNAL_CONDITION_FATAL(type, condition) \
+  ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
+#define ABSL_LOG_INTERNAL_CONDITION_QFATAL(type, condition) \
+  ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
+#define ABSL_LOG_INTERNAL_CONDITION_LEVEL(severity)                    \
+  for (int log_internal_severity_loop = 1; log_internal_severity_loop; \
+       log_internal_severity_loop = 0)                                 \
+    for (const absl::LogSeverity log_internal_severity =               \
+             ::absl::NormalizeLogSeverity(severity);                   \
+         log_internal_severity_loop; log_internal_severity_loop = 0)   \
+  ABSL_LOG_INTERNAL_CONDITION_LEVEL_IMPL
+#define ABSL_LOG_INTERNAL_CONDITION_LEVEL_IMPL(type, condition) \
+  ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
+#endif  // ndef ABSL_MIN_LOG_LEVEL
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+// Stateful condition class name should be "Log" + name + "State".
+class LogEveryNState final {
+ public:
+  bool ShouldLog(int n);
+  uint32_t counter() { return counter_.load(std::memory_order_relaxed); }
+
+ private:
+  std::atomic<uint32_t> counter_{0};
+};
+
+class LogFirstNState final {
+ public:
+  bool ShouldLog(int n);
+  uint32_t counter() { return counter_.load(std::memory_order_relaxed); }
+
+ private:
+  std::atomic<uint32_t> counter_{0};
+};
+
+class LogEveryPow2State final {
+ public:
+  bool ShouldLog();
+  uint32_t counter() { return counter_.load(std::memory_order_relaxed); }
+
+ private:
+  std::atomic<uint32_t> counter_{0};
+};
+
+class LogEveryNSecState final {
+ public:
+  bool ShouldLog(double seconds);
+  uint32_t counter() { return counter_.load(std::memory_order_relaxed); }
+
+ private:
+  std::atomic<uint32_t> counter_{0};
+  // Cycle count according to CycleClock that we should next log at.
+  std::atomic<int64_t> next_log_time_cycles_{0};
+};
+
+// Helper routines to abort the application quietly
+
+ABSL_ATTRIBUTE_NORETURN inline void AbortQuietly() { abort(); }
+ABSL_ATTRIBUTE_NORETURN inline void ExitQuietly() { _exit(1); }
+}  // namespace log_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_LOG_INTERNAL_CONDITIONS_H_
diff --git a/absl/log/internal/config.h b/absl/log/internal/config.h
new file mode 100644
index 0000000..379e9ab
--- /dev/null
+++ b/absl/log/internal/config.h
@@ -0,0 +1,45 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/config.h
+// -----------------------------------------------------------------------------
+//
+
+#ifndef ABSL_LOG_INTERNAL_CONFIG_H_
+#define ABSL_LOG_INTERNAL_CONFIG_H_
+
+#include "absl/base/config.h"
+
+#ifdef _WIN32
+#include <cstdint>
+#else
+#include <sys/types.h>
+#endif
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+#ifdef _WIN32
+using Tid = uint32_t;
+#else
+using Tid = pid_t;
+#endif
+
+}  // namespace log_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_LOG_INTERNAL_CONFIG_H_
diff --git a/absl/log/internal/flags.h b/absl/log/internal/flags.h
new file mode 100644
index 0000000..0c5e81e
--- /dev/null
+++ b/absl/log/internal/flags.h
@@ -0,0 +1,53 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/log_flags.h
+// -----------------------------------------------------------------------------
+//
+// This header declares set of flags which can be used to configure Abseil
+// Logging library behaviour at runtime.
+
+#ifndef ABSL_LOG_INTERNAL_FLAGS_H_
+#define ABSL_LOG_INTERNAL_FLAGS_H_
+
+#include <string>
+
+#include "absl/flags/declare.h"
+
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+// These flags should not be used in C++ code to access logging library
+// configuration knobs. Use interfaces defined in absl/log/globals.h
+// instead. It is still ok to use these flags on a command line.
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+// Log messages at this severity or above are sent to stderr in *addition* to
+// logfiles.  Defaults to `ERROR`.  See log_severity.h for numeric values of
+// severity levels.
+ABSL_DECLARE_FLAG(int, stderrthreshold);
+
+// Log messages at this severity or above are logged; others are discarded.
+// Defaults to `INFO`, i.e. log all severities.  See log_severity.h for numeric
+// values of severity levels.
+ABSL_DECLARE_FLAG(int, minloglevel);
+
+// If specified in the form file:linenum, any messages logged from a matching
+// location will also include a backtrace.
+ABSL_DECLARE_FLAG(std::string, log_backtrace_at);
+
+// If true, the log prefix (severity, date, time, PID, etc.) is prepended to
+// each message logged. Defaults to true.
+ABSL_DECLARE_FLAG(bool, log_prefix);
+
+#endif  // ABSL_LOG_INTERNAL_FLAGS_H_
diff --git a/absl/log/internal/globals.cc b/absl/log/internal/globals.cc
new file mode 100644
index 0000000..863b047
--- /dev/null
+++ b/absl/log/internal/globals.cc
@@ -0,0 +1,125 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/internal/globals.h"
+
+#include <atomic>
+#include <cstdio>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/base/log_severity.h"
+#include "absl/strings/string_view.h"
+#include "absl/time/time.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+namespace {
+// Keeps track of whether Logging initialization is finalized.
+// Log messages generated before that will go to stderr.
+ABSL_CONST_INIT std::atomic<bool> logging_initialized(false);
+
+// The TimeZone used for logging. This may only be set once.
+ABSL_CONST_INIT std::atomic<absl::TimeZone*> timezone_ptr{nullptr};
+
+// If true, the logging library will symbolize stack in fatal messages
+ABSL_CONST_INIT std::atomic<bool> symbolize_stack_trace(true);
+
+// Specifies maximum number of stack frames to report in fatal messages.
+ABSL_CONST_INIT std::atomic<int> max_frames_in_stack_trace(64);
+
+ABSL_CONST_INIT std::atomic<bool> exit_on_dfatal(true);
+ABSL_CONST_INIT std::atomic<bool> suppress_sigabort_trace(false);
+}  // namespace
+
+bool IsInitialized() {
+  return logging_initialized.load(std::memory_order_acquire);
+}
+
+void SetInitialized() {
+  logging_initialized.store(true, std::memory_order_release);
+}
+
+void WriteToStderr(absl::string_view message, absl::LogSeverity severity) {
+  // Avoid using std::cerr from this module since we may get called during
+  // exit code, and cerr may be partially or fully destroyed by then.
+  std::fwrite(message.data(), message.size(), 1, stderr);
+
+#if defined(_WIN64) || defined(_WIN32) || defined(_WIN16)
+  // C99 requires stderr to not be fully-buffered by default (7.19.3.7), but
+  // MS CRT buffers it anyway, so we must `fflush` to ensure the string hits
+  // the console/file before the program dies (and takes the libc buffers
+  // with it).
+  // https://docs.microsoft.com/en-us/cpp/c-runtime-library/stream-i-o
+  if (severity >= absl::LogSeverity::kWarning) {
+    std::fflush(stderr);
+  }
+#else
+  // Avoid unused parameter warning in this branch.
+  (void)severity;
+#endif
+}
+
+void SetTimeZone(absl::TimeZone tz) {
+  absl::TimeZone* expected = nullptr;
+  absl::TimeZone* new_tz = new absl::TimeZone(tz);
+  // timezone_ptr can only be set once, otherwise new_tz is leaked.
+  if (!timezone_ptr.compare_exchange_strong(expected, new_tz,
+                                            std::memory_order_release,
+                                            std::memory_order_relaxed)) {
+    ABSL_RAW_LOG(FATAL,
+                 "absl::log_internal::SetTimeZone() has already been called");
+  }
+}
+
+const absl::TimeZone* TimeZone() {
+  return timezone_ptr.load(std::memory_order_acquire);
+}
+
+bool ShouldSymbolizeLogStackTrace() {
+  return symbolize_stack_trace.load(std::memory_order_acquire);
+}
+
+void EnableSymbolizeLogStackTrace(bool on_off) {
+  symbolize_stack_trace.store(on_off, std::memory_order_release);
+}
+
+int MaxFramesInLogStackTrace() {
+  return max_frames_in_stack_trace.load(std::memory_order_acquire);
+}
+
+void SetMaxFramesInLogStackTrace(int max_num_frames) {
+  max_frames_in_stack_trace.store(max_num_frames, std::memory_order_release);
+}
+
+bool ExitOnDFatal() { return exit_on_dfatal.load(std::memory_order_acquire); }
+
+void SetExitOnDFatal(bool on_off) {
+  exit_on_dfatal.store(on_off, std::memory_order_release);
+}
+
+bool SuppressSigabortTrace() {
+  return suppress_sigabort_trace.load(std::memory_order_acquire);
+}
+
+bool SetSuppressSigabortTrace(bool on_off) {
+  return suppress_sigabort_trace.exchange(on_off);
+}
+
+}  // namespace log_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/log/internal/globals.h b/absl/log/internal/globals.h
new file mode 100644
index 0000000..27bc0d0
--- /dev/null
+++ b/absl/log/internal/globals.h
@@ -0,0 +1,101 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/globals.h
+// -----------------------------------------------------------------------------
+//
+// This header file contains various global objects and static helper routines
+// use in logging implementation.
+
+#ifndef ABSL_LOG_INTERNAL_GLOBALS_H_
+#define ABSL_LOG_INTERNAL_GLOBALS_H_
+
+#include "absl/base/config.h"
+#include "absl/base/log_severity.h"
+#include "absl/strings/string_view.h"
+#include "absl/time/time.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+// IsInitialized returns true if the logging library is initialized.
+// This function is async-signal-safe
+bool IsInitialized();
+
+// SetLoggingInitialized is called once after logging initialization is done.
+void SetInitialized();
+
+// Unconditionally write a `message` to stderr. If `severity` exceeds kInfo
+// we also flush the stderr stream.
+void WriteToStderr(absl::string_view message, absl::LogSeverity severity);
+
+// Set the TimeZone used for human-friendly times (for example, the log message
+// prefix) printed by the logging library. This may only be called once.
+void SetTimeZone(absl::TimeZone tz);
+
+// Returns the TimeZone used for human-friendly times (for example, the log
+// message prefix) printed by the logging library Returns nullptr prior to
+// initialization.
+const absl::TimeZone* TimeZone();
+
+// Returns true if stack traces emitted by the logging library should be
+// symbolized. This function is async-signal-safe.
+bool ShouldSymbolizeLogStackTrace();
+
+// Enables or disables symbolization of stack traces emitted by the
+// logging library. This function is async-signal-safe.
+void EnableSymbolizeLogStackTrace(bool on_off);
+
+// Returns the maximum number of frames that appear in stack traces
+// emitted by the logging library. This function is async-signal-safe.
+int MaxFramesInLogStackTrace();
+
+// Sets the maximum number of frames that appear in stack traces emitted by
+// the logging library. This function is async-signal-safe.
+void SetMaxFramesInLogStackTrace(int max_num_frames);
+
+// Determines whether we exit the program for a LOG(DFATAL) message in
+// debug mode.  It does this by skipping the call to Fail/FailQuietly.
+// This is intended for testing only.
+//
+// This can have some effects on LOG(FATAL) as well. Failure messages
+// are always allocated (rather than sharing a buffer), the crash
+// reason is not recorded, the "gwq" status message is not updated,
+// and the stack trace is not recorded.  The LOG(FATAL) *will* still
+// exit the program. Since this function is used only in testing,
+// these differences are acceptable.
+//
+// Additionally, LOG(LEVEL(FATAL)) is indistinguishable from LOG(DFATAL) and
+// will not terminate the program if SetExitOnDFatal(false) has been called.
+bool ExitOnDFatal();
+
+// SetExitOnDFatal() sets the ExitOnDFatal() status
+void SetExitOnDFatal(bool on_off);
+
+// Determines if the logging library should suppress logging of stacktraces in
+// the `SIGABRT` handler, typically because we just logged a stacktrace as part
+// of `LOG(FATAL)` and are about to send ourselves a `SIGABRT` to end the
+// program.
+bool SuppressSigabortTrace();
+
+// Sets the SuppressSigabortTrace() status and returns the previous state.
+bool SetSuppressSigabortTrace(bool on_off);
+
+}  // namespace log_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_LOG_INTERNAL_GLOBALS_H_
diff --git a/absl/log/internal/log_format.cc b/absl/log/internal/log_format.cc
new file mode 100644
index 0000000..b10a656
--- /dev/null
+++ b/absl/log/internal/log_format.cc
@@ -0,0 +1,189 @@
+//
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/internal/log_format.h"
+
+#include <string.h>
+
+#ifdef _MSC_VER
+#include <winsock2.h>  // For timeval
+#else
+#include <sys/time.h>
+#endif
+
+#include <cstddef>
+#include <cstdint>
+#include <limits>
+#include <string>
+#include <type_traits>
+
+#include "absl/base/config.h"
+#include "absl/base/log_severity.h"
+#include "absl/base/optimization.h"
+#include "absl/log/internal/config.h"
+#include "absl/log/internal/globals.h"
+#include "absl/strings/numbers.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/string_view.h"
+#include "absl/time/civil_time.h"
+#include "absl/time/time.h"
+#include "absl/types/span.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+namespace {
+
+// The fields before the filename are all fixed-width except for the thread ID,
+// which is of bounded width.
+size_t FormatBoundedFields(absl::LogSeverity severity, absl::Time timestamp,
+                           log_internal::Tid tid, absl::Span<char>& buf) {
+  constexpr size_t kBoundedFieldsMaxLen =
+      sizeof("SMMDD HH:MM:SS.NNNNNN  ") +
+      (1 + std::numeric_limits<log_internal::Tid>::digits10 + 1) - sizeof("");
+  if (ABSL_PREDICT_FALSE(buf.size() < kBoundedFieldsMaxLen)) {
+    // We don't bother trying to truncate these fields if the buffer is too
+    // short (or almost too short) because it would require doing a lot more
+    // length checking (slow) and it should never happen.  A 15kB buffer should
+    // be enough for anyone.  Instead we mark `buf` full without writing
+    // anything.
+    buf.remove_suffix(buf.size());
+    return 0;
+  }
+
+  // We can't call absl::LocalTime(), localtime_r(), or anything else here that
+  // isn't async-signal-safe. We can only use the time zone if it has already
+  // been loaded.
+  const absl::TimeZone* tz = absl::log_internal::TimeZone();
+  if (ABSL_PREDICT_FALSE(tz == nullptr)) {
+    // If a time zone hasn't been set yet because we are logging before the
+    // logging library has been initialized, we fallback to a simpler, slower
+    // method. Just report the raw Unix time in seconds. We cram this into the
+    // normal time format for the benefit of parsers.
+    auto tv = absl::ToTimeval(timestamp);
+    int snprintf_result = absl::SNPrintF(
+        buf.data(), buf.size(), "%c0000 00:00:%02d.%06d %7d ",
+        absl::LogSeverityName(severity)[0], static_cast<int>(tv.tv_sec),
+        static_cast<int>(tv.tv_usec), static_cast<int>(tid));
+    if (snprintf_result >= 0) {
+      buf.remove_prefix(snprintf_result);
+      return static_cast<size_t>(snprintf_result);
+    }
+    return 0;
+  }
+
+  char* p = buf.data();
+  *p++ = absl::LogSeverityName(severity)[0];
+  const absl::TimeZone::CivilInfo ci = tz->At(timestamp);
+  absl::numbers_internal::PutTwoDigits(ci.cs.month(), p);
+  p += 2;
+  absl::numbers_internal::PutTwoDigits(ci.cs.day(), p);
+  p += 2;
+  *p++ = ' ';
+  absl::numbers_internal::PutTwoDigits(ci.cs.hour(), p);
+  p += 2;
+  *p++ = ':';
+  absl::numbers_internal::PutTwoDigits(ci.cs.minute(), p);
+  p += 2;
+  *p++ = ':';
+  absl::numbers_internal::PutTwoDigits(ci.cs.second(), p);
+  p += 2;
+  *p++ = '.';
+  const int64_t usecs = absl::ToInt64Microseconds(ci.subsecond);
+  absl::numbers_internal::PutTwoDigits(usecs / 10000, p);
+  p += 2;
+  absl::numbers_internal::PutTwoDigits(usecs / 100 % 100, p);
+  p += 2;
+  absl::numbers_internal::PutTwoDigits(usecs % 100, p);
+  p += 2;
+  *p++ = ' ';
+  constexpr bool unsigned_tid_t = !std::is_signed<log_internal::Tid>::value;
+  if ((unsigned_tid_t || tid >= 0) && tid < 10) *p++ = ' ';
+  if ((unsigned_tid_t || tid > -10) && tid < 100) *p++ = ' ';
+  if ((unsigned_tid_t || tid > -100) && tid < 1000) *p++ = ' ';
+  if ((unsigned_tid_t || tid > -1000) && tid < 10000) *p++ = ' ';
+  if ((unsigned_tid_t || tid > -10000) && tid < 100000) *p++ = ' ';
+  if ((unsigned_tid_t || tid > -100000) && tid < 1000000) *p++ = ' ';
+  p = absl::numbers_internal::FastIntToBuffer(tid, p);
+  *p++ = ' ';
+  const size_t bytes_formatted = p - buf.data();
+  buf.remove_prefix(bytes_formatted);
+  return bytes_formatted;
+}
+
+// Copies into `dst` as many bytes of `src` as will fit, then advances `dst`
+// past the copied bytes and returns the number of bytes written.
+size_t AppendTruncated(absl::string_view src, absl::Span<char>& dst) {
+  if (src.size() > dst.size()) src = src.substr(0, dst.size());
+  memcpy(dst.data(), src.data(), src.size());
+  dst.remove_prefix(src.size());
+  return src.size();
+}
+
+size_t FormatLineNumber(int line, absl::Span<char>& buf) {
+  constexpr size_t kLineFieldMaxLen =
+      sizeof(":] ") + (1 + std::numeric_limits<int>::digits10 + 1) - sizeof("");
+  if (ABSL_PREDICT_FALSE(buf.size() < kLineFieldMaxLen)) {
+    // As above, we don't bother trying to truncate this if the buffer is too
+    // short and it should never happen.
+    buf.remove_suffix(buf.size());
+    return 0;
+  }
+  char* p = buf.data();
+  *p++ = ':';
+  p = absl::numbers_internal::FastIntToBuffer(line, p);
+  *p++ = ']';
+  *p++ = ' ';
+  const size_t bytes_formatted = p - buf.data();
+  buf.remove_prefix(bytes_formatted);
+  return bytes_formatted;
+}
+
+}  // namespace
+
+std::string FormatLogMessage(absl::LogSeverity severity,
+                             absl::CivilSecond civil_second,
+                             absl::Duration subsecond, log_internal::Tid tid,
+                             absl::string_view basename, int line,
+                             absl::string_view message) {
+  return absl::StrFormat(
+      "%c%02d%02d %02d:%02d:%02d.%06d %7d %s:%d] %s",
+      absl::LogSeverityName(severity)[0], civil_second.month(),
+      civil_second.day(), civil_second.hour(), civil_second.minute(),
+      civil_second.second(), absl::ToInt64Microseconds(subsecond), tid,
+      basename, line, message);
+}
+
+// This method is fairly hot, and the library always passes a huge `buf`, so we
+// save some bounds-checking cycles by not trying to do precise truncation.
+// Truncating at a field boundary is probably a better UX anyway.
+//
+// The prefix is written in three parts, each of which does a single
+// bounds-check and truncation:
+// 1. severity, timestamp, and thread ID
+// 2. filename
+// 3. line number and bracket
+size_t FormatLogPrefix(absl::LogSeverity severity, absl::Time timestamp,
+                       log_internal::Tid tid, absl::string_view basename,
+                       int line, absl::Span<char>& buf) {
+  auto prefix_size = FormatBoundedFields(severity, timestamp, tid, buf);
+  prefix_size += AppendTruncated(basename, buf);
+  prefix_size += FormatLineNumber(line, buf);
+  return prefix_size;
+}
+
+}  // namespace log_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/log/internal/log_format.h b/absl/log/internal/log_format.h
new file mode 100644
index 0000000..a016328
--- /dev/null
+++ b/absl/log/internal/log_format.h
@@ -0,0 +1,73 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/log_format.h
+// -----------------------------------------------------------------------------
+//
+// This file declares routines implementing formatting of log message and log
+// prefix.
+
+#ifndef ABSL_LOG_INTERNAL_LOG_FORMAT_H_
+#define ABSL_LOG_INTERNAL_LOG_FORMAT_H_
+
+#include <stddef.h>
+
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/base/log_severity.h"
+#include "absl/log/internal/config.h"
+#include "absl/strings/string_view.h"
+#include "absl/time/civil_time.h"
+#include "absl/time/time.h"
+#include "absl/types/span.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+// Formats log message based on provided data.
+std::string FormatLogMessage(absl::LogSeverity severity,
+                             absl::CivilSecond civil_second,
+                             absl::Duration subsecond, log_internal::Tid tid,
+                             absl::string_view basename, int line,
+                             absl::string_view message);
+
+// Formats various entry metadata into a text string meant for use as a
+// prefix on a log message string.  Writes into `buf`, advances `buf` to point
+// at the remainder of the buffer (i.e. past any written bytes), and returns the
+// number of bytes written.
+//
+// In addition to calling `buf->remove_prefix()` (or the equivalent), this
+// function may also do `buf->remove_suffix(buf->size())` in cases where no more
+// bytes (i.e. no message data) should be written into the buffer.  For example,
+// if the prefix ought to be:
+//   I0926 09:00:00.000000 1234567 foo.cc:123]
+// `buf` is too small, the function might fill the whole buffer:
+//   I0926 09:00:00.000000 1234
+// (note the apparrently incorrect thread ID), or it might write less:
+//   I0926 09:00:00.000000
+// In this case, it might also empty `buf` prior to returning to prevent
+// message data from being written into the space where a reader would expect to
+// see a thread ID.
+size_t FormatLogPrefix(absl::LogSeverity severity, absl::Time timestamp,
+                       log_internal::Tid tid, absl::string_view basename,
+                       int line, absl::Span<char>& buf);
+
+}  // namespace log_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_LOG_INTERNAL_LOG_FORMAT_H_
diff --git a/absl/log/internal/log_message.cc b/absl/log/internal/log_message.cc
new file mode 100644
index 0000000..9ef0c29
--- /dev/null
+++ b/absl/log/internal/log_message.cc
@@ -0,0 +1,508 @@
+//
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/internal/log_message.h"
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+#include <algorithm>
+#include <array>
+#include <atomic>
+#include <memory>
+#include <ostream>
+#include <string>
+#include <tuple>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/base/internal/strerror.h"
+#include "absl/base/internal/sysinfo.h"
+#include "absl/base/log_severity.h"
+#include "absl/container/inlined_vector.h"
+#include "absl/debugging/internal/examine_stack.h"
+#include "absl/log/globals.h"
+#include "absl/log/internal/config.h"
+#include "absl/log/internal/globals.h"
+#include "absl/log/internal/log_format.h"
+#include "absl/log/internal/log_sink_set.h"
+#include "absl/log/log_entry.h"
+#include "absl/log/log_sink.h"
+#include "absl/log/log_sink_registry.h"
+#include "absl/memory/memory.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/string_view.h"
+#include "absl/time/clock.h"
+#include "absl/time/time.h"
+#include "absl/types/span.h"
+
+extern "C" ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(
+    AbslInternalOnFatalLogMessage)(const absl::LogEntry&) {
+  // Default - Do nothing
+}
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+namespace {
+// Copies into `dst` as many bytes of `src` as will fit, then truncates the
+// copied bytes from the front of `dst` and returns the number of bytes written.
+size_t AppendTruncated(absl::string_view src, absl::Span<char>* dst) {
+  if (src.size() > dst->size()) src = src.substr(0, dst->size());
+  memcpy(dst->data(), src.data(), src.size());
+  dst->remove_prefix(src.size());
+  return src.size();
+}
+
+absl::string_view Basename(absl::string_view filepath) {
+#ifdef _WIN32
+  size_t path = filepath.find_last_of("/\\");
+#else
+  size_t path = filepath.find_last_of('/');
+#endif
+  if (path != filepath.npos) filepath.remove_prefix(path + 1);
+  return filepath;
+}
+
+void WriteToString(const char* data, void* str) {
+  reinterpret_cast<std::string*>(str)->append(data);
+}
+void WriteToStream(const char* data, void* os) {
+  auto* cast_os = static_cast<std::ostream*>(os);
+  *cast_os << data;
+}
+}  // namespace
+
+// A write-only `std::streambuf` that writes into an `absl::Span<char>`.
+//
+// This class is responsible for writing a metadata prefix just before the first
+// data are streamed in.  The metadata are subject to change (cf.
+// `LogMessage::AtLocation`) until then, so we wait as long as possible.
+//
+// This class is also responsible for reserving space for a trailing newline
+// so that one can be added later by `Finalize` no matter how many data are
+// streamed in.
+class LogEntryStreambuf final : public std::streambuf {
+ public:
+  explicit LogEntryStreambuf(absl::Span<char> buf, const absl::LogEntry& entry)
+      : buf_(buf), entry_(entry), prefix_len_(0), finalized_(false) {
+    // To detect when data are first written, we leave the put area null,
+    // override `overflow`, and check ourselves in `xsputn`.
+  }
+
+  LogEntryStreambuf(LogEntryStreambuf&&) = delete;
+  LogEntryStreambuf& operator=(LogEntryStreambuf&&) = delete;
+
+  absl::Span<const char> Finalize() {
+    assert(!finalized_);
+    // If no data were ever streamed in, this is where we must write the prefix.
+    if (pbase() == nullptr) Initialize();
+    // Here we reclaim the two bytes we reserved.
+    size_t idx = pptr() - pbase();
+    setp(buf_.data(), buf_.data() + buf_.size());
+    pbump(idx);
+    sputc('\n');
+    sputc('\0');
+    finalized_ = true;
+    return absl::Span<const char>(pbase(), pptr() - pbase());
+  }
+  size_t prefix_len() const { return prefix_len_; }
+
+ protected:
+  std::streamsize xsputn(const char* s, std::streamsize n) override {
+    if (pbase() == nullptr) Initialize();
+    return Append(absl::string_view(s, n));
+  }
+
+  int overflow(int ch = EOF) override {
+    if (pbase() == nullptr) Initialize();
+    if (ch == EOF) return 0;
+    if (pptr() == epptr()) return EOF;
+    *pptr() = static_cast<char>(ch);
+    pbump(1);
+    return 1;
+  }
+
+ private:
+  void Initialize() {
+    // Here we reserve two bytes in our buffer to guarantee `Finalize` space to
+    // add a trailing "\n\0".
+    assert(buf_.size() >= 2);
+    setp(buf_.data(), buf_.data() + buf_.size() - 2);
+    if (entry_.prefix()) {
+      absl::Span<char> remaining = buf_;
+      prefix_len_ = log_internal::FormatLogPrefix(
+          entry_.log_severity(), entry_.timestamp(), entry_.tid(),
+          entry_.source_basename(), entry_.source_line(), remaining);
+      pbump(prefix_len_);
+    }
+  }
+
+  size_t Append(absl::string_view data) {
+    absl::Span<char> remaining(pptr(), epptr() - pptr());
+    const size_t written = AppendTruncated(data, &remaining);
+    pbump(written);
+    return written;
+  }
+
+  const absl::Span<char> buf_;
+  const absl::LogEntry& entry_;
+  size_t prefix_len_;
+  bool finalized_;
+};
+
+struct LogMessage::LogMessageData final {
+  LogMessageData(const char* file, int line, absl::LogSeverity severity,
+                 absl::Time timestamp);
+  LogMessageData(const LogMessageData&) = delete;
+  LogMessageData& operator=(const LogMessageData&) = delete;
+
+  // `LogEntry` sent to `LogSink`s; contains metadata.
+  absl::LogEntry entry;
+
+  // true => this was first fatal msg
+  bool first_fatal;
+  // true => all failures should be quiet
+  bool fail_quietly;
+  // true => PLOG was requested
+  bool is_perror;
+
+  // Extra `LogSink`s to log to, in addition to `global_sinks`.
+  absl::InlinedVector<absl::LogSink*, 16> extra_sinks;
+  // If true, log to `extra_sinks` but not to `global_sinks` or hardcoded
+  // non-sink targets (e.g. stderr, log files).
+  bool extra_sinks_only;
+
+  // A formatted string message is built in `string_buf`.
+  std::array<char, kLogMessageBufferSize> string_buf;
+
+  // A `std::streambuf` that stores into `string_buf`.
+  LogEntryStreambuf streambuf_;
+};
+
+LogMessage::LogMessageData::LogMessageData(const char* file, int line,
+                                           absl::LogSeverity severity,
+                                           absl::Time timestamp)
+    : extra_sinks_only(false),
+      streambuf_(absl::MakeSpan(string_buf), entry) {
+  entry.full_filename_ = file;
+  entry.base_filename_ = Basename(file);
+  entry.line_ = line;
+  entry.prefix_ = absl::ShouldPrependLogPrefix();
+  entry.severity_ = absl::NormalizeLogSeverity(severity);
+  entry.verbose_level_ = absl::LogEntry::kNoVerbosityLevel;
+  entry.timestamp_ = timestamp;
+  entry.tid_ = absl::base_internal::GetCachedTID();
+}
+
+LogMessage::LogMessage(const char* file, int line, absl::LogSeverity severity)
+    : data_(
+          absl::make_unique<LogMessageData>(file, line, severity, absl::Now()))
+      ,
+      stream_(&data_->streambuf_)
+{
+  data_->first_fatal = false;
+  data_->is_perror = false;
+  data_->fail_quietly = false;
+
+  // Legacy defaults for LOG's ostream:
+  stream_.setf(std::ios_base::showbase | std::ios_base::boolalpha);
+  // `fill('0')` is omitted here because its effects are very different without
+  // structured logging.  Resolution is tracked in b/111310488.
+
+  // This logs a backtrace even if the location is subsequently changed using
+  // AtLocation.  This quirk, and the behavior when AtLocation is called twice,
+  // are fixable but probably not worth fixing.
+  LogBacktraceIfNeeded();
+}
+
+LogMessage::~LogMessage() {
+#ifdef ABSL_MIN_LOG_LEVEL
+  if (data_->entry.log_severity() <
+          static_cast<absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) &&
+      data_->entry.log_severity() < absl::LogSeverity::kFatal) {
+    return;
+  }
+#endif
+  Flush();
+}
+
+LogMessage& LogMessage::AtLocation(absl::string_view file, int line) {
+  data_->entry.full_filename_ = file;
+  data_->entry.base_filename_ = Basename(file);
+  data_->entry.line_ = line;
+  LogBacktraceIfNeeded();
+  return *this;
+}
+
+LogMessage& LogMessage::NoPrefix() {
+  data_->entry.prefix_ = false;
+  return *this;
+}
+
+LogMessage& LogMessage::WithVerbosity(int verbose_level) {
+  if (verbose_level == absl::LogEntry::kNoVerbosityLevel) {
+    data_->entry.verbose_level_ = absl::LogEntry::kNoVerbosityLevel;
+  } else {
+    data_->entry.verbose_level_ = std::max(0, verbose_level);
+  }
+  return *this;
+}
+
+LogMessage& LogMessage::WithTimestamp(absl::Time timestamp) {
+  data_->entry.timestamp_ = timestamp;
+  return *this;
+}
+
+LogMessage& LogMessage::WithThreadID(absl::LogEntry::tid_t tid) {
+  data_->entry.tid_ = tid;
+  return *this;
+}
+
+LogMessage& LogMessage::WithMetadataFrom(const absl::LogEntry& entry) {
+  data_->entry.full_filename_ = entry.full_filename_;
+  data_->entry.base_filename_ = entry.base_filename_;
+  data_->entry.line_ = entry.line_;
+  data_->entry.prefix_ = entry.prefix_;
+  data_->entry.severity_ = entry.severity_;
+  data_->entry.verbose_level_ = entry.verbose_level_;
+  data_->entry.timestamp_ = entry.timestamp_;
+  data_->entry.tid_ = entry.tid_;
+  return *this;
+}
+
+LogMessage& LogMessage::WithPerror() {
+  data_->is_perror = true;
+  return *this;
+}
+
+LogMessage& LogMessage::ToSinkAlso(absl::LogSink* sink) {
+  ABSL_INTERNAL_CHECK(sink, "null LogSink*");
+  data_->extra_sinks.push_back(sink);
+  return *this;
+}
+
+LogMessage& LogMessage::ToSinkOnly(absl::LogSink* sink) {
+  ABSL_INTERNAL_CHECK(sink, "null LogSink*");
+  data_->extra_sinks.clear();
+  data_->extra_sinks.push_back(sink);
+  data_->extra_sinks_only = true;
+  return *this;
+}
+
+#ifdef __ELF__
+extern "C" void __gcov_dump() ABSL_ATTRIBUTE_WEAK;
+extern "C" void __gcov_flush() ABSL_ATTRIBUTE_WEAK;
+#endif
+
+void LogMessage::FailWithoutStackTrace() {
+  // Now suppress repeated trace logging:
+  log_internal::SetSuppressSigabortTrace(true);
+#if defined _DEBUG && defined COMPILER_MSVC
+  // When debugging on windows, avoid the obnoxious dialog.
+  __debugbreak();
+#endif
+
+#ifdef __ELF__
+  // For b/8737634, flush coverage if we are in coverage mode.
+  if (&__gcov_dump != nullptr) {
+    __gcov_dump();
+  } else if (&__gcov_flush != nullptr) {
+    __gcov_flush();
+  }
+#endif
+
+  abort();
+}
+
+void LogMessage::FailQuietly() {
+  // _exit. Calling abort() would trigger all sorts of death signal handlers
+  // and a detailed stack trace. Calling exit() would trigger the onexit
+  // handlers, including the heap-leak checker, which is guaranteed to fail in
+  // this case: we probably just new'ed the std::string that we logged.
+  // Anyway, if you're calling Fail or FailQuietly, you're trying to bail out
+  // of the program quickly, and it doesn't make much sense for FailQuietly to
+  // offer different guarantees about exit behavior than Fail does. (And as a
+  // consequence for QCHECK and CHECK to offer different exit behaviors)
+  _exit(1);
+}
+
+template LogMessage& LogMessage::operator<<(const char& v);
+template LogMessage& LogMessage::operator<<(const signed char& v);
+template LogMessage& LogMessage::operator<<(const unsigned char& v);
+template LogMessage& LogMessage::operator<<(const short& v);           // NOLINT
+template LogMessage& LogMessage::operator<<(const unsigned short& v);  // NOLINT
+template LogMessage& LogMessage::operator<<(const int& v);
+template LogMessage& LogMessage::operator<<(const unsigned int& v);
+template LogMessage& LogMessage::operator<<(const long& v);           // NOLINT
+template LogMessage& LogMessage::operator<<(const unsigned long& v);  // NOLINT
+template LogMessage& LogMessage::operator<<(const long long& v);      // NOLINT
+template LogMessage& LogMessage::operator<<(
+    const unsigned long long& v);  // NOLINT
+template LogMessage& LogMessage::operator<<(void* const& v);
+template LogMessage& LogMessage::operator<<(const void* const& v);
+template LogMessage& LogMessage::operator<<(const float& v);
+template LogMessage& LogMessage::operator<<(const double& v);
+template LogMessage& LogMessage::operator<<(const bool& v);
+template LogMessage& LogMessage::operator<<(const std::string& v);
+template LogMessage& LogMessage::operator<<(const absl::string_view& v);
+
+void LogMessage::Flush() {
+  if (data_->entry.log_severity() < absl::MinLogLevel())
+    return;
+
+  if (data_->is_perror) {
+    InternalStream() << ": " << absl::base_internal::StrError(errno_saver_())
+                     << " [" << errno_saver_() << "]";
+  }
+
+  // Have we already seen a fatal message?
+  ABSL_CONST_INIT static std::atomic_flag seen_fatal = ATOMIC_FLAG_INIT;
+  if (data_->entry.log_severity() == absl::LogSeverity::kFatal &&
+      absl::log_internal::ExitOnDFatal()) {
+    // Exactly one LOG(FATAL) message is responsible for aborting the process,
+    // even if multiple threads LOG(FATAL) concurrently.
+    data_->first_fatal = !seen_fatal.test_and_set(std::memory_order_relaxed);
+  }
+
+  data_->entry.text_message_with_prefix_and_newline_and_nul_ =
+      data_->streambuf_.Finalize();
+  data_->entry.prefix_len_ = data_->streambuf_.prefix_len();
+  SendToLog();
+}
+
+void LogMessage::SetFailQuietly() { data_->fail_quietly = true; }
+
+bool LogMessage::IsFatal() const {
+  return data_->entry.log_severity() == absl::LogSeverity::kFatal &&
+         absl::log_internal::ExitOnDFatal();
+}
+
+void LogMessage::PrepareToDie() {
+  // If we log a FATAL message, flush all the log destinations, then toss
+  // a signal for others to catch. We leave the logs in a state that
+  // someone else can use them (as long as they flush afterwards)
+  if (data_->first_fatal) {
+    // Notify observers about the upcoming fatal error.
+    ABSL_INTERNAL_C_SYMBOL(AbslInternalOnFatalLogMessage)(data_->entry);
+  }
+
+  if (!data_->fail_quietly) {
+    // Log the message first before we start collecting stack trace.
+    log_internal::LogToSinks(data_->entry, absl::MakeSpan(data_->extra_sinks),
+                             data_->extra_sinks_only);
+
+    // `DumpStackTrace` generates an empty string under MSVC.
+    // Adding the constant prefix here simplifies testing.
+    data_->entry.stacktrace_ = "*** Check failure stack trace: ***\n";
+    debugging_internal::DumpStackTrace(
+        0, log_internal::MaxFramesInLogStackTrace(),
+        log_internal::ShouldSymbolizeLogStackTrace(), WriteToString,
+        &data_->entry.stacktrace_);
+  }
+}
+
+void LogMessage::Die() {
+  absl::FlushLogSinks();
+
+  if (data_->fail_quietly) {
+    FailQuietly();
+  } else {
+    FailWithoutStackTrace();
+  }
+}
+
+void LogMessage::SendToLog() {
+  if (IsFatal()) PrepareToDie();
+  // Also log to all registered sinks, even if OnlyLogToStderr() is set.
+  log_internal::LogToSinks(data_->entry, absl::MakeSpan(data_->extra_sinks),
+                           data_->extra_sinks_only);
+  if (IsFatal()) Die();
+}
+
+void LogMessage::LogBacktraceIfNeeded() {
+  if (!absl::log_internal::IsInitialized()) return;
+
+  if (!absl::log_internal::ShouldLogBacktraceAt(data_->entry.source_basename(),
+                                                data_->entry.source_line()))
+    return;
+  stream_ << " (stacktrace:\n";
+  debugging_internal::DumpStackTrace(
+      1, log_internal::MaxFramesInLogStackTrace(),
+      log_internal::ShouldSymbolizeLogStackTrace(), WriteToStream, &stream_);
+  stream_ << ") ";
+}
+
+LogMessageFatal::LogMessageFatal(const char* file, int line)
+    : LogMessage(file, line, absl::LogSeverity::kFatal) {}
+
+LogMessageFatal::LogMessageFatal(const char* file, int line,
+                                 absl::string_view failure_msg)
+    : LogMessage(file, line, absl::LogSeverity::kFatal) {
+  *this << "Check failed: " << failure_msg << " ";
+}
+
+// ABSL_ATTRIBUTE_NORETURN doesn't seem to work on destructors with msvc, so
+// disable msvc's warning about the d'tor never returning.
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4722)
+#endif
+LogMessageFatal::~LogMessageFatal() {
+  Flush();
+  FailWithoutStackTrace();
+}
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+LogMessageQuietlyFatal::LogMessageQuietlyFatal(const char* file, int line)
+    : LogMessage(file, line, absl::LogSeverity::kFatal) {
+  SetFailQuietly();
+}
+
+LogMessageQuietlyFatal::LogMessageQuietlyFatal(const char* file, int line,
+                                               absl::string_view failure_msg)
+    : LogMessage(file, line, absl::LogSeverity::kFatal) {
+  SetFailQuietly();
+  *this << "Check failed: " << failure_msg << " ";
+}
+
+// ABSL_ATTRIBUTE_NORETURN doesn't seem to work on destructors with msvc, so
+// disable msvc's warning about the d'tor never returning.
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4722)
+#endif
+LogMessageQuietlyFatal::~LogMessageQuietlyFatal() {
+  Flush();
+  FailQuietly();
+}
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+}  // namespace log_internal
+
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/log/internal/log_message.h b/absl/log/internal/log_message.h
new file mode 100644
index 0000000..37a267c
--- /dev/null
+++ b/absl/log/internal/log_message.h
@@ -0,0 +1,287 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/log_message.h
+// -----------------------------------------------------------------------------
+//
+// This file declares `class absl::log_internal::LogMessage`. This class more or
+// less represents a particular log message. LOG/CHECK macros create a
+// temporary instance of `LogMessage` and then stream values to it.  At the end
+// of the LOG/CHECK statement, LogMessage instance goes out of scope and
+// `~LogMessage` directs the message to the registered log sinks.
+// Heap-allocation of `LogMessage` is unsupported.  Construction outside of a
+// `LOG` macro is unsupported.
+
+#ifndef ABSL_LOG_INTERNAL_LOG_MESSAGE_H_
+#define ABSL_LOG_INTERNAL_LOG_MESSAGE_H_
+
+#include <ios>
+#include <memory>
+#include <ostream>
+#include <streambuf>
+#include <string>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/internal/errno_saver.h"
+#include "absl/base/log_severity.h"
+#include "absl/log/internal/config.h"
+#include "absl/log/internal/nullguard.h"
+#include "absl/log/log_entry.h"
+#include "absl/log/log_sink.h"
+#include "absl/strings/string_view.h"
+#include "absl/time/time.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+constexpr int kLogMessageBufferSize = 15000;
+
+class LogMessage {
+ public:
+  // Used for `LOG`.
+  LogMessage(const char* file, int line,
+             absl::LogSeverity severity) ABSL_ATTRIBUTE_COLD;
+  LogMessage(const LogMessage&) = delete;
+  LogMessage& operator=(const LogMessage&) = delete;
+  ~LogMessage() ABSL_ATTRIBUTE_COLD;
+
+  // Overrides the location inferred from the callsite.  The string pointed to
+  // by `file` must be valid until the end of the statement.
+  LogMessage& AtLocation(absl::string_view file, int line);
+  // Omits the prefix from this line.  The prefix includes metadata about the
+  // logged data such as source code location and timestamp.
+  LogMessage& NoPrefix();
+  // Sets the verbosity field of the logged message as if it was logged by
+  // `VLOG(verbose_level)`.  Unlike `VLOG`, this method does not affect
+  // evaluation of the statement when the specified `verbose_level` has been
+  // disabled.  The only effect is on `absl::LogSink` implementations which
+  // make use of the `absl::LogSink::verbosity()` value.  The value
+  // `absl::LogEntry::kNoVerbosityLevel` can be specified to mark the message
+  // not verbose.
+  LogMessage& WithVerbosity(int verbose_level);
+  // Uses the specified timestamp instead of one collected in the constructor.
+  LogMessage& WithTimestamp(absl::Time timestamp);
+  // Uses the specified thread ID instead of one collected in the constructor.
+  LogMessage& WithThreadID(absl::LogEntry::tid_t tid);
+  // Copies all metadata (but no data) from the specified `absl::LogEntry`.
+  LogMessage& WithMetadataFrom(const absl::LogEntry& entry);
+  // Appends to the logged message a colon, a space, a textual description of
+  // the current value of `errno` (as by strerror(3)), and the numerical value
+  // of `errno`.
+  LogMessage& WithPerror();
+  // Sends this message to `*sink` in addition to whatever other sinks it would
+  // otherwise have been sent to.  `sink` must not be null.
+  LogMessage& ToSinkAlso(absl::LogSink* sink);
+  // Sends this message to `*sink` and no others.  `sink` must not be null.
+  LogMessage& ToSinkOnly(absl::LogSink* sink);
+
+  // Don't call this method from outside this library.
+  LogMessage& InternalStream() { return *this; }
+
+  // By-value overloads for small, common types let us overlook common failures
+  // to define globals and static data members (i.e. in a .cc file).
+  // clang-format off
+  // The CUDA toolchain cannot handle these <<<'s:
+  LogMessage& operator<<(char v) { return operator<< <char>(v); }
+  LogMessage& operator<<(signed char v) { return operator<< <signed char>(v); }
+  LogMessage& operator<<(unsigned char v) {
+    return operator<< <unsigned char>(v);
+  }
+  LogMessage& operator<<(signed short v) {  // NOLINT
+    return operator<< <signed short>(v);  // NOLINT
+  }
+  LogMessage& operator<<(signed int v) { return operator<< <signed int>(v); }
+  LogMessage& operator<<(signed long v) {  // NOLINT
+    return operator<< <signed long>(v);  // NOLINT
+  }
+  LogMessage& operator<<(signed long long v) {  // NOLINT
+    return operator<< <signed long long>(v);  // NOLINT
+  }
+  LogMessage& operator<<(unsigned short v) {  // NOLINT
+    return operator<< <unsigned short>(v);  // NOLINT
+  }
+  LogMessage& operator<<(unsigned int v) {
+    return operator<< <unsigned int>(v);
+  }
+  LogMessage& operator<<(unsigned long v) {  // NOLINT
+    return operator<< <unsigned long>(v);  // NOLINT
+  }
+  LogMessage& operator<<(unsigned long long v) {  // NOLINT
+    return operator<< <unsigned long long>(v);  // NOLINT
+  }
+  LogMessage& operator<<(void* v) { return operator<< <void*>(v); }
+  LogMessage& operator<<(const void* v) { return operator<< <const void*>(v); }
+  LogMessage& operator<<(float v) { return operator<< <float>(v); }
+  LogMessage& operator<<(double v) { return operator<< <double>(v); }
+  LogMessage& operator<<(bool v) { return operator<< <bool>(v); }
+  // clang-format on
+
+  // Handle stream manipulators e.g. std::endl.
+  LogMessage& operator<<(std::ostream& (*m)(std::ostream& os));
+  LogMessage& operator<<(std::ios_base& (*m)(std::ios_base& os));
+
+  // Literal strings.  This allows us to record C string literals as literals in
+  // the logging.proto.Value.
+  //
+  // Allow this overload to be inlined to prevent generating instantiations of
+  // this template for every value of `SIZE` encountered in each source code
+  // file. That significantly increases linker input sizes. Inlining is cheap
+  // because the argument to this overload is almost always a string literal so
+  // the call to `strlen` can be replaced at compile time. The overload for
+  // `char[]` below should not be inlined. The compiler typically does not have
+  // the string at compile time and cannot replace the call to `strlen` so
+  // inlining it increases the binary size. See the discussion on
+  // cl/107527369.
+  template <int SIZE>
+  LogMessage& operator<<(const char (&buf)[SIZE]);
+
+  // This prevents non-const `char[]` arrays from looking like literals.
+  template <int SIZE>
+  LogMessage& operator<<(char (&buf)[SIZE]) ABSL_ATTRIBUTE_NOINLINE;
+
+  // Default: uses `ostream` logging to convert `v` to a string.
+  template <typename T>
+  LogMessage& operator<<(const T& v) ABSL_ATTRIBUTE_NOINLINE;
+
+  // Note: We explicitly do not support `operator<<` for non-const references
+  // because it breaks logging of non-integer bitfield types (i.e., enums).
+
+ protected:
+  // Call `abort()` or similar to perform `LOG(FATAL)` crash.  It is assumed
+  // that the caller has already generated and written the trace as appropriate.
+  ABSL_ATTRIBUTE_NORETURN static void FailWithoutStackTrace();
+
+  // Similar to `FailWithoutStackTrace()`, but without `abort()`.  Terminates
+  // the process with an error exit code.
+  ABSL_ATTRIBUTE_NORETURN static void FailQuietly();
+
+  // Dispatches the completed `absl::LogEntry` to applicable `absl::LogSink`s.
+  // This might as well be inlined into `~LogMessage` except that
+  // `~LogMessageFatal` needs to call it early.
+  void Flush();
+
+  // After this is called, failures are done as quiet as possible for this log
+  // message.
+  void SetFailQuietly();
+
+ private:
+  struct LogMessageData;  // Opaque type containing message state
+
+  // Returns `true` if the message is fatal or enabled debug-fatal.
+  bool IsFatal() const;
+
+  // Records some tombstone-type data in anticipation of `Die`.
+  void PrepareToDie();
+  void Die();
+
+  void SendToLog();
+
+  // Checks `FLAGS_log_backtrace_at` and appends a backtrace if appropriate.
+  void LogBacktraceIfNeeded();
+
+  // This should be the first data member so that its initializer captures errno
+  // before any other initializers alter it (e.g. with calls to new) and so that
+  // no other destructors run afterward an alter it (e.g. with calls to delete).
+  absl::base_internal::ErrnoSaver errno_saver_;
+
+  // We keep the data in a separate struct so that each instance of `LogMessage`
+  // uses less stack space.
+  std::unique_ptr<LogMessageData> data_;
+
+  std::ostream stream_;
+};
+
+// Note: the following is declared `ABSL_ATTRIBUTE_NOINLINE`
+template <typename T>
+LogMessage& LogMessage::operator<<(const T& v) {
+  stream_ << log_internal::NullGuard<T>().Guard(v);
+  return *this;
+}
+inline LogMessage& LogMessage::operator<<(
+    std::ostream& (*m)(std::ostream& os)) {
+  stream_ << m;
+  return *this;
+}
+inline LogMessage& LogMessage::operator<<(
+    std::ios_base& (*m)(std::ios_base& os)) {
+  stream_ << m;
+  return *this;
+}
+template <int SIZE>
+LogMessage& LogMessage::operator<<(const char (&buf)[SIZE]) {
+  stream_ << buf;
+  return *this;
+}
+// Note: the following is declared `ABSL_ATTRIBUTE_NOINLINE`
+template <int SIZE>
+LogMessage& LogMessage::operator<<(char (&buf)[SIZE]) {
+  stream_ << buf;
+  return *this;
+}
+// We instantiate these specializations in the library's TU to save space in
+// other TUs.  Since the template is marked `ABSL_ATTRIBUTE_NOINLINE` we will be
+// emitting a function call either way.
+extern template LogMessage& LogMessage::operator<<(const char& v);
+extern template LogMessage& LogMessage::operator<<(const signed char& v);
+extern template LogMessage& LogMessage::operator<<(const unsigned char& v);
+extern template LogMessage& LogMessage::operator<<(const short& v);  // NOLINT
+extern template LogMessage& LogMessage::operator<<(
+    const unsigned short& v);  // NOLINT
+extern template LogMessage& LogMessage::operator<<(const int& v);
+extern template LogMessage& LogMessage::operator<<(
+    const unsigned int& v);                                         // NOLINT
+extern template LogMessage& LogMessage::operator<<(const long& v);  // NOLINT
+extern template LogMessage& LogMessage::operator<<(
+    const unsigned long& v);  // NOLINT
+extern template LogMessage& LogMessage::operator<<(
+    const long long& v);  // NOLINT
+extern template LogMessage& LogMessage::operator<<(
+    const unsigned long long& v);  // NOLINT
+extern template LogMessage& LogMessage::operator<<(void* const& v);
+extern template LogMessage& LogMessage::operator<<(const void* const& v);
+extern template LogMessage& LogMessage::operator<<(const float& v);
+extern template LogMessage& LogMessage::operator<<(const double& v);
+extern template LogMessage& LogMessage::operator<<(const bool& v);
+extern template LogMessage& LogMessage::operator<<(const std::string& v);
+extern template LogMessage& LogMessage::operator<<(const absl::string_view& v);
+
+// `LogMessageFatal` ensures the process will exit in failure after logging this
+// message.
+class LogMessageFatal final : public LogMessage {
+ public:
+  LogMessageFatal(const char* file, int line) ABSL_ATTRIBUTE_COLD;
+  LogMessageFatal(const char* file, int line,
+                  absl::string_view failure_msg) ABSL_ATTRIBUTE_COLD;
+  ABSL_ATTRIBUTE_NORETURN ~LogMessageFatal();
+};
+
+class LogMessageQuietlyFatal final : public LogMessage {
+ public:
+  LogMessageQuietlyFatal(const char* file, int line) ABSL_ATTRIBUTE_COLD;
+  LogMessageQuietlyFatal(const char* file, int line,
+                         absl::string_view failure_msg) ABSL_ATTRIBUTE_COLD;
+  ABSL_ATTRIBUTE_NORETURN ~LogMessageQuietlyFatal();
+};
+
+}  // namespace log_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+extern "C" ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(
+    AbslInternalOnFatalLogMessage)(const absl::LogEntry&);
+
+#endif  // ABSL_LOG_INTERNAL_LOG_MESSAGE_H_
diff --git a/absl/log/internal/log_sink_set.cc b/absl/log/internal/log_sink_set.cc
new file mode 100644
index 0000000..4fe301c
--- /dev/null
+++ b/absl/log/internal/log_sink_set.cc
@@ -0,0 +1,295 @@
+//
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/internal/log_sink_set.h"
+
+#ifndef ABSL_HAVE_THREAD_LOCAL
+#include <pthread.h>
+#endif
+
+#ifdef __ANDROID__
+#include <android/log.h>
+#endif
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#include <algorithm>
+#include <vector>
+
+#include "absl/base/attributes.h"
+#include "absl/base/call_once.h"
+#include "absl/base/config.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/base/log_severity.h"
+#include "absl/base/thread_annotations.h"
+#include "absl/cleanup/cleanup.h"
+#include "absl/log/globals.h"
+#include "absl/log/internal/config.h"
+#include "absl/log/internal/globals.h"
+#include "absl/log/log_entry.h"
+#include "absl/log/log_sink.h"
+#include "absl/strings/string_view.h"
+#include "absl/synchronization/mutex.h"
+#include "absl/types/span.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+namespace {
+
+// Returns a mutable reference to a thread-local variable that should be true if
+// a globally-registered `LogSink`'s `Send()` is currently being invoked on this
+// thread.
+bool& ThreadIsLoggingStatus() {
+#ifdef ABSL_HAVE_THREAD_LOCAL
+  ABSL_CONST_INIT thread_local bool thread_is_logging = false;
+  return thread_is_logging;
+#else
+  ABSL_CONST_INIT static pthread_key_t thread_is_logging_key;
+  static const bool unused = [] {
+    if (pthread_key_create(&thread_is_logging_key, [](void* data) {
+          delete reinterpret_cast<bool*>(data);
+        })) {
+      perror("pthread_key_create failed!");
+      abort();
+    }
+    return true;
+  }();
+  bool* thread_is_logging_ptr =
+      reinterpret_cast<bool*>(pthread_getspecific(thread_is_logging_key));
+
+  if (ABSL_PREDICT_FALSE(!thread_is_logging_ptr)) {
+    thread_is_logging_ptr = new bool{false};
+    if (pthread_setspecific(thread_is_logging_key, thread_is_logging_ptr)) {
+      perror("pthread_setspecific failed");
+      abort();
+    }
+  }
+  return *thread_is_logging_ptr;
+#endif
+}
+
+class StderrLogSink final : public LogSink {
+ public:
+  ~StderrLogSink() override = default;
+
+  void Send(const absl::LogEntry& entry) override {
+    if (entry.log_severity() < absl::StderrThreshold() &&
+        absl::log_internal::IsInitialized()) {
+      return;
+    }
+
+    ABSL_CONST_INIT static absl::once_flag warn_if_not_initialized;
+    absl::call_once(warn_if_not_initialized, []() {
+      if (absl::log_internal::IsInitialized()) return;
+      const char w[] =
+          "WARNING: All log messages before absl::InitializeLog() is called"
+          " are written to STDERR\n";
+      absl::log_internal::WriteToStderr(w, absl::LogSeverity::kWarning);
+    });
+
+    if (!entry.stacktrace().empty()) {
+      absl::log_internal::WriteToStderr(entry.stacktrace(),
+                                        entry.log_severity());
+    } else {
+      // TODO(b/226937039): do this outside else condition once we avoid
+      // ReprintFatalMessage
+      absl::log_internal::WriteToStderr(
+          entry.text_message_with_prefix_and_newline(), entry.log_severity());
+    }
+  }
+};
+
+#if defined(__ANDROID__)
+class AndroidLogSink final : public LogSink {
+ public:
+  ~AndroidLogSink() override = default;
+
+  void Send(const absl::LogEntry& entry) override {
+    const int level = AndroidLogLevel(entry);
+    // TODO(b/37587197): make the tag ("native") configurable.
+    __android_log_write(level, "native",
+                        entry.text_message_with_prefix_and_newline_c_str());
+    if (entry.log_severity() == absl::LogSeverity::kFatal)
+      __android_log_write(ANDROID_LOG_FATAL, "native", "terminating.\n");
+  }
+
+ private:
+  static int AndroidLogLevel(const absl::LogEntry& entry) {
+    switch (entry.log_severity()) {
+      case absl::LogSeverity::kFatal:
+        return ANDROID_LOG_FATAL;
+      case absl::LogSeverity::kError:
+        return ANDROID_LOG_ERROR;
+      case absl::LogSeverity::kWarning:
+        return ANDROID_LOG_WARN;
+      default:
+        if (entry.verbosity() >= 2) return ANDROID_LOG_VERBOSE;
+        if (entry.verbosity() == 1) return ANDROID_LOG_DEBUG;
+        return ANDROID_LOG_INFO;
+    }
+  }
+};
+#endif  // !defined(__ANDROID__)
+
+#if defined(_WIN32)
+class WindowsDebuggerLogSink final : public LogSink {
+ public:
+  ~WindowsDebuggerLogSink() override = default;
+
+  void Send(const absl::LogEntry& entry) override {
+    if (entry.log_severity() < absl::StderrThreshold() &&
+        absl::log_internal::IsInitialized()) {
+      return;
+    }
+    ::OutputDebugStringA(entry.text_message_with_prefix_and_newline_c_str());
+  }
+};
+#endif  // !defined(_WIN32)
+
+class GlobalLogSinkSet final {
+ public:
+  GlobalLogSinkSet() {
+#if defined(__myriad2__) || defined(__Fuchsia__)
+    // myriad2 and Fuchsia do not log to stderr by default.
+#else
+    static StderrLogSink* stderr_log_sink = new StderrLogSink;
+    AddLogSink(stderr_log_sink);
+#endif
+#ifdef __ANDROID__
+    static AndroidLogSink* android_log_sink = new AndroidLogSink;
+    AddLogSink(android_log_sink);
+#endif
+#if defined(_WIN32)
+    static WindowsDebuggerLogSink* debugger_log_sink =
+        new WindowsDebuggerLogSink;
+    AddLogSink(debugger_log_sink);
+#endif  // !defined(_WIN32)
+  }
+
+  void LogToSinks(const absl::LogEntry& entry,
+                  absl::Span<absl::LogSink*> extra_sinks, bool extra_sinks_only)
+      ABSL_LOCKS_EXCLUDED(guard_) {
+    SendToSinks(entry, extra_sinks);
+
+    if (!extra_sinks_only) {
+      if (ThreadIsLoggingToLogSink()) {
+        absl::log_internal::WriteToStderr(
+            entry.text_message_with_prefix_and_newline(), entry.log_severity());
+      } else {
+        absl::ReaderMutexLock global_sinks_lock(&guard_);
+        ThreadIsLoggingStatus() = true;
+        // Ensure the "thread is logging" status is reverted upon leaving the
+        // scope even in case of exceptions.
+        auto status_cleanup =
+            absl::MakeCleanup([] { ThreadIsLoggingStatus() = false; });
+        SendToSinks(entry, absl::MakeSpan(sinks_));
+      }
+    }
+  }
+
+  void AddLogSink(absl::LogSink* sink) ABSL_LOCKS_EXCLUDED(guard_) {
+    {
+      absl::WriterMutexLock global_sinks_lock(&guard_);
+      auto pos = std::find(sinks_.begin(), sinks_.end(), sink);
+      if (pos == sinks_.end()) {
+        sinks_.push_back(sink);
+        return;
+      }
+    }
+    ABSL_INTERNAL_LOG(FATAL, "Duplicate log sinks are not supported");
+  }
+
+  void RemoveLogSink(absl::LogSink* sink) ABSL_LOCKS_EXCLUDED(guard_) {
+    {
+      absl::WriterMutexLock global_sinks_lock(&guard_);
+      auto pos = std::find(sinks_.begin(), sinks_.end(), sink);
+      if (pos != sinks_.end()) {
+        sinks_.erase(pos);
+        return;
+      }
+    }
+    ABSL_INTERNAL_LOG(FATAL, "Mismatched log sink being removed");
+  }
+
+  void FlushLogSinks() ABSL_LOCKS_EXCLUDED(guard_) {
+    if (ThreadIsLoggingToLogSink()) {
+      // The thread_local condition demonstrates that we're already holding the
+      // lock in order to iterate over `sinks_` for dispatch.  The thread-safety
+      // annotations don't know this, so we use `ABSL_NO_THREAD_SAFETY_ANALYSIS`
+      guard_.AssertReaderHeld();
+      FlushLogSinksLocked();
+    } else {
+      absl::ReaderMutexLock global_sinks_lock(&guard_);
+      // In case if LogSink::Flush overload decides to log
+      ThreadIsLoggingStatus() = true;
+      // Ensure the "thread is logging" status is reverted upon leaving the
+      // scope even in case of exceptions.
+      auto status_cleanup =
+          absl::MakeCleanup([] { ThreadIsLoggingStatus() = false; });
+      FlushLogSinksLocked();
+    }
+  }
+
+ private:
+  void FlushLogSinksLocked() ABSL_SHARED_LOCKS_REQUIRED(guard_) {
+    for (absl::LogSink* sink : sinks_) {
+      sink->Flush();
+    }
+  }
+
+  // Helper routine for LogToSinks.
+  static void SendToSinks(const absl::LogEntry& entry,
+                          absl::Span<absl::LogSink*> sinks) {
+    for (absl::LogSink* sink : sinks) {
+      sink->Send(entry);
+    }
+  }
+
+  using LogSinksSet = std::vector<absl::LogSink*>;
+  absl::Mutex guard_;
+  LogSinksSet sinks_ ABSL_GUARDED_BY(guard_);
+};
+
+// Returns reference to the global LogSinks set.
+GlobalLogSinkSet& GlobalSinks() {
+  static GlobalLogSinkSet* global_sinks = new GlobalLogSinkSet;
+  return *global_sinks;
+}
+
+}  // namespace
+
+bool ThreadIsLoggingToLogSink() { return ThreadIsLoggingStatus(); }
+
+void LogToSinks(const absl::LogEntry& entry,
+                absl::Span<absl::LogSink*> extra_sinks, bool extra_sinks_only) {
+  log_internal::GlobalSinks().LogToSinks(entry, extra_sinks, extra_sinks_only);
+}
+
+void AddLogSink(absl::LogSink* sink) {
+  log_internal::GlobalSinks().AddLogSink(sink);
+}
+
+void RemoveLogSink(absl::LogSink* sink) {
+  log_internal::GlobalSinks().RemoveLogSink(sink);
+}
+
+void FlushLogSinks() { log_internal::GlobalSinks().FlushLogSinks(); }
+
+}  // namespace log_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/log/internal/log_sink_set.h b/absl/log/internal/log_sink_set.h
new file mode 100644
index 0000000..88ab073
--- /dev/null
+++ b/absl/log/internal/log_sink_set.h
@@ -0,0 +1,54 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/log_sink_set.h
+// -----------------------------------------------------------------------------
+
+#ifndef ABSL_LOG_INTERNAL_LOG_SINK_SET_H_
+#define ABSL_LOG_INTERNAL_LOG_SINK_SET_H_
+
+#include "absl/base/config.h"
+#include "absl/log/log_entry.h"
+#include "absl/log/log_sink.h"
+#include "absl/types/span.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+// Returns true if a globally-registered `LogSink`'s `Send()` is currently
+// being invoked on this thread.
+bool ThreadIsLoggingToLogSink();
+
+// This function may log to two sets of sinks:
+//
+// * If `extra_sinks_only` is true, it will dispatch only to `extra_sinks`.
+//   `LogMessage::ToSinkAlso` and `LogMessage::ToSinkOnly` are used to attach
+//    extra sinks to the entry.
+// * Otherwise it will also log to the global sinks set. This set is managed
+//   by `absl::AddLogSink` and `absl::RemoveLogSink`.
+void LogToSinks(const absl::LogEntry& entry,
+                absl::Span<absl::LogSink*> extra_sinks, bool extra_sinks_only);
+
+// Implementation for operations with log sink set.
+void AddLogSink(absl::LogSink* sink);
+void RemoveLogSink(absl::LogSink* sink);
+void FlushLogSinks();
+
+}  // namespace log_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_LOG_INTERNAL_LOG_SINK_SET_H_
diff --git a/absl/log/internal/nullguard.h b/absl/log/internal/nullguard.h
new file mode 100644
index 0000000..147ca81
--- /dev/null
+++ b/absl/log/internal/nullguard.h
@@ -0,0 +1,56 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/nullguard.h
+// -----------------------------------------------------------------------------
+//
+// NullGuard exists such that NullGuard<T>::Guard(v) returns v, unless passed a
+// nullptr_t, or a null char* or const char*, in which case it returns "(null)".
+// This allows streaming NullGuard<T>::Guard(v) to an output stream without
+// hitting undefined behavior for null values.
+
+#ifndef ABSL_LOG_INTERNAL_NULLGUARD_H_
+#define ABSL_LOG_INTERNAL_NULLGUARD_H_
+
+#include <cstddef>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+template <typename T>
+struct NullGuard final {
+  static const T& Guard(const T& v) { return v; }
+};
+template <>
+struct NullGuard<char*> final {
+  static const char* Guard(const char* v) { return v ? v : "(null)"; }
+};
+template <>
+struct NullGuard<const char*> final {
+  static const char* Guard(const char* v) { return v ? v : "(null)"; }
+};
+template <>
+struct NullGuard<std::nullptr_t> final {
+  static const char* Guard(const std::nullptr_t&) { return "(null)"; }
+};
+
+}  // namespace log_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_LOG_INTERNAL_NULLGUARD_H_
diff --git a/absl/log/internal/nullstream.h b/absl/log/internal/nullstream.h
new file mode 100644
index 0000000..80c62c9
--- /dev/null
+++ b/absl/log/internal/nullstream.h
@@ -0,0 +1,134 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/nullstream.h
+// -----------------------------------------------------------------------------
+//
+// Classes `NullStream`, `NullStreamMaybeFatal ` and `NullStreamFatal`
+// implement a subset of the `LogMessage` API and are used instead when logging
+// of messages has been disabled.
+
+#ifndef ABSL_LOG_INTERNAL_NULLSTREAM_H_
+#define ABSL_LOG_INTERNAL_NULLSTREAM_H_
+
+#ifdef _WIN32
+#include <cstdlib>
+#else
+#include <unistd.h>
+#endif
+#include <ios>
+#include <ostream>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/log_severity.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+// A `NullStream` implements the API of `LogMessage` (a few methods and
+// `operator<<`) but does nothing.  All methods are defined inline so the
+// compiler can eliminate the whole instance and discard anything that's
+// streamed in.
+class NullStream {
+ public:
+  NullStream& AtLocation(absl::string_view, int) { return *this; }
+  template <typename SourceLocationType>
+  NullStream& AtLocation(SourceLocationType) {
+    return *this;
+  }
+  NullStream& NoPrefix() { return *this; }
+  NullStream& WithVerbosity(int) { return *this; }
+  template <typename TimeType>
+  NullStream& WithTimestamp(TimeType) {
+    return *this;
+  }
+  template <typename Tid>
+  NullStream& WithThreadID(Tid) {
+    return *this;
+  }
+  template <typename LogEntryType>
+  NullStream& WithMetadataFrom(const LogEntryType&) {
+    return *this;
+  }
+  NullStream& WithPerror() { return *this; }
+  template <typename LogSinkType>
+  NullStream& ToSinkAlso(LogSinkType*) {
+    return *this;
+  }
+  template <typename LogSinkType>
+  NullStream& ToSinkOnly(LogSinkType*) {
+    return *this;
+  }
+  template <typename LogSinkType>
+  NullStream& OutputToSink(LogSinkType*, bool) {
+    return *this;
+  }
+  NullStream& InternalStream() { return *this; }
+};
+template <typename T>
+inline NullStream& operator<<(NullStream& str, const T&) {
+  return str;
+}
+inline NullStream& operator<<(NullStream& str,
+                              std::ostream& (*)(std::ostream& os)) {
+  return str;
+}
+inline NullStream& operator<<(NullStream& str,
+                              std::ios_base& (*)(std::ios_base& os)) {
+  return str;
+}
+
+// `NullStreamMaybeFatal` implements the process termination semantics of
+// `LogMessage`, which is used for `DFATAL` severity and expression-defined
+// severity e.g. `LOG(LEVEL(HowBadIsIt()))`.  Like `LogMessage`, it terminates
+// the process when destroyed if the passed-in severity equals `FATAL`.
+class NullStreamMaybeFatal final : public NullStream {
+ public:
+  explicit NullStreamMaybeFatal(absl::LogSeverity severity)
+      : fatal_(severity == absl::LogSeverity::kFatal) {}
+  ~NullStreamMaybeFatal() {
+    if (fatal_) _exit(1);
+  }
+
+ private:
+  bool fatal_;
+};
+
+// `NullStreamFatal` implements the process termination semantics of
+// `LogMessageFatal`, which means it always terminates the process.  `DFATAL`
+// and expression-defined severity use `NullStreamMaybeFatal` above.
+class NullStreamFatal final : public NullStream {
+ public:
+  NullStreamFatal() {}
+  // ABSL_ATTRIBUTE_NORETURN doesn't seem to work on destructors with msvc, so
+  // disable msvc's warning about the d'tor never returning.
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4722)
+#endif
+  ABSL_ATTRIBUTE_NORETURN ~NullStreamFatal() { _exit(1); }
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+};
+
+}  // namespace log_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_LOG_INTERNAL_GLOBALS_H_
diff --git a/absl/log/internal/stderr_log_sink_test.cc b/absl/log/internal/stderr_log_sink_test.cc
new file mode 100644
index 0000000..763690d
--- /dev/null
+++ b/absl/log/internal/stderr_log_sink_test.cc
@@ -0,0 +1,105 @@
+//
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <stdlib.h>
+
+#include <string>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/attributes.h"
+#include "absl/base/log_severity.h"
+#include "absl/log/globals.h"
+#include "absl/log/internal/test_helpers.h"
+#include "absl/log/log.h"
+
+namespace {
+using ::testing::AllOf;
+using ::testing::HasSubstr;
+
+auto* test_env ABSL_ATTRIBUTE_UNUSED = ::testing::AddGlobalTestEnvironment(
+    new absl::log_internal::LogTestEnvironment);
+
+MATCHER_P2(HasSubstrTimes, substr, expected_count, "") {
+  int count = 0;
+  std::string::size_type pos = 0;
+  std::string needle(substr);
+  while ((pos = arg.find(needle, pos)) != std::string::npos) {
+    ++count;
+    pos += needle.size();
+  }
+
+  return count == expected_count;
+}
+
+TEST(StderrLogSinkDeathTest, InfoMessagesInStderr) {
+  EXPECT_DEATH_IF_SUPPORTED(
+      {
+        absl::SetStderrThreshold(absl::LogSeverityAtLeast::kInfo);
+        LOG(INFO) << "INFO message";
+        exit(1);
+      },
+      "INFO message");
+}
+
+TEST(StderrLogSinkDeathTest, WarningMessagesInStderr) {
+  EXPECT_DEATH_IF_SUPPORTED(
+      {
+        absl::SetStderrThreshold(absl::LogSeverityAtLeast::kInfo);
+        LOG(WARNING) << "WARNING message";
+        exit(1);
+      },
+      "WARNING message");
+}
+
+TEST(StderrLogSinkDeathTest, ErrorMessagesInStderr) {
+  EXPECT_DEATH_IF_SUPPORTED(
+      {
+        absl::SetStderrThreshold(absl::LogSeverityAtLeast::kInfo);
+        LOG(ERROR) << "ERROR message";
+        exit(1);
+      },
+      "ERROR message");
+}
+
+TEST(StderrLogSinkDeathTest, FatalMessagesInStderr) {
+  char message[] = "FATAL message";
+  char stacktrace[] = "*** Check failure stack trace: ***";
+
+  int expected_count = 1;
+
+  EXPECT_DEATH_IF_SUPPORTED(
+      {
+        absl::SetStderrThreshold(absl::LogSeverityAtLeast::kInfo);
+        LOG(FATAL) << message;
+      },
+      AllOf(HasSubstrTimes(message, expected_count), HasSubstr(stacktrace)));
+}
+
+TEST(StderrLogSinkDeathTest, SecondaryFatalMessagesInStderr) {
+  auto MessageGen = []() -> std::string {
+    LOG(FATAL) << "Internal failure";
+    return "External failure";
+  };
+
+  EXPECT_DEATH_IF_SUPPORTED(
+      {
+        absl::SetStderrThreshold(absl::LogSeverityAtLeast::kInfo);
+        LOG(FATAL) << MessageGen();
+      },
+      "Internal failure");
+}
+
+}  // namespace
diff --git a/absl/log/internal/strip.h b/absl/log/internal/strip.h
new file mode 100644
index 0000000..848c386
--- /dev/null
+++ b/absl/log/internal/strip.h
@@ -0,0 +1,71 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/strip.h
+// -----------------------------------------------------------------------------
+//
+
+#ifndef ABSL_LOG_INTERNAL_STRIP_H_
+#define ABSL_LOG_INTERNAL_STRIP_H_
+
+#include "absl/base/log_severity.h"
+#include "absl/log/internal/log_message.h"
+#include "absl/log/internal/nullstream.h"
+
+// `ABSL_LOGGING_INTERNAL_LOG_*` evaluates to a temporary `LogMessage` object or
+// to a related object with a compatible API but different behavior.  This set
+// of defines comes in three flavors: vanilla, plus two variants that strip some
+// logging in subtly different ways for subtly different reasons (see below).
+#if defined(STRIP_LOG) && STRIP_LOG
+#define ABSL_LOGGING_INTERNAL_LOG_INFO ::absl::log_internal::NullStream()
+#define ABSL_LOGGING_INTERNAL_LOG_WARNING ::absl::log_internal::NullStream()
+#define ABSL_LOGGING_INTERNAL_LOG_ERROR ::absl::log_internal::NullStream()
+#define ABSL_LOGGING_INTERNAL_LOG_FATAL ::absl::log_internal::NullStreamFatal()
+#define ABSL_LOGGING_INTERNAL_LOG_QFATAL ::absl::log_internal::NullStreamFatal()
+#define ABSL_LOGGING_INTERNAL_LOG_DFATAL \
+  ::absl::log_internal::NullStreamMaybeFatal(::absl::kLogDebugFatal)
+#define ABSL_LOGGING_INTERNAL_LOG_LEVEL(severity) \
+  ::absl::log_internal::NullStreamMaybeFatal(log_internal_severity)
+#define ABSL_LOG_INTERNAL_CHECK(failure_message) ABSL_LOGGING_INTERNAL_LOG_FATAL
+#define ABSL_LOG_INTERNAL_QCHECK(failure_message) \
+  ABSL_LOGGING_INTERNAL_LOG_QFATAL
+#else  // !defined(STRIP_LOG) || !STRIP_LOG
+#define ABSL_LOGGING_INTERNAL_LOG_INFO                 \
+  ::absl::log_internal::LogMessage(__FILE__, __LINE__, \
+                                   ::absl::LogSeverity::kInfo)
+#define ABSL_LOGGING_INTERNAL_LOG_WARNING              \
+  ::absl::log_internal::LogMessage(__FILE__, __LINE__, \
+                                   ::absl::LogSeverity::kWarning)
+#define ABSL_LOGGING_INTERNAL_LOG_ERROR                \
+  ::absl::log_internal::LogMessage(__FILE__, __LINE__, \
+                                   ::absl::LogSeverity::kError)
+#define ABSL_LOGGING_INTERNAL_LOG_FATAL \
+  ::absl::log_internal::LogMessageFatal(__FILE__, __LINE__)
+#define ABSL_LOGGING_INTERNAL_LOG_QFATAL \
+  ::absl::log_internal::LogMessageQuietlyFatal(__FILE__, __LINE__)
+#define ABSL_LOGGING_INTERNAL_LOG_DFATAL \
+  ::absl::log_internal::LogMessage(__FILE__, __LINE__, ::absl::kLogDebugFatal)
+#define ABSL_LOGGING_INTERNAL_LOG_LEVEL(severity) \
+  ::absl::log_internal::LogMessage(__FILE__, __LINE__, log_internal_severity)
+// These special cases dispatch to special-case constructors that allow us to
+// avoid an extra function call and shrink non-LTO binaries by a percent or so.
+#define ABSL_LOG_INTERNAL_CHECK(failure_message) \
+  ::absl::log_internal::LogMessageFatal(__FILE__, __LINE__, failure_message)
+#define ABSL_LOG_INTERNAL_QCHECK(failure_message)                  \
+  ::absl::log_internal::LogMessageQuietlyFatal(__FILE__, __LINE__, \
+                                               failure_message)
+#endif  // !defined(STRIP_LOG) || !STRIP_LOG
+
+#endif  // ABSL_LOG_INTERNAL_STRIP_H_
diff --git a/absl/log/internal/test_actions.cc b/absl/log/internal/test_actions.cc
new file mode 100644
index 0000000..41ca988
--- /dev/null
+++ b/absl/log/internal/test_actions.cc
@@ -0,0 +1,68 @@
+//
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/internal/test_actions.h"
+
+#include <cassert>
+#include <iostream>
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/log/internal/config.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/string_view.h"
+#include "absl/time/time.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+void WriteToStderrWithFilename::operator()(const absl::LogEntry& entry) const {
+  std::cerr << message << " (file: " << entry.source_filename() << ")"
+            << std::endl;
+}
+
+void WriteEntryToStderr::operator()(const absl::LogEntry& entry) const {
+  if (!message.empty()) std::cerr << message << std::endl;
+
+  std::cerr << "LogEntry{\n"
+            << "  source_filename: \""
+            << absl::CHexEscape(entry.source_filename()) << "\"\n"
+            << "  source_basename: \""
+            << absl::CHexEscape(entry.source_basename()) << "\"\n"
+            << "  source_line: " << entry.source_line() << "\n"
+            << "  prefix: " << (entry.prefix() ? "true\n" : "false\n")
+            << "  log_severity: " << entry.log_severity() << "\n"
+            << "  timestamp: " << entry.timestamp() << "\n"
+            << "  text_message: \"" << absl::CHexEscape(entry.text_message())
+            << "\"\n  verbosity: " << entry.verbosity() << "\n"
+            << "}" << std::endl;
+}
+
+void WriteEntryToStderr::operator()(absl::LogSeverity severity,
+                                    absl::string_view filename,
+                                    absl::string_view log_message) const {
+  if (!message.empty()) std::cerr << message << std::endl;
+
+  std::cerr << "LogEntry{\n"
+            << "  source_filename: \"" << absl::CHexEscape(filename) << "\"\n"
+            << "  log_severity: " << severity << "\n"
+            << "  text_message: \"" << absl::CHexEscape(log_message) << "}"
+            << std::endl;
+}
+
+}  // namespace log_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/log/internal/test_actions.h b/absl/log/internal/test_actions.h
new file mode 100644
index 0000000..649a050
--- /dev/null
+++ b/absl/log/internal/test_actions.h
@@ -0,0 +1,90 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/test_actions.h
+// -----------------------------------------------------------------------------
+//
+// This file declares Googletest's actions used in the Abseil Logging library
+// unit tests.
+
+#ifndef ABSL_LOG_INTERNAL_TEST_ACTIONS_H_
+#define ABSL_LOG_INTERNAL_TEST_ACTIONS_H_
+
+#include <iostream>
+#include <ostream>
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/base/log_severity.h"
+#include "absl/log/log_entry.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+// These actions are used by the child process in a death test.
+//
+// Expectations set in the child cannot cause test failure in the parent
+// directly.  Instead, the child can use these actions with
+// `EXPECT_CALL`/`WillOnce` and `ON_CALL`/`WillByDefault` (for unexpected calls)
+// to write messages to stderr that the parent can match against.
+struct WriteToStderr final {
+  explicit WriteToStderr(absl::string_view m) : message(m) {}
+  std::string message;
+
+  template <typename... Args>
+  void operator()(const Args&...) const {
+    std::cerr << message << std::endl;
+  }
+};
+
+struct WriteToStderrWithFilename final {
+  explicit WriteToStderrWithFilename(absl::string_view m) : message(m) {}
+
+  std::string message;
+
+  void operator()(const absl::LogEntry& entry) const;
+};
+
+struct WriteEntryToStderr final {
+  explicit WriteEntryToStderr(absl::string_view m) : message(m) {}
+
+  std::string message = "";
+
+  void operator()(const absl::LogEntry& entry) const;
+  void operator()(absl::LogSeverity, absl::string_view,
+                  absl::string_view) const;
+};
+
+// See the documentation for `DeathTestValidateExpectations` above.
+// `DeathTestExpectedLogging` should be used once in a given death test, and the
+// applicable severity level is the one that should be passed to
+// `DeathTestValidateExpectations`.
+inline WriteEntryToStderr DeathTestExpectedLogging() {
+  return WriteEntryToStderr{"Mock received expected entry:"};
+}
+
+// `DeathTestUnexpectedLogging` should be used zero or more times to mark
+// messages that should not hit the logs as the process dies.
+inline WriteEntryToStderr DeathTestUnexpectedLogging() {
+  return WriteEntryToStderr{"Mock received unexpected entry:"};
+}
+
+}  // namespace log_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_LOG_INTERNAL_TEST_ACTIONS_H_
diff --git a/absl/log/internal/test_helpers.cc b/absl/log/internal/test_helpers.cc
new file mode 100644
index 0000000..bff5cc1
--- /dev/null
+++ b/absl/log/internal/test_helpers.cc
@@ -0,0 +1,82 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include "absl/log/internal/test_helpers.h"
+
+#ifdef __Fuchsia__
+#include <zircon/syscalls.h>
+#endif
+
+#include "gtest/gtest.h"
+#include "absl/base/config.h"
+#include "absl/base/log_severity.h"
+#include "absl/log/globals.h"
+#include "absl/log/initialize.h"
+#include "absl/log/internal/globals.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+// Returns false if the specified severity level is disabled by
+// `ABSL_MIN_LOG_LEVEL` or `absl::MinLogLevel()`.
+bool LoggingEnabledAt(absl::LogSeverity severity) {
+  return severity >= kAbslMinLogLevel && severity >= absl::MinLogLevel();
+}
+
+// -----------------------------------------------------------------------------
+// Googletest Death Test Predicates
+// -----------------------------------------------------------------------------
+
+#if GTEST_HAS_DEATH_TEST
+
+bool DiedOfFatal(int exit_status) {
+#if defined(_WIN32)
+  // Depending on NDEBUG and (configuration?) MSVC's abort either results
+  // in error code 3 (SIGABRT) or error code 0x80000003 (breakpoint
+  // triggered).
+  return ::testing::ExitedWithCode(3)(exit_status & ~0x80000000);
+#elif defined(__Fuchsia__)
+  // The Fuchsia death test implementation kill()'s the process when it detects
+  // an exception, so it should exit with the corresponding code. See
+  // FuchsiaDeathTest::Wait().
+  return ::testing::ExitedWithCode(ZX_TASK_RETCODE_SYSCALL_KILL)(exit_status);
+#elif defined(__ANDROID__) && defined(__aarch64__)
+  // These are all run under a qemu config that eats died-due-to-signal exit
+  // statuses.
+  return true;
+#else
+  return ::testing::KilledBySignal(SIGABRT)(exit_status);
+#endif
+}
+
+bool DiedOfQFatal(int exit_status) {
+  return ::testing::ExitedWithCode(1)(exit_status);
+}
+
+#endif
+
+// -----------------------------------------------------------------------------
+// Helper for Log inititalization in test
+// -----------------------------------------------------------------------------
+
+void LogTestEnvironment::SetUp() {
+  if (!absl::log_internal::IsInitialized()) {
+    absl::InitializeLog();
+  }
+}
+
+}  // namespace log_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/log/internal/test_helpers.h b/absl/log/internal/test_helpers.h
new file mode 100644
index 0000000..fd06e29
--- /dev/null
+++ b/absl/log/internal/test_helpers.h
@@ -0,0 +1,71 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/test_helpers.h
+// -----------------------------------------------------------------------------
+//
+// This file declares testing helpers for the logging library.
+
+#ifndef ABSL_LOG_INTERNAL_TEST_HELPERS_H_
+#define ABSL_LOG_INTERNAL_TEST_HELPERS_H_
+
+#include "gtest/gtest.h"
+#include "absl/base/config.h"
+#include "absl/base/log_severity.h"
+#include "absl/log/globals.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+// `ABSL_MIN_LOG_LEVEL` can't be used directly since it is not always defined.
+constexpr auto kAbslMinLogLevel =
+#ifdef ABSL_MIN_LOG_LEVEL
+    static_cast<absl::LogSeverityAtLeast>(ABSL_MIN_LOG_LEVEL);
+#else
+    absl::LogSeverityAtLeast::kInfo;
+#endif
+
+// Returns false if the specified severity level is disabled by
+// `ABSL_MIN_LOG_LEVEL` or `absl::MinLogLevel()`.
+bool LoggingEnabledAt(absl::LogSeverity severity);
+
+// -----------------------------------------------------------------------------
+// Googletest Death Test Predicates
+// -----------------------------------------------------------------------------
+
+#if GTEST_HAS_DEATH_TEST
+
+bool DiedOfFatal(int exit_status);
+bool DiedOfQFatal(int exit_status);
+
+#endif
+
+// -----------------------------------------------------------------------------
+// Helper for Log inititalization in test
+// -----------------------------------------------------------------------------
+
+class LogTestEnvironment : public ::testing::Environment {
+ public:
+  ~LogTestEnvironment() override = default;
+
+  void SetUp() override;
+};
+
+}  // namespace log_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_LOG_INTERNAL_TEST_HELPERS_H_
diff --git a/absl/log/internal/test_matchers.cc b/absl/log/internal/test_matchers.cc
new file mode 100644
index 0000000..ee32617
--- /dev/null
+++ b/absl/log/internal/test_matchers.cc
@@ -0,0 +1,168 @@
+//
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/internal/test_matchers.h"
+
+#include <sstream>
+#include <string>
+#include <utility>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/config.h"
+#include "absl/log/internal/config.h"
+#include "absl/log/internal/test_helpers.h"
+#include "absl/strings/string_view.h"
+#include "absl/time/clock.h"
+#include "absl/time/time.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+::testing::Matcher<const absl::LogEntry&> SourceFilename(
+    const ::testing::Matcher<absl::string_view>& source_filename) {
+  return Property("source_filename", &absl::LogEntry::source_filename,
+                  source_filename);
+}
+
+::testing::Matcher<const absl::LogEntry&> SourceBasename(
+    const ::testing::Matcher<absl::string_view>& source_basename) {
+  return Property("source_basename", &absl::LogEntry::source_basename,
+                  source_basename);
+}
+
+::testing::Matcher<const absl::LogEntry&> SourceLine(
+    const ::testing::Matcher<int>& source_line) {
+  return Property("source_line", &absl::LogEntry::source_line, source_line);
+}
+
+::testing::Matcher<const absl::LogEntry&> Prefix(
+    const ::testing::Matcher<bool>& prefix) {
+  return Property("prefix", &absl::LogEntry::prefix, prefix);
+}
+
+::testing::Matcher<const absl::LogEntry&> LogSeverity(
+    const ::testing::Matcher<absl::LogSeverity>& log_severity) {
+  return Property("log_severity", &absl::LogEntry::log_severity, log_severity);
+}
+
+::testing::Matcher<const absl::LogEntry&> Timestamp(
+    const ::testing::Matcher<absl::Time>& timestamp) {
+  return Property("timestamp", &absl::LogEntry::timestamp, timestamp);
+}
+
+::testing::Matcher<const absl::LogEntry&> TimestampInMatchWindow() {
+  return Property("timestamp", &absl::LogEntry::timestamp,
+                  ::testing::AllOf(::testing::Ge(absl::Now()),
+                                   ::testing::Truly([](absl::Time arg) {
+                                     return arg <= absl::Now();
+                                   })));
+}
+
+::testing::Matcher<const absl::LogEntry&> ThreadID(
+    const ::testing::Matcher<absl::LogEntry::tid_t>& tid) {
+  return Property("tid", &absl::LogEntry::tid, tid);
+}
+
+::testing::Matcher<const absl::LogEntry&> TextMessageWithPrefixAndNewline(
+    const ::testing::Matcher<absl::string_view>&
+        text_message_with_prefix_and_newline) {
+  return Property("text_message_with_prefix_and_newline",
+                  &absl::LogEntry::text_message_with_prefix_and_newline,
+                  text_message_with_prefix_and_newline);
+}
+
+::testing::Matcher<const absl::LogEntry&> TextMessageWithPrefix(
+    const ::testing::Matcher<absl::string_view>& text_message_with_prefix) {
+  return Property("text_message_with_prefix",
+                  &absl::LogEntry::text_message_with_prefix,
+                  text_message_with_prefix);
+}
+
+::testing::Matcher<const absl::LogEntry&> TextMessage(
+    const ::testing::Matcher<absl::string_view>& text_message) {
+  return Property("text_message", &absl::LogEntry::text_message, text_message);
+}
+
+::testing::Matcher<const absl::LogEntry&> TextPrefix(
+    const ::testing::Matcher<absl::string_view>& text_prefix) {
+  return ResultOf(
+      [](const absl::LogEntry& entry) {
+        absl::string_view msg = entry.text_message_with_prefix();
+        msg.remove_suffix(entry.text_message().size());
+        return msg;
+      },
+      text_prefix);
+}
+
+::testing::Matcher<const absl::LogEntry&> Verbosity(
+    const ::testing::Matcher<int>& verbosity) {
+  return Property("verbosity", &absl::LogEntry::verbosity, verbosity);
+}
+
+::testing::Matcher<const absl::LogEntry&> Stacktrace(
+    const ::testing::Matcher<absl::string_view>& stacktrace) {
+  return Property("stacktrace", &absl::LogEntry::stacktrace, stacktrace);
+}
+
+class MatchesOstreamImpl final
+    : public ::testing::MatcherInterface<absl::string_view> {
+ public:
+  explicit MatchesOstreamImpl(std::string expected)
+      : expected_(std::move(expected)) {}
+  bool MatchAndExplain(absl::string_view actual,
+                       ::testing::MatchResultListener*) const override {
+    return actual == expected_;
+  }
+  void DescribeTo(std::ostream* os) const override {
+    *os << "matches the contents of the ostringstream, which are \""
+        << expected_ << "\"";
+  }
+
+  void DescribeNegationTo(std::ostream* os) const override {
+    *os << "does not match the contents of the ostringstream, which are \""
+        << expected_ << "\"";
+  }
+
+ private:
+  const std::string expected_;
+};
+::testing::Matcher<absl::string_view> MatchesOstream(
+    const std::ostringstream& stream) {
+  return ::testing::MakeMatcher(new MatchesOstreamImpl(stream.str()));
+}
+
+// We need to validate what is and isn't logged as the process dies due to
+// `FATAL`, `QFATAL`, `CHECK`, etc., but assertions inside a death test
+// subprocess don't directly affect the pass/fail status of the parent process.
+// Instead, we use the mock actions `DeathTestExpectedLogging` and
+// `DeathTestUnexpectedLogging` to write specific phrases to `stderr` that we
+// can validate in the parent process using this matcher.
+::testing::Matcher<const std::string&> DeathTestValidateExpectations() {
+  if (log_internal::LoggingEnabledAt(absl::LogSeverity::kFatal)) {
+    return ::testing::Matcher<const std::string&>(::testing::AllOf(
+        ::testing::HasSubstr("Mock received expected entry"),
+        Not(::testing::HasSubstr("Mock received unexpected entry"))));
+  }
+  // If `FATAL` logging is disabled, neither message should have been written.
+  return ::testing::Matcher<const std::string&>(::testing::AllOf(
+      Not(::testing::HasSubstr("Mock received expected entry")),
+      Not(::testing::HasSubstr("Mock received unexpected entry"))));
+}
+
+}  // namespace log_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/log/internal/test_matchers.h b/absl/log/internal/test_matchers.h
new file mode 100644
index 0000000..b8179cc
--- /dev/null
+++ b/absl/log/internal/test_matchers.h
@@ -0,0 +1,90 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/test_matchers.h
+// -----------------------------------------------------------------------------
+//
+// This file declares Googletest's matchers used in the Abseil Logging library
+// unit tests.
+
+#ifndef ABSL_LOG_INTERNAL_TEST_MATCHERS_H_
+#define ABSL_LOG_INTERNAL_TEST_MATCHERS_H_
+
+#include <iosfwd>
+#include <sstream>
+#include <string>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/config.h"
+#include "absl/base/log_severity.h"
+#include "absl/log/internal/config.h"
+#include "absl/log/internal/test_helpers.h"
+#include "absl/log/log_entry.h"
+#include "absl/strings/string_view.h"
+#include "absl/time/time.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+// These matchers correspond to the components of `absl::LogEntry`.
+::testing::Matcher<const absl::LogEntry&> SourceFilename(
+    const ::testing::Matcher<absl::string_view>& source_filename);
+::testing::Matcher<const absl::LogEntry&> SourceBasename(
+    const ::testing::Matcher<absl::string_view>& source_basename);
+// Be careful with this one; multi-line statements using `__LINE__` evaluate
+// differently on different platforms.  In particular, the MSVC implementation
+// of `EXPECT_DEATH` returns the line number of the macro expansion to all lines
+// within the code block that's expected to die.
+::testing::Matcher<const absl::LogEntry&> SourceLine(
+    const ::testing::Matcher<int>& source_line);
+::testing::Matcher<const absl::LogEntry&> Prefix(
+    const ::testing::Matcher<bool>& prefix);
+::testing::Matcher<const absl::LogEntry&> LogSeverity(
+    const ::testing::Matcher<absl::LogSeverity>& log_severity);
+::testing::Matcher<const absl::LogEntry&> Timestamp(
+    const ::testing::Matcher<absl::Time>& timestamp);
+// Matches if the `LogEntry`'s timestamp falls after the instantiation of this
+// matcher and before its execution, as is normal when used with EXPECT_CALL.
+::testing::Matcher<const absl::LogEntry&> TimestampInMatchWindow();
+::testing::Matcher<const absl::LogEntry&> ThreadID(
+    const ::testing::Matcher<absl::LogEntry::tid_t>&);
+::testing::Matcher<const absl::LogEntry&> TextMessageWithPrefixAndNewline(
+    const ::testing::Matcher<absl::string_view>&
+        text_message_with_prefix_and_newline);
+::testing::Matcher<const absl::LogEntry&> TextMessageWithPrefix(
+    const ::testing::Matcher<absl::string_view>& text_message_with_prefix);
+::testing::Matcher<const absl::LogEntry&> TextMessage(
+    const ::testing::Matcher<absl::string_view>& text_message);
+::testing::Matcher<const absl::LogEntry&> TextPrefix(
+    const ::testing::Matcher<absl::string_view>& text_prefix);
+::testing::Matcher<const absl::LogEntry&> Verbosity(
+    const ::testing::Matcher<int>& verbosity);
+::testing::Matcher<const absl::LogEntry&> Stacktrace(
+    const ::testing::Matcher<absl::string_view>& stacktrace);
+// Behaves as `Eq(stream.str())`, but produces better failure messages.
+::testing::Matcher<absl::string_view> MatchesOstream(
+    const std::ostringstream& stream);
+::testing::Matcher<const std::string&> DeathTestValidateExpectations();
+
+// This feature coming soon =).
+#define ENCODED_MESSAGE(message_matcher) ::testing::_
+
+}  // namespace log_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_LOG_INTERNAL_TEST_MATCHERS_H_
diff --git a/absl/log/internal/voidify.h b/absl/log/internal/voidify.h
new file mode 100644
index 0000000..8f62da2
--- /dev/null
+++ b/absl/log/internal/voidify.h
@@ -0,0 +1,44 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/voidify.h
+// -----------------------------------------------------------------------------
+//
+// This class is used to explicitly ignore values in the conditional logging
+// macros. This avoids compiler warnings like "value computed is not used" and
+// "statement has no effect".
+
+#ifndef ABSL_LOG_INTERNAL_VOIDIFY_H_
+#define ABSL_LOG_INTERNAL_VOIDIFY_H_
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+class Voidify final {
+ public:
+  // This has to be an operator with a precedence lower than << but higher than
+  // ?:
+  template <typename T>
+  void operator&&(const T&) const&& {}
+};
+
+}  // namespace log_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_LOG_INTERNAL_VOIDIFY_H_
diff --git a/absl/log/log.h b/absl/log/log.h
new file mode 100644
index 0000000..13c4938
--- /dev/null
+++ b/absl/log/log.h
@@ -0,0 +1,439 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/log.h
+// -----------------------------------------------------------------------------
+//
+// This header declares a family of LOG macros.
+//
+// Basic invocation looks like this:
+//
+//   LOG(INFO) << "Found " << num_cookies << " cookies";
+//
+// Most `LOG` macros take a severity level argument.  The severity levels are
+// `INFO`, `WARNING`, `ERROR`, and `FATAL`.  They are defined
+// in absl/base/log_severity.h.
+// * The `FATAL` severity level terminates the program with a stack trace after
+//   logging its message.  Error handlers registered with `RunOnFailure`
+//   (process_state.h) are run, but exit handlers registered with `atexit(3)`
+//   are not.
+// * The `QFATAL` pseudo-severity level is equivalent to `FATAL` but triggers
+//   quieter termination messages, e.g. without a full stack trace, and skips
+//   running registered error handlers.
+// Some preprocessor shenanigans are used to ensure that e.g. `LOG(INFO)` has
+// the same meaning even if a local symbol or preprocessor macro named `INFO` is
+// defined.  To specify a severity level using an expression instead of a
+// literal, use `LEVEL(expr)`.
+// Example:
+//
+//   LOG(LEVEL(stale ? absl::LogSeverity::kWarning : absl::LogSeverity::kInfo))
+//       << "Cookies are " << days << " days old";
+
+// `LOG` macros evaluate to an unterminated statement.  The value at the end of
+// the statement supports some chainable methods:
+//
+//   * .AtLocation(absl::string_view file, int line)
+//     .AtLocation(absl::SourceLocation loc)
+//     Overrides the location inferred from the callsite.  The string pointed to
+//     by `file` must be valid until the end of the statement.
+//   * .NoPrefix()
+//     Omits the prefix from this line.  The prefix includes metadata about the
+//     logged data such as source code location and timestamp.
+//   * .WithTimestamp(absl::Time timestamp)
+//     Uses the specified timestamp instead of one collected at the time of
+//     execution.
+//   * .WithThreadID(absl::LogEntry::tid_t tid)
+//     Uses the specified thread ID instead of one collected at the time of
+//     execution.
+//   * .WithMetadataFrom(const absl::LogEntry &entry)
+//     Copies all metadata (but no data) from the specified `absl::LogEntry`.
+//     This can be used to change the severity of a message, but it has some
+//     limitations:
+//     * `ABSL_MIN_LOG_LEVEL` is evaluated against the severity passed into
+//       `LOG` (or the implicit `FATAL` level of `CHECK`).
+//     * `LOG(FATAL)` and `CHECK` terminate the process unconditionally, even if
+//       the severity is changed later.
+//     `.WithMetadataFrom(entry)` should almost always be used in combination
+//     with `LOG(LEVEL(entry.log_severity()))`.
+//   * .WithPerror()
+//     Appends to the logged message a colon, a space, a textual description of
+//     the current value of `errno` (as by `strerror(3)`), and the numerical
+//     value of `errno`.
+//   * .ToSinkAlso(absl::LogSink* sink)
+//     Sends this message to `*sink` in addition to whatever other sinks it
+//     would otherwise have been sent to.  `sink` must not be null.
+//   * .ToSinkOnly(absl::LogSink* sink)
+//     Sends this message to `*sink` and no others.  `sink` must not be null.
+//
+// No interfaces in this header are async-signal-safe; their use in signal
+// handlers is unsupported and may deadlock your program or eat your lunch.
+//
+// Many logging statements are inherently conditional.  For example,
+// `LOG_IF(INFO, !foo)` does nothing if `foo` is true.  Even seemingly
+// unconditional statements like `LOG(INFO)` might be disabled at
+// compile-time to minimize binary size or for security reasons.
+//
+// * Except for the condition in a `CHECK` or `QCHECK` statement, programs must
+//   not rely on evaluation of expressions anywhere in logging statements for
+//   correctness.  For example, this is ok:
+//
+//     CHECK((fp = fopen("config.ini", "r")) != nullptr);
+//
+//   But this is probably not ok:
+//
+//     LOG(INFO) << "Server status: " << StartServerAndReturnStatusString();
+//
+//   The example below is bad too; the `i++` in the `LOG_IF` condition might
+//   not be evaluated, resulting in an infinite loop:
+//
+//     for (int i = 0; i < 1000000;)
+//       LOG_IF(INFO, i++ % 1000 == 0) << "Still working...";
+//
+// * Except where otherwise noted, conditions which cause a statement not to log
+//   also cause expressions not to be evaluated.  Programs may rely on this for
+//   performance reasons, e.g. by streaming the result of an expensive function
+//   call into a `DLOG` or `LOG_EVERY_N` statement.
+// * Care has been taken to ensure that expressions are parsed by the compiler
+//   even if they are never evaluated.  This means that syntax errors will be
+//   caught and variables will be considered used for the purposes of
+//   unused-variable diagnostics.  For example, this statement won't compile
+//   even if `INFO`-level logging has been compiled out:
+//
+//     int number_of_cakes = 40;
+//     LOG(INFO) << "Number of cakes: " << number_of_cake;  // Note the typo!
+//
+//   Similarly, this won't produce unused-variable compiler diagnostics even
+//   if `INFO`-level logging is compiled out:
+//
+//     {
+//       char fox_line1[] = "Hatee-hatee-hatee-ho!";
+//       LOG_IF(ERROR, false) << "The fox says " << fox_line1;
+//       char fox_line2[] = "A-oo-oo-oo-ooo!";
+//       LOG(INFO) << "The fox also says " << fox_line2;
+//     }
+//
+//   This error-checking is not perfect; for example, symbols that have been
+//   declared but not defined may not produce link errors if used in logging
+//   statements that compile away.
+//
+// Expressions streamed into these macros are formatted using `operator<<` just
+// as they would be if streamed into a `std::ostream`, however it should be
+// noted that their actual type is unspecified.
+//
+// To implement a custom formatting operator for a type you own, define
+// `std::ostream& operator<<(std::ostream&, ...)` in your type's namespace (for
+// ADL) just as you would to stream it to `std::cout`.
+//
+// Those macros that support streaming honor output manipulators and `fmtflag`
+// changes that output data (e.g. `std::ends`) or control formatting of data
+// (e.g. `std::hex` and `std::fixed`), however flushing such a stream is
+// ignored.  The message produced by a log statement is sent to registered
+// `absl::LogSink` instances at the end of the statement; those sinks are
+// responsible for their own flushing (e.g. to disk) semantics.
+//
+// Flag settings are not carried over from one `LOG` statement to the next; this
+// is a bit different than e.g. `std::cout`:
+//
+//   LOG(INFO) << std::hex << 0xdeadbeef;  // logs "0xdeadbeef"
+//   LOG(INFO) << 0xdeadbeef;              // logs "3735928559"
+
+#ifndef ABSL_LOG_LOG_H_
+#define ABSL_LOG_LOG_H_
+
+#include "absl/log/internal/conditions.h"
+#include "absl/log/internal/log_message.h"
+#include "absl/log/internal/strip.h"
+
+// LOG()
+//
+// `LOG` takes a single argument which is a severity level.  Data streamed in
+// comprise the logged message.
+// Example:
+//
+//   LOG(INFO) << "Found " << num_cookies << " cookies";
+#define LOG(severity)                                     \
+  ABSL_LOG_INTERNAL_CONDITION_##severity(STATELESS, true) \
+      ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()
+
+// PLOG()
+//
+// `PLOG` behaves like `LOG` except that a description of the current state of
+// `errno` is appended to the streamed message.
+#define PLOG(severity)                                      \
+  ABSL_LOG_INTERNAL_CONDITION_##severity(STATELESS, true)   \
+      ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream() \
+          .WithPerror()
+
+// DLOG()
+//
+// `DLOG` behaves like `LOG` in debug mode (i.e. `#ifndef NDEBUG`).  Otherwise
+// it compiles away and does nothing.  Note that `DLOG(FATAL)` does not
+// terminate the program if `NDEBUG` is defined.
+#ifndef NDEBUG
+#define DLOG(severity)                                    \
+  ABSL_LOG_INTERNAL_CONDITION_##severity(STATELESS, true) \
+      ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()
+#else
+#define DLOG(severity)                                     \
+  ABSL_LOG_INTERNAL_CONDITION_##severity(STATELESS, false) \
+      ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()
+#endif
+
+// `LOG_IF` and friends add a second argument which specifies a condition.  If
+// the condition is false, nothing is logged.
+// Example:
+//
+//   LOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";
+//
+// There is no `VLOG_IF` because the order of evaluation of the arguments is
+// ambiguous and the alternate spelling with an `if`-statement is trivial.
+#define LOG_IF(severity, condition)                            \
+  ABSL_LOG_INTERNAL_CONDITION_##severity(STATELESS, condition) \
+      ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()
+#define PLOG_IF(severity, condition)                           \
+  ABSL_LOG_INTERNAL_CONDITION_##severity(STATELESS, condition) \
+      ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()    \
+          .WithPerror()
+
+#ifndef NDEBUG
+#define DLOG_IF(severity, condition)                           \
+  ABSL_LOG_INTERNAL_CONDITION_##severity(STATELESS, condition) \
+      ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()
+#else
+#define DLOG_IF(severity, condition)                                      \
+  ABSL_LOG_INTERNAL_CONDITION_##severity(STATELESS, false && (condition)) \
+      ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()
+#endif
+
+// LOG_EVERY_N
+//
+// An instance of `LOG_EVERY_N` increments a hidden zero-initialized counter
+// every time execution passes through it and logs the specified message when
+// the counter's value is a multiple of `n`, doing nothing otherwise.  Each
+// instance has its own counter.  The counter's value can be logged by streaming
+// the symbol `COUNTER`.  `LOG_EVERY_N` is thread-safe.
+// Example:
+//
+//   LOG_EVERY_N(WARNING, 1000) << "Got a packet with a bad CRC (" << COUNTER
+//                              << " total)";
+#define LOG_EVERY_N(severity, n)                                    \
+  ABSL_LOG_INTERNAL_CONDITION_##severity(STATEFUL, true)(EveryN, n) \
+      ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()
+
+// LOG_FIRST_N
+//
+// `LOG_FIRST_N` behaves like `LOG_EVERY_N` except that the specified message is
+// logged when the counter's value is less than `n`.  `LOG_FIRST_N` is
+// thread-safe.
+#define LOG_FIRST_N(severity, n)                                    \
+  ABSL_LOG_INTERNAL_CONDITION_##severity(STATEFUL, true)(FirstN, n) \
+      ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()
+
+// LOG_EVERY_POW_2
+//
+// `LOG_EVERY_POW_2` behaves like `LOG_EVERY_N` except that the specified
+// message is logged when the counter's value is a power of 2.
+// `LOG_EVERY_POW_2` is thread-safe.
+#define LOG_EVERY_POW_2(severity)                                   \
+  ABSL_LOG_INTERNAL_CONDITION_##severity(STATEFUL, true)(EveryPow2) \
+      ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()
+
+// LOG_EVERY_N_SEC
+//
+// An instance of `LOG_EVERY_N_SEC` uses a hidden state variable to log the
+// specified message at most once every `n_seconds`.  A hidden counter of
+// executions (whether a message is logged or not) is also maintained and can be
+// logged by streaming the symbol `COUNTER`.  `LOG_EVERY_N_SEC` is thread-safe.
+// Example:
+//
+//   LOG_EVERY_N_SEC(INFO, 2.5) << "Got " << COUNTER << " cookies so far";
+#define LOG_EVERY_N_SEC(severity, n_seconds)                                   \
+  ABSL_LOG_INTERNAL_CONDITION_##severity(STATEFUL, true)(EveryNSec, n_seconds) \
+      ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()
+
+#define PLOG_EVERY_N(severity, n)                                   \
+  ABSL_LOG_INTERNAL_CONDITION_##severity(STATEFUL, true)(EveryN, n) \
+      ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()         \
+          .WithPerror()
+
+#define PLOG_FIRST_N(severity, n)                                   \
+  ABSL_LOG_INTERNAL_CONDITION_##severity(STATEFUL, true)(FirstN, n) \
+      ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()         \
+          .WithPerror()
+
+#define PLOG_EVERY_POW_2(severity)                                  \
+  ABSL_LOG_INTERNAL_CONDITION_##severity(STATEFUL, true)(EveryPow2) \
+      ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()         \
+          .WithPerror()
+
+#define PLOG_EVERY_N_SEC(severity, n_seconds)                                  \
+  ABSL_LOG_INTERNAL_CONDITION_##severity(STATEFUL, true)(EveryNSec, n_seconds) \
+      ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()                    \
+          .WithPerror()
+
+#ifndef NDEBUG
+#define DLOG_EVERY_N(severity, n)                  \
+  ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, true) \
+  (EveryN, n) ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()
+
+#define DLOG_FIRST_N(severity, n)                  \
+  ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, true) \
+  (FirstN, n) ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()
+
+#define DLOG_EVERY_POW_2(severity)                 \
+  ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, true) \
+  (EveryPow2) ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()
+
+#define DLOG_EVERY_N_SEC(severity, n_seconds)      \
+  ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, true) \
+  (EveryNSec, n_seconds) ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()
+
+#else  // def NDEBUG
+#define DLOG_EVERY_N(severity, n)                   \
+  ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, false) \
+  (EveryN, n) ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()
+
+#define DLOG_FIRST_N(severity, n)                   \
+  ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, false) \
+  (FirstN, n) ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()
+
+#define DLOG_EVERY_POW_2(severity)                  \
+  ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, false) \
+  (EveryPow2) ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()
+
+#define DLOG_EVERY_N_SEC(severity, n_seconds)       \
+  ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, false) \
+  (EveryNSec, n_seconds) ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()
+#endif  // def NDEBUG
+
+#define VLOG_EVERY_N(verbose_level, n)                                       \
+  for (int absl_logging_internal_verbose_level = (verbose_level),            \
+           absl_logging_internal_log_loop = 1;                               \
+       absl_logging_internal_log_loop; absl_logging_internal_log_loop = 0)   \
+    ABSL_LOG_INTERNAL_CONDITION_INFO(                                        \
+        STATEFUL, VLOG_IS_ON(absl_logging_internal_verbose_level))           \
+  (EveryN, n) ABSL_LOGGING_INTERNAL_LOG_INFO.InternalStream().WithVerbosity( \
+      absl_logging_internal_verbose_level)
+
+#define VLOG_FIRST_N(verbose_level, n)                                       \
+  for (int absl_logging_internal_verbose_level = (verbose_level),            \
+           absl_logging_internal_log_loop = 1;                               \
+       absl_logging_internal_log_loop; absl_logging_internal_log_loop = 0)   \
+    ABSL_LOG_INTERNAL_CONDITION_INFO(                                        \
+        STATEFUL, VLOG_IS_ON(absl_logging_internal_verbose_level))           \
+  (FirstN, n) ABSL_LOGGING_INTERNAL_LOG_INFO.InternalStream().WithVerbosity( \
+      absl_logging_internal_verbose_level)
+
+#define VLOG_EVERY_POW_2(verbose_level)                                      \
+  for (int absl_logging_internal_verbose_level = (verbose_level),            \
+           absl_logging_internal_log_loop = 1;                               \
+       absl_logging_internal_log_loop; absl_logging_internal_log_loop = 0)   \
+    ABSL_LOG_INTERNAL_CONDITION_INFO(                                        \
+        STATEFUL, VLOG_IS_ON(absl_logging_internal_verbose_level))           \
+  (EveryPow2) ABSL_LOGGING_INTERNAL_LOG_INFO.InternalStream().WithVerbosity( \
+      absl_logging_internal_verbose_level)
+
+#define VLOG_EVERY_N_SEC(verbose_level, n_seconds)                         \
+  for (int absl_logging_internal_verbose_level = (verbose_level),          \
+           absl_logging_internal_log_loop = 1;                             \
+       absl_logging_internal_log_loop; absl_logging_internal_log_loop = 0) \
+    ABSL_LOG_INTERNAL_CONDITION_INFO(                                      \
+        STATEFUL, VLOG_IS_ON(absl_logging_internal_verbose_level))         \
+  (EveryNSec, n_seconds) ABSL_LOGGING_INTERNAL_LOG_INFO.InternalStream()   \
+      .WithVerbosity(absl_logging_internal_verbose_level)
+
+// `LOG_IF_EVERY_N` and friends behave as the corresponding `LOG_EVERY_N`
+// but neither increment a counter nor log a message if condition is false (as
+// `LOG_IF`).
+// Example:
+//
+//   LOG_IF_EVERY_N(INFO, (size > 1024), 10) << "Got the " << COUNTER
+//                                           << "th big cookie";
+#define LOG_IF_EVERY_N(severity, condition, n)                           \
+  ABSL_LOG_INTERNAL_CONDITION_##severity(STATEFUL, condition)(EveryN, n) \
+      ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()
+
+#define LOG_IF_FIRST_N(severity, condition, n)                           \
+  ABSL_LOG_INTERNAL_CONDITION_##severity(STATEFUL, condition)(FirstN, n) \
+      ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()
+
+#define LOG_IF_EVERY_POW_2(severity, condition)                          \
+  ABSL_LOG_INTERNAL_CONDITION_##severity(STATEFUL, condition)(EveryPow2) \
+      ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()
+
+#define LOG_IF_EVERY_N_SEC(severity, condition, n_seconds)               \
+  ABSL_LOG_INTERNAL_CONDITION_##severity(STATEFUL, condition)(EveryNSec, \
+                                                              n_seconds) \
+      ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()
+
+#define PLOG_IF_EVERY_N(severity, condition, n)                          \
+  ABSL_LOG_INTERNAL_CONDITION_##severity(STATEFUL, condition)(EveryN, n) \
+      ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()              \
+          .WithPerror()
+
+#define PLOG_IF_FIRST_N(severity, condition, n)                          \
+  ABSL_LOG_INTERNAL_CONDITION_##severity(STATEFUL, condition)(FirstN, n) \
+      ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()              \
+          .WithPerror()
+
+#define PLOG_IF_EVERY_POW_2(severity, condition)                         \
+  ABSL_LOG_INTERNAL_CONDITION_##severity(STATEFUL, condition)(EveryPow2) \
+      ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()              \
+          .WithPerror()
+
+#define PLOG_IF_EVERY_N_SEC(severity, condition, n_seconds)              \
+  ABSL_LOG_INTERNAL_CONDITION_##severity(STATEFUL, condition)(EveryNSec, \
+                                                              n_seconds) \
+      ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()              \
+          .WithPerror()
+
+#ifndef NDEBUG
+#define DLOG_IF_EVERY_N(severity, condition, n)                          \
+  ABSL_LOG_INTERNAL_CONDITION_##severity(STATEFUL, condition)(EveryN, n) \
+      ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()
+
+#define DLOG_IF_FIRST_N(severity, condition, n)                          \
+  ABSL_LOG_INTERNAL_CONDITION_##severity(STATEFUL, condition)(FirstN, n) \
+      ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()
+
+#define DLOG_IF_EVERY_POW_2(severity, condition)                         \
+  ABSL_LOG_INTERNAL_CONDITION_##severity(STATEFUL, condition)(EveryPow2) \
+      ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()
+
+#define DLOG_IF_EVERY_N_SEC(severity, condition, n_seconds)              \
+  ABSL_LOG_INTERNAL_CONDITION_##severity(STATEFUL, condition)(EveryNSec, \
+                                                              n_seconds) \
+      ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()
+
+#else  // def NDEBUG
+#define DLOG_IF_EVERY_N(severity, condition, n)                           \
+  ABSL_LOG_INTERNAL_CONDITION_##severity(STATEFUL, false && (condition))( \
+      EveryN, n) ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()
+
+#define DLOG_IF_FIRST_N(severity, condition, n)                           \
+  ABSL_LOG_INTERNAL_CONDITION_##severity(STATEFUL, false && (condition))( \
+      FirstN, n) ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()
+
+#define DLOG_IF_EVERY_POW_2(severity, condition)                          \
+  ABSL_LOG_INTERNAL_CONDITION_##severity(STATEFUL, false && (condition))( \
+      EveryPow2) ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()
+
+#define DLOG_IF_EVERY_N_SEC(severity, condition, n_seconds)               \
+  ABSL_LOG_INTERNAL_CONDITION_##severity(STATEFUL, false && (condition))( \
+      EveryNSec, n_seconds)                                               \
+      ABSL_LOGGING_INTERNAL_LOG_##severity.InternalStream()
+#endif  // def NDEBUG
+
+#endif  // ABSL_LOG_LOG_H_
diff --git a/absl/log/log_benchmark.cc b/absl/log/log_benchmark.cc
new file mode 100644
index 0000000..45d9a5d
--- /dev/null
+++ b/absl/log/log_benchmark.cc
@@ -0,0 +1,97 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/base/attributes.h"
+#include "absl/base/log_severity.h"
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/globals.h"
+#include "absl/log/log.h"
+#include "absl/log/log_entry.h"
+#include "absl/log/log_sink.h"
+#include "absl/log/log_sink_registry.h"
+#include "benchmark/benchmark.h"
+
+namespace {
+
+class NullLogSink : public absl::LogSink {
+ public:
+  NullLogSink() { absl::AddLogSink(this); }
+
+  ~NullLogSink() override { absl::RemoveLogSink(this); }
+
+  void Send(const absl::LogEntry&) override {}
+};
+
+constexpr int x = -1;
+
+void BM_SuccessfulBinaryCheck(benchmark::State& state) {
+  int n = 0;
+  while (state.KeepRunningBatch(8)) {
+    CHECK_GE(n, x);
+    CHECK_GE(n, x);
+    CHECK_GE(n, x);
+    CHECK_GE(n, x);
+    CHECK_GE(n, x);
+    CHECK_GE(n, x);
+    CHECK_GE(n, x);
+    CHECK_GE(n, x);
+    ++n;
+  }
+  benchmark::DoNotOptimize(n);
+}
+BENCHMARK(BM_SuccessfulBinaryCheck);
+
+static void BM_SuccessfulUnaryCheck(benchmark::State& state) {
+  int n = 0;
+  while (state.KeepRunningBatch(8)) {
+    CHECK(n >= x);
+    CHECK(n >= x);
+    CHECK(n >= x);
+    CHECK(n >= x);
+    CHECK(n >= x);
+    CHECK(n >= x);
+    CHECK(n >= x);
+    CHECK(n >= x);
+    ++n;
+  }
+  benchmark::DoNotOptimize(n);
+}
+BENCHMARK(BM_SuccessfulUnaryCheck);
+
+static void BM_DisabledLogOverhead(benchmark::State& state) {
+  absl::ScopedStderrThreshold disable_stderr_logging(
+      absl::LogSeverityAtLeast::kInfinity);
+  absl::log_internal::ScopedMinLogLevel scoped_min_log_level(
+      absl::LogSeverityAtLeast::kInfinity);
+  for (auto _ : state) {
+    LOG(INFO);
+  }
+}
+BENCHMARK(BM_DisabledLogOverhead);
+
+static void BM_EnabledLogOverhead(benchmark::State& state) {
+  absl::ScopedStderrThreshold stderr_logging(
+      absl::LogSeverityAtLeast::kInfinity);
+  absl::log_internal::ScopedMinLogLevel scoped_min_log_level(
+      absl::LogSeverityAtLeast::kInfo);
+  ABSL_ATTRIBUTE_UNUSED NullLogSink null_sink;
+  for (auto _ : state) {
+    LOG(INFO);
+  }
+}
+BENCHMARK(BM_EnabledLogOverhead);
+
+}  // namespace
+
diff --git a/absl/log/log_entry.cc b/absl/log/log_entry.cc
new file mode 100644
index 0000000..19c3b3f
--- /dev/null
+++ b/absl/log/log_entry.cc
@@ -0,0 +1,29 @@
+//
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/log_entry.h"
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
+constexpr int LogEntry::kNoVerbosityLevel;
+constexpr int LogEntry::kNoVerboseLevel;
+#endif
+
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/log/log_entry.h b/absl/log/log_entry.h
new file mode 100644
index 0000000..d1f500c
--- /dev/null
+++ b/absl/log/log_entry.h
@@ -0,0 +1,163 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/log_entry.h
+// -----------------------------------------------------------------------------
+//
+// This header declares `class absl::LogEntry`, which represents a log record as
+// passed to `LogSink::Send`. Data returned by pointer or by reference or by
+// `absl::string_view` must be copied if they are needed after the lifetime of
+// the `absl::LogEntry`.
+
+#ifndef ABSL_LOG_LOG_ENTRY_H_
+#define ABSL_LOG_LOG_ENTRY_H_
+
+#include <cstddef>
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/base/log_severity.h"
+#include "absl/log/internal/config.h"
+#include "absl/strings/string_view.h"
+#include "absl/time/time.h"
+#include "absl/types/span.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+namespace log_internal {
+// Test only friend.
+class LogEntryTestPeer;
+class LogMessage;
+}  // namespace log_internal
+
+// LogEntry
+//
+// Represents a single entry in a log, i.e., one log message.
+//
+// LogEntry is copyable and thread-compatible.
+class LogEntry final {
+ public:
+  using tid_t = log_internal::Tid;
+
+  // For non-verbose log entries, `verbosity()` returns `kNoVerbosityLevel`.
+  static constexpr int kNoVerbosityLevel = -1;
+  static constexpr int kNoVerboseLevel = -1;  // TO BE removed
+
+  LogEntry(const LogEntry&) = default;
+  LogEntry& operator=(const LogEntry&) = default;
+
+  // Source file and line where the log message occurred.
+  // Take special care not to dereference the pointers returned by
+  // source_filename() and source_basename() after the lifetime of the
+  // `LogEntry`. This will usually work, because these are usually backed by a
+  // statically allocated char array obtained from the `__FILE__` macro, but
+  // it is nevertheless incorrect and will be broken by statements like
+  // `LOG(INFO).AtLocation(...)` (see above).  If you need the data later, you
+  // must copy it.
+  absl::string_view source_filename() const { return full_filename_; }
+  absl::string_view source_basename() const { return base_filename_; }
+  int source_line() const { return line_; }
+
+  // LogEntry::prefix()
+  //
+  // True unless cleared by LOG(...).NoPrefix(), which indicates suppression of
+  // the line prefix containing metadata like file, line, timestamp, etc.
+  bool prefix() const { return prefix_; }
+
+  // LogEntry::log_severity()
+  //
+  // Returns this LogEntry's severity.
+  absl::LogSeverity log_severity() const { return severity_; }
+
+  // LogEntry::verbosity()
+  //
+  // Returns this LogEntry's verbosity, or kNoVerbosityLevel for a non-verbose
+  // LogEntry.
+  int verbosity() const { return verbose_level_; }
+
+  // LogEntry::timestamp()
+  //
+  // Returns the time at which this LogEntry was written.
+  absl::Time timestamp() const { return timestamp_; }
+
+  // LogEntry::tid()
+  //
+  // Returns the id of the thread that wrote this LogEntry.
+  tid_t tid() const { return tid_; }
+
+  // Text-formatted version of the log message.  An underlying buffer holds:
+  //
+  // * A prefix formed by formatting metadata (timestamp, filename, line number,
+  //   etc.)
+  // * The streamed data
+  // * A newline
+  // * A nul terminator
+  //
+  // These methods give access to the most commonly-used substrings of the
+  // buffer's contents.  Other combinations can be obtained with substring
+  // arithmetic.
+  absl::string_view text_message_with_prefix_and_newline() const {
+    return absl::string_view(
+        text_message_with_prefix_and_newline_and_nul_.data(),
+        text_message_with_prefix_and_newline_and_nul_.size() - 1);
+  }
+  absl::string_view text_message_with_prefix() const {
+    return absl::string_view(
+        text_message_with_prefix_and_newline_and_nul_.data(),
+        text_message_with_prefix_and_newline_and_nul_.size() - 2);
+  }
+  absl::string_view text_message_with_newline() const {
+    return absl::string_view(
+        text_message_with_prefix_and_newline_and_nul_.data() + prefix_len_,
+        text_message_with_prefix_and_newline_and_nul_.size() - prefix_len_ - 1);
+  }
+  absl::string_view text_message() const {
+    return absl::string_view(
+        text_message_with_prefix_and_newline_and_nul_.data() + prefix_len_,
+        text_message_with_prefix_and_newline_and_nul_.size() - prefix_len_ - 2);
+  }
+  const char* text_message_with_prefix_and_newline_c_str() const {
+    return text_message_with_prefix_and_newline_and_nul_.data();
+  }
+
+  // LogEntry::stacktrace()
+  //
+  // Optional stacktrace, e.g., for `FATAL` logs.
+  absl::string_view stacktrace() const { return stacktrace_; }
+
+ private:
+  LogEntry() = default;
+
+  absl::string_view full_filename_;
+  absl::string_view base_filename_;
+  int line_;
+  bool prefix_;
+  absl::LogSeverity severity_;
+  int verbose_level_;  // >=0 for `VLOG`, etc.; otherwise `kNoVerbosityLevel`.
+  absl::Time timestamp_;
+  tid_t tid_;
+  absl::Span<const char> text_message_with_prefix_and_newline_and_nul_;
+  size_t prefix_len_;
+  std::string stacktrace_;
+
+  friend class log_internal::LogEntryTestPeer;
+  friend class log_internal::LogMessage;
+};
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_LOG_LOG_ENTRY_H_
diff --git a/absl/log/log_entry_test.cc b/absl/log/log_entry_test.cc
new file mode 100644
index 0000000..b19794e
--- /dev/null
+++ b/absl/log/log_entry_test.cc
@@ -0,0 +1,432 @@
+//
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/log_entry.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <cstring>
+#include <limits>
+#include <string>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/log_severity.h"
+#include "absl/log/internal/log_format.h"
+#include "absl/log/internal/test_helpers.h"
+#include "absl/strings/numbers.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/string_view.h"
+#include "absl/time/civil_time.h"
+#include "absl/time/time.h"
+#include "absl/types/span.h"
+
+namespace {
+
+using ::absl::log_internal::LogEntryTestPeer;
+using ::testing::Eq;
+using ::testing::IsTrue;
+using ::testing::StartsWith;
+using ::testing::StrEq;
+
+auto* test_env ABSL_ATTRIBUTE_UNUSED = ::testing::AddGlobalTestEnvironment(
+    new absl::log_internal::LogTestEnvironment);
+
+// Copies into `dst` as many bytes of `src` as will fit, then truncates the
+// copied bytes from the front of `dst` and returns the number of bytes written.
+size_t AppendTruncated(absl::string_view src, absl::Span<char>& dst) {
+  if (src.size() > dst.size()) src = src.substr(0, dst.size());
+  memcpy(dst.data(), src.data(), src.size());
+  dst.remove_prefix(src.size());
+  return src.size();
+}
+
+}  // namespace
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+class LogEntryTestPeer {
+ public:
+  LogEntryTestPeer(absl::string_view base_filename, int line, bool prefix,
+                   absl::LogSeverity severity, absl::string_view timestamp,
+                   absl::LogEntry::tid_t tid, absl::string_view text_message)
+      : buf_(15000, '\0') {
+    entry_.base_filename_ = base_filename;
+    entry_.line_ = line;
+    entry_.prefix_ = prefix;
+    entry_.severity_ = severity;
+    std::string time_err;
+    EXPECT_THAT(
+        absl::ParseTime("%Y-%m-%d%ET%H:%M:%E*S", timestamp,
+                        absl::LocalTimeZone(), &entry_.timestamp_, &time_err),
+        IsTrue())
+        << "Failed to parse time " << timestamp << ": " << time_err;
+    entry_.tid_ = tid;
+    std::pair<absl::string_view, std::string> timestamp_bits =
+        absl::StrSplit(timestamp, absl::ByChar('.'));
+    EXPECT_THAT(absl::ParseCivilTime(timestamp_bits.first, &ci_.cs), IsTrue())
+        << "Failed to parse time " << timestamp_bits.first;
+    timestamp_bits.second.resize(9, '0');
+    int64_t nanos = 0;
+    EXPECT_THAT(absl::SimpleAtoi(timestamp_bits.second, &nanos), IsTrue())
+        << "Failed to parse time " << timestamp_bits.first;
+    ci_.subsecond = absl::Nanoseconds(nanos);
+
+    absl::Span<char> view = absl::MakeSpan(buf_);
+    view.remove_suffix(2);
+    entry_.prefix_len_ =
+        entry_.prefix_
+            ? log_internal::FormatLogPrefix(
+                  entry_.log_severity(), entry_.timestamp(), entry_.tid(),
+                  entry_.source_basename(), entry_.source_line(), view)
+            : 0;
+
+    EXPECT_THAT(entry_.prefix_len_, Eq(view.data() - buf_.data()));
+    AppendTruncated(text_message, view);
+    view = absl::Span<char>(view.data(), view.size() + 2);
+    view[0] = '\n';
+    view[1] = '\0';
+    view.remove_prefix(2);
+    buf_.resize(view.data() - buf_.data());
+    entry_.text_message_with_prefix_and_newline_and_nul_ = absl::MakeSpan(buf_);
+  }
+  LogEntryTestPeer(const LogEntryTestPeer&) = delete;
+  LogEntryTestPeer& operator=(const LogEntryTestPeer&) = delete;
+
+  std::string FormatLogMessage() const {
+    return log_internal::FormatLogMessage(
+        entry_.log_severity(), ci_.cs, ci_.subsecond, entry_.tid(),
+        entry_.source_basename(), entry_.source_line(), entry_.text_message());
+  }
+  std::string FormatPrefixIntoSizedBuffer(size_t sz) {
+    std::string str(sz, '\0');
+    absl::Span<char> buf(&str[0], str.size());
+    const size_t prefix_size = log_internal::FormatLogPrefix(
+        entry_.log_severity(), entry_.timestamp(), entry_.tid(),
+        entry_.source_basename(), entry_.source_line(), buf);
+    EXPECT_THAT(prefix_size, Eq(buf.data() - str.data()));
+    str.resize(prefix_size);
+    return str;
+  }
+  const absl::LogEntry& entry() const { return entry_; }
+
+ private:
+  absl::LogEntry entry_;
+  absl::TimeZone::CivilInfo ci_;
+  std::vector<char> buf_;
+};
+
+}  // namespace log_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+namespace {
+constexpr bool kUsePrefix = true, kNoPrefix = false;
+
+TEST(LogEntryTest, Baseline) {
+  LogEntryTestPeer entry("foo.cc", 1234, kUsePrefix, absl::LogSeverity::kInfo,
+                         "2020-01-02T03:04:05.6789", 451, "hello world");
+  EXPECT_THAT(entry.FormatLogMessage(),
+              Eq("I0102 03:04:05.678900     451 foo.cc:1234] hello world"));
+  EXPECT_THAT(entry.FormatPrefixIntoSizedBuffer(1000),
+              Eq("I0102 03:04:05.678900     451 foo.cc:1234] "));
+  for (size_t sz = strlen("I0102 03:04:05.678900     451 foo.cc:1234] ") + 20;
+       sz != std::numeric_limits<size_t>::max(); sz--)
+    EXPECT_THAT("I0102 03:04:05.678900     451 foo.cc:1234] ",
+                StartsWith(entry.FormatPrefixIntoSizedBuffer(sz)));
+
+  EXPECT_THAT(entry.entry().text_message_with_prefix_and_newline(),
+              Eq("I0102 03:04:05.678900     451 foo.cc:1234] hello world\n"));
+  EXPECT_THAT(
+      entry.entry().text_message_with_prefix_and_newline_c_str(),
+      StrEq("I0102 03:04:05.678900     451 foo.cc:1234] hello world\n"));
+  EXPECT_THAT(entry.entry().text_message_with_prefix(),
+              Eq("I0102 03:04:05.678900     451 foo.cc:1234] hello world"));
+  EXPECT_THAT(entry.entry().text_message(), Eq("hello world"));
+}
+
+TEST(LogEntryTest, NoPrefix) {
+  LogEntryTestPeer entry("foo.cc", 1234, kNoPrefix, absl::LogSeverity::kInfo,
+                         "2020-01-02T03:04:05.6789", 451, "hello world");
+  EXPECT_THAT(entry.FormatLogMessage(),
+              Eq("I0102 03:04:05.678900     451 foo.cc:1234] hello world"));
+  // These methods are not responsible for honoring `prefix()`.
+  EXPECT_THAT(entry.FormatPrefixIntoSizedBuffer(1000),
+              Eq("I0102 03:04:05.678900     451 foo.cc:1234] "));
+  for (size_t sz = strlen("I0102 03:04:05.678900     451 foo.cc:1234] ") + 20;
+       sz != std::numeric_limits<size_t>::max(); sz--)
+    EXPECT_THAT("I0102 03:04:05.678900     451 foo.cc:1234] ",
+                StartsWith(entry.FormatPrefixIntoSizedBuffer(sz)));
+
+  EXPECT_THAT(entry.entry().text_message_with_prefix_and_newline(),
+              Eq("hello world\n"));
+  EXPECT_THAT(entry.entry().text_message_with_prefix_and_newline_c_str(),
+              StrEq("hello world\n"));
+  EXPECT_THAT(entry.entry().text_message_with_prefix(), Eq("hello world"));
+  EXPECT_THAT(entry.entry().text_message(), Eq("hello world"));
+}
+
+TEST(LogEntryTest, EmptyFields) {
+  LogEntryTestPeer entry("", 0, kUsePrefix, absl::LogSeverity::kInfo,
+                         "2020-01-02T03:04:05", 0, "");
+  const std::string format_message = entry.FormatLogMessage();
+  EXPECT_THAT(format_message, Eq("I0102 03:04:05.000000       0 :0] "));
+  EXPECT_THAT(entry.FormatPrefixIntoSizedBuffer(1000), Eq(format_message));
+  for (size_t sz = format_message.size() + 20;
+       sz != std::numeric_limits<size_t>::max(); sz--)
+    EXPECT_THAT(format_message,
+                StartsWith(entry.FormatPrefixIntoSizedBuffer(sz)));
+
+  EXPECT_THAT(entry.entry().text_message_with_prefix_and_newline(),
+              Eq("I0102 03:04:05.000000       0 :0] \n"));
+  EXPECT_THAT(entry.entry().text_message_with_prefix_and_newline_c_str(),
+              StrEq("I0102 03:04:05.000000       0 :0] \n"));
+  EXPECT_THAT(entry.entry().text_message_with_prefix(),
+              Eq("I0102 03:04:05.000000       0 :0] "));
+  EXPECT_THAT(entry.entry().text_message(), Eq(""));
+}
+
+TEST(LogEntryTest, NegativeFields) {
+  if (std::is_signed<absl::LogEntry::tid_t>::value) {
+    LogEntryTestPeer entry("foo.cc", -1234, kUsePrefix,
+                           absl::LogSeverity::kInfo, "2020-01-02T03:04:05.6789",
+                           -451, "hello world");
+    EXPECT_THAT(entry.FormatLogMessage(),
+                Eq("I0102 03:04:05.678900    -451 foo.cc:-1234] hello world"));
+    EXPECT_THAT(entry.FormatPrefixIntoSizedBuffer(1000),
+                Eq("I0102 03:04:05.678900    -451 foo.cc:-1234] "));
+    for (size_t sz =
+             strlen("I0102 03:04:05.678900    -451 foo.cc:-1234] ") + 20;
+         sz != std::numeric_limits<size_t>::max(); sz--)
+      EXPECT_THAT("I0102 03:04:05.678900    -451 foo.cc:-1234] ",
+                  StartsWith(entry.FormatPrefixIntoSizedBuffer(sz)));
+
+    EXPECT_THAT(
+        entry.entry().text_message_with_prefix_and_newline(),
+        Eq("I0102 03:04:05.678900    -451 foo.cc:-1234] hello world\n"));
+    EXPECT_THAT(
+        entry.entry().text_message_with_prefix_and_newline_c_str(),
+        StrEq("I0102 03:04:05.678900    -451 foo.cc:-1234] hello world\n"));
+    EXPECT_THAT(entry.entry().text_message_with_prefix(),
+                Eq("I0102 03:04:05.678900    -451 foo.cc:-1234] hello world"));
+    EXPECT_THAT(entry.entry().text_message(), Eq("hello world"));
+  } else {
+    LogEntryTestPeer entry("foo.cc", -1234, kUsePrefix,
+                           absl::LogSeverity::kInfo, "2020-01-02T03:04:05.6789",
+                           451, "hello world");
+    EXPECT_THAT(entry.FormatLogMessage(),
+                Eq("I0102 03:04:05.678900     451 foo.cc:-1234] hello world"));
+    EXPECT_THAT(entry.FormatPrefixIntoSizedBuffer(1000),
+                Eq("I0102 03:04:05.678900     451 foo.cc:-1234] "));
+    for (size_t sz =
+             strlen("I0102 03:04:05.678900     451 foo.cc:-1234] ") + 20;
+         sz != std::numeric_limits<size_t>::max(); sz--)
+      EXPECT_THAT("I0102 03:04:05.678900     451 foo.cc:-1234] ",
+                  StartsWith(entry.FormatPrefixIntoSizedBuffer(sz)));
+
+    EXPECT_THAT(
+        entry.entry().text_message_with_prefix_and_newline(),
+        Eq("I0102 03:04:05.678900     451 foo.cc:-1234] hello world\n"));
+    EXPECT_THAT(
+        entry.entry().text_message_with_prefix_and_newline_c_str(),
+        StrEq("I0102 03:04:05.678900     451 foo.cc:-1234] hello world\n"));
+    EXPECT_THAT(entry.entry().text_message_with_prefix(),
+                Eq("I0102 03:04:05.678900     451 foo.cc:-1234] hello world"));
+    EXPECT_THAT(entry.entry().text_message(), Eq("hello world"));
+  }
+}
+
+TEST(LogEntryTest, LongFields) {
+  LogEntryTestPeer entry(
+      "I am the very model of a modern Major-General / "
+      "I've information vegetable, animal, and mineral.",
+      2147483647, kUsePrefix, absl::LogSeverity::kInfo,
+      "2020-01-02T03:04:05.678967896789", 2147483647,
+      "I know the kings of England, and I quote the fights historical / "
+      "From Marathon to Waterloo, in order categorical.");
+  EXPECT_THAT(entry.FormatLogMessage(),
+              Eq("I0102 03:04:05.678967 2147483647 I am the very model of a "
+                 "modern Major-General / I've information vegetable, animal, "
+                 "and mineral.:2147483647] I know the kings of England, and I "
+                 "quote the fights historical / From Marathon to Waterloo, in "
+                 "order categorical."));
+  EXPECT_THAT(entry.FormatPrefixIntoSizedBuffer(1000),
+              Eq("I0102 03:04:05.678967 2147483647 I am the very model of a "
+                 "modern Major-General / I've information vegetable, animal, "
+                 "and mineral.:2147483647] "));
+  for (size_t sz =
+           strlen("I0102 03:04:05.678967 2147483647 I am the very model of a "
+                  "modern Major-General / I've information vegetable, animal, "
+                  "and mineral.:2147483647] ") +
+           20;
+       sz != std::numeric_limits<size_t>::max(); sz--)
+    EXPECT_THAT(
+        "I0102 03:04:05.678967 2147483647 I am the very model of a "
+        "modern Major-General / I've information vegetable, animal, "
+        "and mineral.:2147483647] ",
+        StartsWith(entry.FormatPrefixIntoSizedBuffer(sz)));
+
+  EXPECT_THAT(entry.entry().text_message_with_prefix_and_newline(),
+              Eq("I0102 03:04:05.678967 2147483647 I am the very model of a "
+                 "modern Major-General / I've information vegetable, animal, "
+                 "and mineral.:2147483647] I know the kings of England, and I "
+                 "quote the fights historical / From Marathon to Waterloo, in "
+                 "order categorical.\n"));
+  EXPECT_THAT(
+      entry.entry().text_message_with_prefix_and_newline_c_str(),
+      StrEq("I0102 03:04:05.678967 2147483647 I am the very model of a "
+            "modern Major-General / I've information vegetable, animal, "
+            "and mineral.:2147483647] I know the kings of England, and I "
+            "quote the fights historical / From Marathon to Waterloo, in "
+            "order categorical.\n"));
+  EXPECT_THAT(entry.entry().text_message_with_prefix(),
+              Eq("I0102 03:04:05.678967 2147483647 I am the very model of a "
+                 "modern Major-General / I've information vegetable, animal, "
+                 "and mineral.:2147483647] I know the kings of England, and I "
+                 "quote the fights historical / From Marathon to Waterloo, in "
+                 "order categorical."));
+  EXPECT_THAT(
+      entry.entry().text_message(),
+      Eq("I know the kings of England, and I quote the fights historical / "
+         "From Marathon to Waterloo, in order categorical."));
+}
+
+TEST(LogEntryTest, LongNegativeFields) {
+  if (std::is_signed<absl::LogEntry::tid_t>::value) {
+    LogEntryTestPeer entry(
+        "I am the very model of a modern Major-General / "
+        "I've information vegetable, animal, and mineral.",
+        -2147483647, kUsePrefix, absl::LogSeverity::kInfo,
+        "2020-01-02T03:04:05.678967896789", -2147483647,
+        "I know the kings of England, and I quote the fights historical / "
+        "From Marathon to Waterloo, in order categorical.");
+    EXPECT_THAT(
+        entry.FormatLogMessage(),
+        Eq("I0102 03:04:05.678967 -2147483647 I am the very model of a "
+           "modern Major-General / I've information vegetable, animal, "
+           "and mineral.:-2147483647] I know the kings of England, and I "
+           "quote the fights historical / From Marathon to Waterloo, in "
+           "order categorical."));
+    EXPECT_THAT(entry.FormatPrefixIntoSizedBuffer(1000),
+                Eq("I0102 03:04:05.678967 -2147483647 I am the very model of a "
+                   "modern Major-General / I've information vegetable, animal, "
+                   "and mineral.:-2147483647] "));
+    for (size_t sz =
+             strlen(
+                 "I0102 03:04:05.678967 -2147483647 I am the very model of a "
+                 "modern Major-General / I've information vegetable, animal, "
+                 "and mineral.:-2147483647] ") +
+             20;
+         sz != std::numeric_limits<size_t>::max(); sz--)
+      EXPECT_THAT(
+          "I0102 03:04:05.678967 -2147483647 I am the very model of a "
+          "modern Major-General / I've information vegetable, animal, "
+          "and mineral.:-2147483647] ",
+          StartsWith(entry.FormatPrefixIntoSizedBuffer(sz)));
+
+    EXPECT_THAT(
+        entry.entry().text_message_with_prefix_and_newline(),
+        Eq("I0102 03:04:05.678967 -2147483647 I am the very model of a "
+           "modern Major-General / I've information vegetable, animal, "
+           "and mineral.:-2147483647] I know the kings of England, and I "
+           "quote the fights historical / From Marathon to Waterloo, in "
+           "order categorical.\n"));
+    EXPECT_THAT(
+        entry.entry().text_message_with_prefix_and_newline_c_str(),
+        StrEq("I0102 03:04:05.678967 -2147483647 I am the very model of a "
+              "modern Major-General / I've information vegetable, animal, "
+              "and mineral.:-2147483647] I know the kings of England, and I "
+              "quote the fights historical / From Marathon to Waterloo, in "
+              "order categorical.\n"));
+    EXPECT_THAT(
+        entry.entry().text_message_with_prefix(),
+        Eq("I0102 03:04:05.678967 -2147483647 I am the very model of a "
+           "modern Major-General / I've information vegetable, animal, "
+           "and mineral.:-2147483647] I know the kings of England, and I "
+           "quote the fights historical / From Marathon to Waterloo, in "
+           "order categorical."));
+    EXPECT_THAT(
+        entry.entry().text_message(),
+        Eq("I know the kings of England, and I quote the fights historical / "
+           "From Marathon to Waterloo, in order categorical."));
+  } else {
+    LogEntryTestPeer entry(
+        "I am the very model of a modern Major-General / "
+        "I've information vegetable, animal, and mineral.",
+        -2147483647, kUsePrefix, absl::LogSeverity::kInfo,
+        "2020-01-02T03:04:05.678967896789", 2147483647,
+        "I know the kings of England, and I quote the fights historical / "
+        "From Marathon to Waterloo, in order categorical.");
+    EXPECT_THAT(
+        entry.FormatLogMessage(),
+        Eq("I0102 03:04:05.678967 2147483647 I am the very model of a "
+           "modern Major-General / I've information vegetable, animal, "
+           "and mineral.:-2147483647] I know the kings of England, and I "
+           "quote the fights historical / From Marathon to Waterloo, in "
+           "order categorical."));
+    EXPECT_THAT(entry.FormatPrefixIntoSizedBuffer(1000),
+                Eq("I0102 03:04:05.678967 2147483647 I am the very model of a "
+                   "modern Major-General / I've information vegetable, animal, "
+                   "and mineral.:-2147483647] "));
+    for (size_t sz =
+             strlen(
+                 "I0102 03:04:05.678967 2147483647 I am the very model of a "
+                 "modern Major-General / I've information vegetable, animal, "
+                 "and mineral.:-2147483647] ") +
+             20;
+         sz != std::numeric_limits<size_t>::max(); sz--)
+      EXPECT_THAT(
+          "I0102 03:04:05.678967 2147483647 I am the very model of a "
+          "modern Major-General / I've information vegetable, animal, "
+          "and mineral.:-2147483647] ",
+          StartsWith(entry.FormatPrefixIntoSizedBuffer(sz)));
+
+    EXPECT_THAT(
+        entry.entry().text_message_with_prefix_and_newline(),
+        Eq("I0102 03:04:05.678967 2147483647 I am the very model of a "
+           "modern Major-General / I've information vegetable, animal, "
+           "and mineral.:-2147483647] I know the kings of England, and I "
+           "quote the fights historical / From Marathon to Waterloo, in "
+           "order categorical.\n"));
+    EXPECT_THAT(
+        entry.entry().text_message_with_prefix_and_newline_c_str(),
+        StrEq("I0102 03:04:05.678967 2147483647 I am the very model of a "
+              "modern Major-General / I've information vegetable, animal, "
+              "and mineral.:-2147483647] I know the kings of England, and I "
+              "quote the fights historical / From Marathon to Waterloo, in "
+              "order categorical.\n"));
+    EXPECT_THAT(
+        entry.entry().text_message_with_prefix(),
+        Eq("I0102 03:04:05.678967 2147483647 I am the very model of a "
+           "modern Major-General / I've information vegetable, animal, "
+           "and mineral.:-2147483647] I know the kings of England, and I "
+           "quote the fights historical / From Marathon to Waterloo, in "
+           "order categorical."));
+    EXPECT_THAT(
+        entry.entry().text_message(),
+        Eq("I know the kings of England, and I quote the fights historical / "
+           "From Marathon to Waterloo, in order categorical."));
+  }
+}
+
+}  // namespace
diff --git a/absl/log/log_format_test.cc b/absl/log/log_format_test.cc
new file mode 100644
index 0000000..3fdb358
--- /dev/null
+++ b/absl/log/log_format_test.cc
@@ -0,0 +1,1525 @@
+//
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <math.h>
+
+#include <iomanip>
+#include <limits>
+#include <sstream>
+#include <string>
+#include <type_traits>
+
+#ifdef __ANDROID__
+#include <android/api-level.h>
+#endif
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/log/internal/config.h"
+#include "absl/log/internal/test_matchers.h"
+#include "absl/log/log.h"
+#include "absl/log/scoped_mock_log.h"
+#include "absl/strings/match.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+
+namespace {
+using ::absl::log_internal::MatchesOstream;
+using ::absl::log_internal::TextMessage;
+using ::absl::log_internal::TextPrefix;
+
+using ::testing::AllOf;
+using ::testing::AnyOf;
+using ::testing::Eq;
+using ::testing::IsEmpty;
+using ::testing::Truly;
+using ::testing::Types;
+
+using ::testing::Each;
+using ::testing::Ge;
+using ::testing::Le;
+using ::testing::SizeIs;
+
+// Some aspects of formatting streamed data (e.g. pointer handling) are
+// implementation-defined.  Others are buggy in supported implementations.
+// These tests validate that the formatting matches that performed by a
+// `std::ostream` and also that the result is one of a list of expected formats.
+
+std::ostringstream ComparisonStream() {
+  std::ostringstream str;
+  str.setf(std::ios_base::showbase | std::ios_base::boolalpha |
+           std::ios_base::internal);
+  return str;
+}
+
+TEST(LogFormatTest, NoMessage) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const int log_line = __LINE__ + 1;
+  auto do_log = [] { LOG(INFO); };
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(MatchesOstream(ComparisonStream())),
+          TextPrefix(Truly([=](absl::string_view msg) {
+            return absl::EndsWith(
+                msg, absl::StrCat(" log_format_test.cc:", log_line, "] "));
+          })),
+          TextMessage(IsEmpty()), ENCODED_MESSAGE(EqualsProto(R"pb()pb")))));
+
+  test_sink.StartCapturingLogs();
+  do_log();
+}
+
+template <typename T>
+class CharLogFormatTest : public testing::Test {};
+using CharTypes = Types<char, signed char, unsigned char>;
+TYPED_TEST_SUITE(CharLogFormatTest, CharTypes);
+
+TYPED_TEST(CharLogFormatTest, Printable) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const TypeParam value = 'x';
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(Eq("x")),
+                 ENCODED_MESSAGE(EqualsProto(R"pb(value { str: "x" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+TYPED_TEST(CharLogFormatTest, Unprintable) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const TypeParam value = 0xeeu;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value;
+
+  EXPECT_CALL(
+      test_sink, Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                            TextMessage(Eq("\xee")),
+                            ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                               str: "\xee"
+                                                             })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+template <typename T>
+class UnsignedIntLogFormatTest : public testing::Test {};
+using UnsignedIntTypes = Types<unsigned short, unsigned int,        // NOLINT
+                               unsigned long, unsigned long long>;  // NOLINT
+TYPED_TEST_SUITE(UnsignedIntLogFormatTest, UnsignedIntTypes);
+
+TYPED_TEST(UnsignedIntLogFormatTest, Positive) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const TypeParam value = 224;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(Eq("224")),
+                 ENCODED_MESSAGE(EqualsProto(R"pb(value { str: "224" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+TYPED_TEST(UnsignedIntLogFormatTest, BitfieldPositive) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const struct {
+    TypeParam bits : 6;
+  } value{42};
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value.bits;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(Eq("42")),
+                 ENCODED_MESSAGE(EqualsProto(R"pb(value { str: "42" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value.bits;
+}
+
+template <typename T>
+class SignedIntLogFormatTest : public testing::Test {};
+using SignedIntTypes =
+    Types<signed short, signed int, signed long, signed long long>;  // NOLINT
+TYPED_TEST_SUITE(SignedIntLogFormatTest, SignedIntTypes);
+
+TYPED_TEST(SignedIntLogFormatTest, Positive) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const TypeParam value = 224;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(Eq("224")),
+                 ENCODED_MESSAGE(EqualsProto(R"pb(value { str: "224" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+TYPED_TEST(SignedIntLogFormatTest, Negative) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const TypeParam value = -112;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value;
+
+  EXPECT_CALL(
+      test_sink, Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                            TextMessage(Eq("-112")),
+                            ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                               str: "-112"
+                                                             })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+TYPED_TEST(SignedIntLogFormatTest, BitfieldPositive) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const struct {
+    TypeParam bits : 6;
+  } value{21};
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value.bits;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(Eq("21")),
+                 ENCODED_MESSAGE(EqualsProto(R"pb(value { str: "21" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value.bits;
+}
+
+TYPED_TEST(SignedIntLogFormatTest, BitfieldNegative) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const struct {
+    TypeParam bits : 6;
+  } value{-21};
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value.bits;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(Eq("-21")),
+                 ENCODED_MESSAGE(EqualsProto(R"pb(value { str: "-21" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value.bits;
+}
+
+// Ignore these test cases on GCC due to "is too small to hold all values ..."
+// warning.
+#if !defined(__GNUC__) || defined(__clang__)
+// The implementation may choose a signed or unsigned integer type to represent
+// this enum, so it may be tested by either `UnsignedEnumLogFormatTest` or
+// `SignedEnumLogFormatTest`.
+enum MyUnsignedEnum {
+  MyUnsignedEnum_ZERO = 0,
+  MyUnsignedEnum_FORTY_TWO = 42,
+  MyUnsignedEnum_TWO_HUNDRED_TWENTY_FOUR = 224,
+};
+enum MyUnsignedIntEnum : unsigned int {
+  MyUnsignedIntEnum_ZERO = 0,
+  MyUnsignedIntEnum_FORTY_TWO = 42,
+  MyUnsignedIntEnum_TWO_HUNDRED_TWENTY_FOUR = 224,
+};
+
+template <typename T>
+class UnsignedEnumLogFormatTest : public testing::Test {};
+using UnsignedEnumTypes = std::conditional<
+    std::is_signed<std::underlying_type<MyUnsignedEnum>::type>::value,
+    Types<MyUnsignedIntEnum>, Types<MyUnsignedEnum, MyUnsignedIntEnum>>::type;
+TYPED_TEST_SUITE(UnsignedEnumLogFormatTest, UnsignedEnumTypes);
+
+TYPED_TEST(UnsignedEnumLogFormatTest, Positive) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const TypeParam value = static_cast<TypeParam>(224);
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(Eq("224")),
+                 ENCODED_MESSAGE(EqualsProto(R"pb(value { str: "224" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+TYPED_TEST(UnsignedEnumLogFormatTest, BitfieldPositive) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const struct {
+    TypeParam bits : 6;
+  } value{static_cast<TypeParam>(42)};
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value.bits;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(Eq("42")),
+                 ENCODED_MESSAGE(EqualsProto(R"pb(value { str: "42" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value.bits;
+}
+
+enum MySignedEnum {
+  MySignedEnum_NEGATIVE_ONE_HUNDRED_TWELVE = -112,
+  MySignedEnum_NEGATIVE_TWENTY_ONE = -21,
+  MySignedEnum_ZERO = 0,
+  MySignedEnum_TWENTY_ONE = 21,
+  MySignedEnum_TWO_HUNDRED_TWENTY_FOUR = 224,
+};
+enum MySignedIntEnum : signed int {
+  MySignedIntEnum_NEGATIVE_ONE_HUNDRED_TWELVE = -112,
+  MySignedIntEnum_NEGATIVE_TWENTY_ONE = -21,
+  MySignedIntEnum_ZERO = 0,
+  MySignedIntEnum_TWENTY_ONE = 21,
+  MySignedIntEnum_TWO_HUNDRED_TWENTY_FOUR = 224,
+};
+
+template <typename T>
+class SignedEnumLogFormatTest : public testing::Test {};
+using SignedEnumTypes = std::conditional<
+    std::is_signed<std::underlying_type<MyUnsignedEnum>::type>::value,
+    Types<MyUnsignedEnum, MySignedEnum, MySignedIntEnum>,
+    Types<MySignedEnum, MySignedIntEnum>>::type;
+TYPED_TEST_SUITE(SignedEnumLogFormatTest, SignedEnumTypes);
+
+TYPED_TEST(SignedEnumLogFormatTest, Positive) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const TypeParam value = static_cast<TypeParam>(224);
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(Eq("224")),
+                 ENCODED_MESSAGE(EqualsProto(R"pb(value { str: "224" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+TYPED_TEST(SignedEnumLogFormatTest, Negative) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const TypeParam value = static_cast<TypeParam>(-112);
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value;
+
+  EXPECT_CALL(
+      test_sink, Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                            TextMessage(Eq("-112")),
+                            ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                               str: "-112"
+                                                             })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+TYPED_TEST(SignedEnumLogFormatTest, BitfieldPositive) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const struct {
+    TypeParam bits : 6;
+  } value{static_cast<TypeParam>(21)};
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value.bits;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(Eq("21")),
+                 ENCODED_MESSAGE(EqualsProto(R"pb(value { str: "21" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value.bits;
+}
+
+TYPED_TEST(SignedEnumLogFormatTest, BitfieldNegative) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const struct {
+    TypeParam bits : 6;
+  } value{static_cast<TypeParam>(-21)};
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value.bits;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(Eq("-21")),
+                 ENCODED_MESSAGE(EqualsProto(R"pb(value { str: "-21" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value.bits;
+}
+#endif
+
+TEST(FloatLogFormatTest, Positive) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const float value = 6.02e23f;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value;
+
+  EXPECT_CALL(test_sink,
+              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                         TextMessage(Eq("6.02e+23")),
+                         ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                            str: "6.02e+23"
+                                                          })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+TEST(FloatLogFormatTest, Negative) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const float value = -6.02e23f;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value;
+
+  EXPECT_CALL(test_sink,
+              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                         TextMessage(Eq("-6.02e+23")),
+                         ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                            str: "-6.02e+23"
+                                                          })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+TEST(FloatLogFormatTest, NegativeExponent) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const float value = 6.02e-23f;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value;
+
+  EXPECT_CALL(test_sink,
+              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                         TextMessage(Eq("6.02e-23")),
+                         ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                            str: "6.02e-23"
+                                                          })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+TEST(DoubleLogFormatTest, Positive) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const double value = 6.02e23;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value;
+
+  EXPECT_CALL(test_sink,
+              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                         TextMessage(Eq("6.02e+23")),
+                         ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                            str: "6.02e+23"
+                                                          })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+TEST(DoubleLogFormatTest, Negative) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const double value = -6.02e23;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value;
+
+  EXPECT_CALL(test_sink,
+              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                         TextMessage(Eq("-6.02e+23")),
+                         ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                            str: "-6.02e+23"
+                                                          })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+TEST(DoubleLogFormatTest, NegativeExponent) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const double value = 6.02e-23;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value;
+
+  EXPECT_CALL(test_sink,
+              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                         TextMessage(Eq("6.02e-23")),
+                         ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                            str: "6.02e-23"
+                                                          })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+template <typename T>
+class FloatingPointLogFormatTest : public testing::Test {};
+using FloatingPointTypes = Types<float, double>;
+TYPED_TEST_SUITE(FloatingPointLogFormatTest, FloatingPointTypes);
+
+TYPED_TEST(FloatingPointLogFormatTest, Zero) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const TypeParam value = 0.0;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(Eq("0")),
+                 ENCODED_MESSAGE(EqualsProto(R"pb(value { str: "0" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+TYPED_TEST(FloatingPointLogFormatTest, Integer) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const TypeParam value = 1.0;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(Eq("1")),
+                 ENCODED_MESSAGE(EqualsProto(R"pb(value { str: "1" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+TYPED_TEST(FloatingPointLogFormatTest, Infinity) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const TypeParam value = std::numeric_limits<TypeParam>::infinity();
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(AnyOf(Eq("inf"), Eq("Inf"))),
+                 ENCODED_MESSAGE(EqualsProto(R"pb(value { str: "inf" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+TYPED_TEST(FloatingPointLogFormatTest, NegativeInfinity) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const TypeParam value = -std::numeric_limits<TypeParam>::infinity();
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value;
+
+  EXPECT_CALL(
+      test_sink, Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                            TextMessage(AnyOf(Eq("-inf"), Eq("-Inf"))),
+                            ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                               str: "-inf"
+                                                             })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+TYPED_TEST(FloatingPointLogFormatTest, NaN) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const TypeParam value = std::numeric_limits<TypeParam>::quiet_NaN();
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(AnyOf(Eq("nan"), Eq("NaN"))),
+                 ENCODED_MESSAGE(EqualsProto(R"pb(value { str: "nan" })pb")))));
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+TYPED_TEST(FloatingPointLogFormatTest, NegativeNaN) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const TypeParam value =
+      std::copysign(std::numeric_limits<TypeParam>::quiet_NaN(), -1.0);
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(MatchesOstream(comparison_stream)),
+          TextMessage(AnyOf(Eq("-nan"), Eq("nan"), Eq("NaN"), Eq("-nan(ind)"))),
+          ENCODED_MESSAGE(EqualsProto(R"pb(value { str: "-nan" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+template <typename T>
+class VoidPtrLogFormatTest : public testing::Test {};
+using VoidPtrTypes = Types<void *, const void *>;
+TYPED_TEST_SUITE(VoidPtrLogFormatTest, VoidPtrTypes);
+
+TYPED_TEST(VoidPtrLogFormatTest, Null) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const TypeParam value = nullptr;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(AnyOf(Eq("(nil)"), Eq("0"), Eq("0x0"),
+                                   Eq("00000000"), Eq("0000000000000000"))))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+TYPED_TEST(VoidPtrLogFormatTest, NonNull) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const TypeParam value = reinterpret_cast<TypeParam>(0xdeadbeefULL);
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value;
+
+  EXPECT_CALL(test_sink,
+              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                         TextMessage(AnyOf(Eq("0xdeadbeef"), Eq("DEADBEEF"),
+                                           Eq("00000000DEADBEEF"))),
+                         ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                            str: "0xdeadbeef"
+                                                          })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+template <typename T>
+class VolatileVoidPtrLogFormatTest : public testing::Test {};
+using VolatileVoidPtrTypes = Types<volatile void *, const volatile void *>;
+TYPED_TEST_SUITE(VolatileVoidPtrLogFormatTest, VolatileVoidPtrTypes);
+
+TYPED_TEST(VolatileVoidPtrLogFormatTest, Null) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const TypeParam value = nullptr;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value;
+
+  EXPECT_CALL(
+      test_sink, Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                            TextMessage(Eq("false")),
+                            ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                               str: "false"
+                                                             })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+TYPED_TEST(VolatileVoidPtrLogFormatTest, NonNull) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const TypeParam value = reinterpret_cast<TypeParam>(0xdeadbeefLL);
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value;
+
+  EXPECT_CALL(
+      test_sink, Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                            TextMessage(Eq("true")),
+                            ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                               str: "true"
+                                                             })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+template <typename T>
+class CharPtrLogFormatTest : public testing::Test {};
+using CharPtrTypes = Types<char *, const char *>;
+TYPED_TEST_SUITE(CharPtrLogFormatTest, CharPtrTypes);
+
+TYPED_TEST(CharPtrLogFormatTest, Null) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  // Streaming `([cv] char *)nullptr` into a `std::ostream` is UB, and some C++
+  // standard library implementations choose to crash.  We take measures to log
+  // something useful instead of crashing, even when that differs from the
+  // standard library in use (and thus the behavior of `std::ostream`).
+  const TypeParam value = nullptr;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          // `MatchesOstream` deliberately omitted since we deliberately differ.
+          TextMessage(Eq("(null)")),
+          ENCODED_MESSAGE(EqualsProto(R"pb(value { str: "(null)" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+TYPED_TEST(CharPtrLogFormatTest, NonNull) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  char data[] = "value";
+  const TypeParam value = data;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value;
+
+  EXPECT_CALL(
+      test_sink, Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                            TextMessage(Eq("value")),
+                            ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                               str: "value"
+                                                             })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+TEST(BoolLogFormatTest, True) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const bool value = true;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value;
+
+  EXPECT_CALL(
+      test_sink, Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                            TextMessage(Eq("true")),
+                            ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                               str: "true"
+                                                             })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+TEST(BoolLogFormatTest, False) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const bool value = false;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value;
+
+  EXPECT_CALL(
+      test_sink, Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                            TextMessage(Eq("false")),
+                            ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                               str: "false"
+                                                             })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+TEST(LogFormatTest, StringLiteral) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << "value";
+
+  EXPECT_CALL(test_sink,
+              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                         TextMessage(Eq("value")),
+                         ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                            literal: "value"
+                                                          })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << "value";
+}
+
+TEST(LogFormatTest, CharArray) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  char value[] = "value";
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value;
+
+  EXPECT_CALL(
+      test_sink, Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                            TextMessage(Eq("value")),
+                            ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                               str: "value"
+                                                             })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+class CustomClass {};
+std::ostream& operator<<(std::ostream& os, const CustomClass&) {
+  return os << "CustomClass{}";
+}
+
+TEST(LogFormatTest, Custom) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  CustomClass value;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value;
+
+  EXPECT_CALL(test_sink,
+              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                         TextMessage(Eq("CustomClass{}")),
+                         ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                            str: "CustomClass{}"
+                                                          })pb")))));
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+class CustomClassNonCopyable {
+ public:
+  CustomClassNonCopyable() = default;
+  CustomClassNonCopyable(const CustomClassNonCopyable&) = delete;
+  CustomClassNonCopyable& operator=(const CustomClassNonCopyable&) = delete;
+};
+std::ostream& operator<<(std::ostream& os, const CustomClassNonCopyable&) {
+  return os << "CustomClassNonCopyable{}";
+}
+
+TEST(LogFormatTest, CustomNonCopyable) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  CustomClassNonCopyable value;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(Eq("CustomClassNonCopyable{}")),
+                 ENCODED_MESSAGE(EqualsProto(
+                     R"pb(value { str: "CustomClassNonCopyable{}" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+TEST(ManipulatorLogFormatTest, BoolAlphaTrue) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const bool value = true;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << std::noboolalpha << value << " "  //
+                    << std::boolalpha << value << " "    //
+                    << std::noboolalpha << value;
+
+  EXPECT_CALL(test_sink,
+              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                         TextMessage(Eq("1 true 1")),
+                         ENCODED_MESSAGE(EqualsProto(
+                             R"pb(value { str: "1" }
+                                  value { literal: " " }
+                                  value { str: "true" }
+                                  value { literal: " " }
+                                  value { str: "1" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << std::noboolalpha << value << " "  //
+            << std::boolalpha << value << " "    //
+            << std::noboolalpha << value;
+}
+
+TEST(ManipulatorLogFormatTest, BoolAlphaFalse) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const bool value = false;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << std::noboolalpha << value << " "  //
+                    << std::boolalpha << value << " "    //
+                    << std::noboolalpha << value;
+
+  EXPECT_CALL(test_sink,
+              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                         TextMessage(Eq("0 false 0")),
+                         ENCODED_MESSAGE(EqualsProto(
+                             R"pb(value { str: "0" }
+                                  value { literal: " " }
+                                  value { str: "false" }
+                                  value { literal: " " }
+                                  value { str: "0" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << std::noboolalpha << value << " "  //
+            << std::boolalpha << value << " "    //
+            << std::noboolalpha << value;
+}
+
+TEST(ManipulatorLogFormatTest, ShowPoint) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const double value = 77.0;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << std::noshowpoint << value << " "  //
+                    << std::showpoint << value << " "    //
+                    << std::noshowpoint << value;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(Eq("77 77.0000 77")),
+                 ENCODED_MESSAGE(EqualsProto(R"pb(value { str: "77" }
+                                                  value { literal: " " }
+                                                  value { str: "77.0000" }
+                                                  value { literal: " " }
+                                                  value { str: "77" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << std::noshowpoint << value << " "  //
+            << std::showpoint << value << " "    //
+            << std::noshowpoint << value;
+}
+
+TEST(ManipulatorLogFormatTest, ShowPos) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const int value = 77;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << std::noshowpos << value << " "  //
+                    << std::showpos << value << " "    //
+                    << std::noshowpos << value;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(Eq("77 +77 77")),
+                 ENCODED_MESSAGE(EqualsProto(R"pb(value { str: "77" }
+                                                  value { literal: " " }
+                                                  value { str: "+77" }
+                                                  value { literal: " " }
+                                                  value { str: "77" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << std::noshowpos << value << " "  //
+            << std::showpos << value << " "    //
+            << std::noshowpos << value;
+}
+
+TEST(ManipulatorLogFormatTest, UppercaseFloat) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const double value = 7.7e7;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << std::nouppercase << value << " "  //
+                    << std::uppercase << value << " "    //
+                    << std::nouppercase << value;
+
+  EXPECT_CALL(test_sink,
+              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                         TextMessage(Eq("7.7e+07 7.7E+07 7.7e+07")),
+                         ENCODED_MESSAGE(EqualsProto(
+                             R"pb(value { str: "7.7e+07" }
+                                  value { literal: " " }
+                                  value { str: "7.7E+07" }
+                                  value { literal: " " }
+                                  value { str: "7.7e+07" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << std::nouppercase << value << " "  //
+            << std::uppercase << value << " "    //
+            << std::nouppercase << value;
+}
+
+TEST(ManipulatorLogFormatTest, Hex) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const int value = 0x77;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << std::hex << value;
+
+  EXPECT_CALL(
+      test_sink, Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                            TextMessage(Eq("0x77")),
+                            ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                               str: "0x77"
+                                                             })pb")))));
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << std::hex << value;
+}
+
+TEST(ManipulatorLogFormatTest, Oct) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const int value = 077;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << std::oct << value;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(Eq("077")),
+                 ENCODED_MESSAGE(EqualsProto(R"pb(value { str: "077" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << std::oct << value;
+}
+
+TEST(ManipulatorLogFormatTest, Dec) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const int value = 77;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << std::hex << std::dec << value;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(Eq("77")),
+                 ENCODED_MESSAGE(EqualsProto(R"pb(value { str: "77" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << std::hex << std::dec << value;
+}
+
+TEST(ManipulatorLogFormatTest, ShowbaseHex) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const int value = 0x77;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << std::hex                         //
+                    << std::noshowbase << value << " "  //
+                    << std::showbase << value << " "    //
+                    << std::noshowbase << value;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(Eq("77 0x77 77")),
+                 ENCODED_MESSAGE(EqualsProto(R"pb(value { str: "77" }
+                                                  value { literal: " " }
+                                                  value { str: "0x77" }
+                                                  value { literal: " " }
+                                                  value { str: "77" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << std::hex                         //
+            << std::noshowbase << value << " "  //
+            << std::showbase << value << " "    //
+            << std::noshowbase << value;
+}
+
+TEST(ManipulatorLogFormatTest, ShowbaseOct) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const int value = 077;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << std::oct                         //
+                    << std::noshowbase << value << " "  //
+                    << std::showbase << value << " "    //
+                    << std::noshowbase << value;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(Eq("77 077 77")),
+                 ENCODED_MESSAGE(EqualsProto(R"pb(value { str: "77" }
+                                                  value { literal: " " }
+                                                  value { str: "077" }
+                                                  value { literal: " " }
+                                                  value { str: "77" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << std::oct                         //
+            << std::noshowbase << value << " "  //
+            << std::showbase << value << " "    //
+            << std::noshowbase << value;
+}
+
+TEST(ManipulatorLogFormatTest, UppercaseHex) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const int value = 0xbeef;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream                        //
+      << std::hex                          //
+      << std::nouppercase << value << " "  //
+      << std::uppercase << value << " "    //
+      << std::nouppercase << value;
+
+  EXPECT_CALL(test_sink,
+              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                         TextMessage(Eq("0xbeef 0XBEEF 0xbeef")),
+                         ENCODED_MESSAGE(EqualsProto(
+                             R"pb(value { str: "0xbeef" }
+                                  value { literal: " " }
+                                  value { str: "0XBEEF" }
+                                  value { literal: " " }
+                                  value { str: "0xbeef" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << std::hex                          //
+            << std::nouppercase << value << " "  //
+            << std::uppercase << value << " "    //
+            << std::nouppercase << value;
+}
+
+TEST(ManipulatorLogFormatTest, FixedFloat) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const double value = 7.7e7;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << std::fixed << value;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(Eq("77000000.000000")),
+                 ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                    str: "77000000.000000"
+                                                  })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << std::fixed << value;
+}
+
+TEST(ManipulatorLogFormatTest, ScientificFloat) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const double value = 7.7e7;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << std::scientific << value;
+
+  EXPECT_CALL(test_sink,
+              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                         TextMessage(Eq("7.700000e+07")),
+                         ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                            str: "7.700000e+07"
+                                                          })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << std::scientific << value;
+}
+
+#if defined(__BIONIC__) && (!defined(__ANDROID_API__) || __ANDROID_API__ < 22)
+// Bionic doesn't support `%a` until API 22, so this prints 'a' even if the
+// C++ standard library implements it correctly (by forwarding to printf).
+#elif defined(__GLIBCXX__) && __cplusplus < 201402L
+// libstdc++ shipped C++11 support without `std::hexfloat`.
+#else
+TEST(ManipulatorLogFormatTest, FixedAndScientificFloat) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const double value = 7.7e7;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << std::setiosflags(std::ios_base::scientific |
+                                        std::ios_base::fixed)
+                    << value;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(AnyOf(Eq("0x1.25bb50p+26"), Eq("0x1.25bb5p+26"),
+                                   Eq("0x1.25bb500000000p+26"))),
+                 ENCODED_MESSAGE(EqualsProto(R"pb(
+                   value { str: "0x1.25bb5p+26" })pb")))));
+
+  test_sink.StartCapturingLogs();
+
+  // This combination should mean the same thing as `std::hexfloat`.
+  LOG(INFO) << std::setiosflags(std::ios_base::scientific |
+                                std::ios_base::fixed)
+            << value;
+}
+#endif
+
+#if defined(__BIONIC__) && (!defined(__ANDROID_API__) || __ANDROID_API__ < 22)
+// Bionic doesn't support `%a` until API 22, so this prints 'a' even if the C++
+// standard library supports `std::hexfloat` (by forwarding to printf).
+#elif defined(__GLIBCXX__) && __cplusplus < 201402L
+// libstdc++ shipped C++11 support without `std::hexfloat`.
+#else
+TEST(ManipulatorLogFormatTest, HexfloatFloat) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const double value = 7.7e7;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << std::hexfloat << value;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(AnyOf(Eq("0x1.25bb50p+26"), Eq("0x1.25bb5p+26"),
+                                   Eq("0x1.25bb500000000p+26"))),
+                 ENCODED_MESSAGE(EqualsProto(R"pb(
+                   value { str: "0x1.25bb5p+26" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << std::hexfloat << value;
+}
+#endif
+
+TEST(ManipulatorLogFormatTest, DefaultFloatFloat) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const double value = 7.7e7;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << std::hexfloat << std::defaultfloat << value;
+
+  EXPECT_CALL(test_sink,
+              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                         TextMessage(Eq("7.7e+07")),
+                         ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                            str: "7.7e+07"
+                                                          })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << std::hexfloat << std::defaultfloat << value;
+}
+
+TEST(ManipulatorLogFormatTest, Ends) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << std::ends;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(Eq(absl::string_view("\0", 1))),
+                 ENCODED_MESSAGE(EqualsProto(R"pb(value { str: "\0" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << std::ends;
+}
+
+TEST(ManipulatorLogFormatTest, Endl) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << std::endl;
+
+  EXPECT_CALL(test_sink,
+              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                         TextMessage(Eq("\n")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << std::endl;
+}
+
+TEST(ManipulatorLogFormatTest, SetIosFlags) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const int value = 0x77;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << std::resetiosflags(std::ios_base::basefield)
+                    << std::setiosflags(std::ios_base::hex) << value << " "  //
+                    << std::resetiosflags(std::ios_base::basefield)
+                    << std::setiosflags(std::ios_base::dec) << value;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(MatchesOstream(comparison_stream)),
+          TextMessage(Eq("0x77 119")),
+          // `std::setiosflags` and `std::resetiosflags` aren't manipulators.
+          // We're unable to distinguish their return type(s) from arbitrary
+          // user-defined types and thus don't suppress the empty str value.
+          ENCODED_MESSAGE(EqualsProto(R"pb(value { str: "0x77" }
+                                           value { literal: " " }
+                                           value { str: "119" }
+          )pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << std::resetiosflags(std::ios_base::basefield)
+            << std::setiosflags(std::ios_base::hex) << value << " "  //
+            << std::resetiosflags(std::ios_base::basefield)
+            << std::setiosflags(std::ios_base::dec) << value;
+}
+
+TEST(ManipulatorLogFormatTest, SetBase) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const int value = 0x77;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << std::setbase(16) << value << " "  //
+                    << std::setbase(0) << value;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(Eq("0x77 119")),
+                 // `std::setbase` isn't a manipulator.  We're unable to
+                 // distinguish its return type from arbitrary user-defined
+                 // types and thus don't suppress the empty str value.
+                 ENCODED_MESSAGE(EqualsProto(
+                     R"pb(value { str: "0x77" }
+                          value { literal: " " }
+                          value { str: "119" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << std::setbase(16) << value << " "  //
+            << std::setbase(0) << value;
+}
+
+TEST(ManipulatorLogFormatTest, SetPrecision) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const double value = 6.022140857e23;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << std::setprecision(4) << value;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(MatchesOstream(comparison_stream)),
+          TextMessage(Eq("6.022e+23")),
+          // `std::setprecision` isn't a manipulator.  We're unable to
+          // distinguish its return type from arbitrary user-defined
+          // types and thus don't suppress the empty str value.
+          ENCODED_MESSAGE(EqualsProto(R"pb(value { str: "6.022e+23" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << std::setprecision(4) << value;
+}
+
+TEST(ManipulatorLogFormatTest, SetPrecisionOverflow) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const double value = 6.022140857e23;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << std::setprecision(200) << value;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(Eq("602214085700000015187968")),
+                 ENCODED_MESSAGE(EqualsProto(
+                     R"pb(value { str: "602214085700000015187968" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << std::setprecision(200) << value;
+}
+
+TEST(ManipulatorLogFormatTest, SetW) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const int value = 77;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << std::setw(8) << value;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(MatchesOstream(comparison_stream)),
+          TextMessage(Eq("      77")),
+          // `std::setw` isn't a manipulator.  We're unable to
+          // distinguish its return type from arbitrary user-defined
+          // types and thus don't suppress the empty str value.
+          ENCODED_MESSAGE(EqualsProto(R"pb(value { str: "      77" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << std::setw(8) << value;
+}
+
+TEST(ManipulatorLogFormatTest, Left) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const int value = -77;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << std::left << std::setw(8) << value;
+
+  EXPECT_CALL(test_sink,
+              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                         TextMessage(Eq("-77     ")),
+                         ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                            str: "-77     "
+                                                          })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << std::left << std::setw(8) << value;
+}
+
+TEST(ManipulatorLogFormatTest, Right) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const int value = -77;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << std::right << std::setw(8) << value;
+
+  EXPECT_CALL(test_sink,
+              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                         TextMessage(Eq("     -77")),
+                         ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                            str: "     -77"
+                                                          })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << std::right << std::setw(8) << value;
+}
+
+TEST(ManipulatorLogFormatTest, Internal) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const int value = -77;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << std::internal << std::setw(8) << value;
+
+  EXPECT_CALL(test_sink,
+              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                         TextMessage(Eq("-     77")),
+                         ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                            str: "-     77"
+                                                          })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << std::internal << std::setw(8) << value;
+}
+
+TEST(ManipulatorLogFormatTest, SetFill) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const int value = 77;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << std::setfill('0') << std::setw(8) << value;
+
+  EXPECT_CALL(test_sink,
+              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                         TextMessage(Eq("00000077")),
+                         // `std::setfill` isn't a manipulator.  We're
+                         // unable to distinguish its return
+                         // type from arbitrary user-defined types and
+                         // thus don't suppress the empty str value.
+                         ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                            str: "00000077"
+                                                          })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << std::setfill('0') << std::setw(8) << value;
+}
+
+class FromCustomClass {};
+std::ostream& operator<<(std::ostream& os, const FromCustomClass&) {
+  return os << "FromCustomClass{}" << std::hex;
+}
+
+TEST(ManipulatorLogFormatTest, FromCustom) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  FromCustomClass value;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value << " " << 0x77;
+
+  EXPECT_CALL(test_sink,
+              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                         TextMessage(Eq("FromCustomClass{} 0x77")),
+                         ENCODED_MESSAGE(EqualsProto(
+                             R"pb(value { str: "FromCustomClass{}" }
+                                  value { literal: " " }
+                                  value { str: "0x77" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value << " " << 0x77;
+}
+
+class StreamsNothing {};
+std::ostream& operator<<(std::ostream& os, const StreamsNothing&) { return os; }
+
+TEST(ManipulatorLogFormatTest, CustomClassStreamsNothing) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  StreamsNothing value;
+  auto comparison_stream = ComparisonStream();
+  comparison_stream << value << 77;
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(Eq("77")),
+                 ENCODED_MESSAGE(EqualsProto(R"pb(value { str: "77" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value << 77;
+}
+
+// Tests that verify the behavior when more data are streamed into a `LOG`
+// statement than fit in the buffer.
+// Structured logging scenario is tested in other unit tests since the output is
+// significantly different.
+TEST(OverflowTest, TruncatesStrings) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  // This message is too long and should be truncated to some unspecified size
+  // no greater than the buffer size but not too much less either. It should be
+  // truncated rather than discarded.
+  constexpr size_t buffer_size = 15000;
+
+  EXPECT_CALL(test_sink,
+              Send(TextMessage(
+                  AllOf(SizeIs(AllOf(Ge(buffer_size - 256), Le(buffer_size))),
+                        Each(Eq('x'))))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << std::string(2 * buffer_size, 'x');
+}
+
+}  // namespace
diff --git a/absl/log/log_macro_hygiene_test.cc b/absl/log/log_macro_hygiene_test.cc
new file mode 100644
index 0000000..ab6461f
--- /dev/null
+++ b/absl/log/log_macro_hygiene_test.cc
@@ -0,0 +1,171 @@
+//
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/attributes.h"
+#include "absl/base/log_severity.h"
+#include "absl/log/log.h"
+#include "absl/log/scoped_mock_log.h"
+
+namespace {
+using ::testing::_;
+using ::testing::Eq;
+
+namespace not_absl {
+
+class Dummy {
+ public:
+  Dummy() {}
+
+ private:
+  Dummy(const Dummy&) = delete;
+  Dummy& operator=(const Dummy&) = delete;
+};
+
+// This line tests that local definitions of INFO, WARNING, ERROR, and
+// etc don't shadow the global ones used by the logging macros.  If
+// they do, the LOG() calls in the tests won't compile, catching the
+// bug.
+const Dummy INFO, WARNING, ERROR, FATAL, NUM_SEVERITIES;
+
+// These makes sure that the uses of same-named types in the
+// implementation of the logging macros are fully qualified.
+class string {};
+class vector {};
+class LogMessage {};
+class LogMessageFatal {};
+class LogMessageQuietlyFatal {};
+class LogMessageVoidify {};
+class LogSink {};
+class NullStream {};
+class NullStreamFatal {};
+
+}  // namespace not_absl
+
+using namespace not_absl;  // NOLINT
+
+// Tests for LOG(LEVEL(()).
+
+TEST(LogHygieneTest, WorksForQualifiedSeverity) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  ::testing::InSequence seq;
+  EXPECT_CALL(test_sink, Log(absl::LogSeverity::kInfo, _, "To INFO"));
+  EXPECT_CALL(test_sink, Log(absl::LogSeverity::kWarning, _, "To WARNING"));
+  EXPECT_CALL(test_sink, Log(absl::LogSeverity::kError, _, "To ERROR"));
+
+  test_sink.StartCapturingLogs();
+  // Note that LOG(LEVEL()) expects the severity as a run-time
+  // expression (as opposed to a compile-time constant).  Hence we
+  // test that :: is allowed before INFO, etc.
+  LOG(LEVEL(absl::LogSeverity::kInfo)) << "To INFO";
+  LOG(LEVEL(absl::LogSeverity::kWarning)) << "To WARNING";
+  LOG(LEVEL(absl::LogSeverity::kError)) << "To ERROR";
+}
+
+TEST(LogHygieneTest, WorksWithAlternativeINFOSymbol) {
+  const double INFO ABSL_ATTRIBUTE_UNUSED = 7.77;
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(test_sink, Log(absl::LogSeverity::kInfo, _, "Hello world"));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << "Hello world";
+}
+
+TEST(LogHygieneTest, WorksWithAlternativeWARNINGSymbol) {
+  const double WARNING ABSL_ATTRIBUTE_UNUSED = 7.77;
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(test_sink, Log(absl::LogSeverity::kWarning, _, "Hello world"));
+
+  test_sink.StartCapturingLogs();
+  LOG(WARNING) << "Hello world";
+}
+
+TEST(LogHygieneTest, WorksWithAlternativeERRORSymbol) {
+  const double ERROR ABSL_ATTRIBUTE_UNUSED = 7.77;
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(test_sink, Log(absl::LogSeverity::kError, _, "Hello world"));
+
+  test_sink.StartCapturingLogs();
+  LOG(ERROR) << "Hello world";
+}
+
+TEST(LogHygieneTest, WorksWithAlternativeLEVELSymbol) {
+  const double LEVEL ABSL_ATTRIBUTE_UNUSED = 7.77;
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(test_sink, Log(absl::LogSeverity::kError, _, "Hello world"));
+
+  test_sink.StartCapturingLogs();
+  LOG(LEVEL(absl::LogSeverity::kError)) << "Hello world";
+}
+
+#define INFO Bogus
+#ifdef NDEBUG
+constexpr bool IsOptimized = false;
+#else
+constexpr bool IsOptimized = true;
+#endif
+
+TEST(LogHygieneTest, WorksWithINFODefined) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(test_sink, Log(absl::LogSeverity::kInfo, _, "Hello world"))
+      .Times(2 + (IsOptimized ? 2 : 0));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << "Hello world";
+  LOG_IF(INFO, true) << "Hello world";
+
+  DLOG(INFO) << "Hello world";
+  DLOG_IF(INFO, true) << "Hello world";
+}
+
+#undef INFO
+
+TEST(LogHygieneTest, ExpressionEvaluationInLEVELSeverity) {
+  auto i = static_cast<int>(absl::LogSeverity::kInfo);
+  LOG(LEVEL(++i)) << "hello world";  // NOLINT
+  EXPECT_THAT(i, Eq(static_cast<int>(absl::LogSeverity::kInfo) + 1));
+}
+
+TEST(LogHygieneTest, ExpressionEvaluationInStreamedMessage) {
+  int i = 0;
+  LOG(INFO) << ++i;
+  EXPECT_THAT(i, 1);
+  LOG_IF(INFO, false) << ++i;
+  EXPECT_THAT(i, 1);
+}
+
+// Tests that macros are usable in unbraced switch statements.
+// -----------------------------------------------------------
+
+class UnbracedSwitchCompileTest {
+  static void Log() {
+    switch (0) {
+      case 0:
+        LOG(INFO);
+        break;
+      default:
+        break;
+    }
+  }
+};
+
+}  // namespace
diff --git a/absl/log/log_modifier_methods_test.cc b/absl/log/log_modifier_methods_test.cc
new file mode 100644
index 0000000..a9bf38b
--- /dev/null
+++ b/absl/log/log_modifier_methods_test.cc
@@ -0,0 +1,231 @@
+//
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <errno.h>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/log/internal/test_actions.h"
+#include "absl/log/internal/test_helpers.h"
+#include "absl/log/internal/test_matchers.h"
+#include "absl/log/log.h"
+#include "absl/log/log_sink.h"
+#include "absl/log/scoped_mock_log.h"
+#include "absl/strings/match.h"
+#include "absl/strings/string_view.h"
+#include "absl/time/time.h"
+
+namespace {
+#if GTEST_HAS_DEATH_TEST
+using ::absl::log_internal::DeathTestExpectedLogging;
+using ::absl::log_internal::DeathTestUnexpectedLogging;
+using ::absl::log_internal::DeathTestValidateExpectations;
+using ::absl::log_internal::DiedOfQFatal;
+#endif
+using ::absl::log_internal::LogSeverity;
+using ::absl::log_internal::Prefix;
+using ::absl::log_internal::SourceBasename;
+using ::absl::log_internal::SourceFilename;
+using ::absl::log_internal::SourceLine;
+using ::absl::log_internal::Stacktrace;
+using ::absl::log_internal::TextMessage;
+using ::absl::log_internal::TextMessageWithPrefix;
+using ::absl::log_internal::TextMessageWithPrefixAndNewline;
+using ::absl::log_internal::TextPrefix;
+using ::absl::log_internal::ThreadID;
+using ::absl::log_internal::Timestamp;
+using ::absl::log_internal::Verbosity;
+
+using ::testing::AllOf;
+using ::testing::AnyNumber;
+using ::testing::AnyOf;
+using ::testing::Eq;
+using ::testing::IsEmpty;
+using ::testing::IsFalse;
+using ::testing::Truly;
+
+TEST(TailCallsModifiesTest, AtLocationFileLine) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          // The metadata should change:
+          SourceFilename(Eq("/my/very/very/very_long_source_file.cc")),
+          SourceBasename(Eq("very_long_source_file.cc")), SourceLine(Eq(777)),
+          // The logged line should change too, even though the prefix must
+          // grow to fit the new metadata.
+          TextMessageWithPrefix(Truly([](absl::string_view msg) {
+            return absl::EndsWith(msg,
+                                  " very_long_source_file.cc:777] hello world");
+          })))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO).AtLocation("/my/very/very/very_long_source_file.cc", 777)
+      << "hello world";
+}
+
+TEST(TailCallsModifiesTest, NoPrefix) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(test_sink, Send(AllOf(Prefix(IsFalse()), TextPrefix(IsEmpty()),
+                                    TextMessageWithPrefix(Eq("hello world")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO).NoPrefix() << "hello world";
+}
+
+TEST(TailCallsModifiesTest, NoPrefixNoMessageNoShirtNoShoesNoService) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(test_sink,
+              Send(AllOf(Prefix(IsFalse()), TextPrefix(IsEmpty()),
+                         TextMessageWithPrefix(IsEmpty()),
+                         TextMessageWithPrefixAndNewline(Eq("\n")))));
+  test_sink.StartCapturingLogs();
+  LOG(INFO).NoPrefix();
+}
+
+TEST(TailCallsModifiesTest, WithVerbosity) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(test_sink, Send(Verbosity(Eq(2))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO).WithVerbosity(2) << "hello world";
+}
+
+TEST(TailCallsModifiesTest, WithVerbosityNoVerbosity) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(test_sink,
+              Send(Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO).WithVerbosity(2).WithVerbosity(absl::LogEntry::kNoVerbosityLevel)
+      << "hello world";
+}
+
+TEST(TailCallsModifiesTest, WithTimestamp) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(test_sink, Send(Timestamp(Eq(absl::UnixEpoch()))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO).WithTimestamp(absl::UnixEpoch()) << "hello world";
+}
+
+TEST(TailCallsModifiesTest, WithThreadID) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(test_sink, Send(AllOf(ThreadID(Eq(1234)))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO).WithThreadID(1234) << "hello world";
+}
+
+TEST(TailCallsModifiesTest, WithMetadataFrom) {
+  class ForwardingLogSink : public absl::LogSink {
+   public:
+    void Send(const absl::LogEntry &entry) override {
+      LOG(LEVEL(entry.log_severity())).WithMetadataFrom(entry)
+          << "forwarded: " << entry.text_message();
+    }
+  } forwarding_sink;
+
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(SourceFilename(Eq("fake/file")), SourceBasename(Eq("file")),
+                 SourceLine(Eq(123)), Prefix(IsFalse()),
+                 LogSeverity(Eq(absl::LogSeverity::kWarning)),
+                 Timestamp(Eq(absl::UnixEpoch())), ThreadID(Eq(456)),
+                 TextMessage(Eq("forwarded: hello world")), Verbosity(Eq(7)),
+                 ENCODED_MESSAGE(
+                     EqualsProto(R"pb(value { literal: "forwarded: " }
+                                      value { str: "hello world" })pb")))));
+
+  test_sink.StartCapturingLogs();
+  LOG(WARNING)
+          .AtLocation("fake/file", 123)
+          .NoPrefix()
+          .WithTimestamp(absl::UnixEpoch())
+          .WithThreadID(456)
+          .WithVerbosity(7)
+          .ToSinkOnly(&forwarding_sink)
+      << "hello world";
+}
+
+TEST(TailCallsModifiesTest, WithPerror) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(AnyOf(Eq("hello world: Bad file number [9]"),
+                                   Eq("hello world: Bad file descriptor [9]"),
+                                   Eq("hello world: Bad file descriptor [8]"))),
+                 ENCODED_MESSAGE(
+                     AnyOf(EqualsProto(R"pb(value { literal: "hello world" }
+                                            value { literal: ": " }
+                                            value { str: "Bad file number" }
+                                            value { literal: " [" }
+                                            value { str: "9" }
+                                            value { literal: "]" })pb"),
+                           EqualsProto(R"pb(value { literal: "hello world" }
+                                            value { literal: ": " }
+                                            value { str: "Bad file descriptor" }
+                                            value { literal: " [" }
+                                            value { str: "9" }
+                                            value { literal: "]" })pb"),
+                           EqualsProto(R"pb(value { literal: "hello world" }
+                                            value { literal: ": " }
+                                            value { str: "Bad file descriptor" }
+                                            value { literal: " [" }
+                                            value { str: "8" }
+                                            value { literal: "]" })pb"))))));
+
+  test_sink.StartCapturingLogs();
+  errno = EBADF;
+  LOG(INFO).WithPerror() << "hello world";
+}
+
+#if GTEST_HAS_DEATH_TEST
+TEST(ModifierMethodDeathTest, ToSinkOnlyQFatal) {
+  EXPECT_EXIT(
+      {
+        absl::ScopedMockLog test_sink(
+            absl::MockLogDefault::kDisallowUnexpected);
+
+        auto do_log = [&test_sink] {
+          LOG(QFATAL).ToSinkOnly(&test_sink.UseAsLocalSink()) << "hello world";
+        };
+
+        EXPECT_CALL(test_sink, Send)
+            .Times(AnyNumber())
+            .WillRepeatedly(DeathTestUnexpectedLogging());
+
+        EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq("hello world")),
+                                          Stacktrace(IsEmpty()))))
+            .WillOnce(DeathTestExpectedLogging());
+
+        test_sink.StartCapturingLogs();
+        do_log();
+      },
+      DiedOfQFatal, DeathTestValidateExpectations());
+}
+#endif
+
+}  // namespace
diff --git a/absl/log/log_sink.cc b/absl/log/log_sink.cc
new file mode 100644
index 0000000..01d7ca8
--- /dev/null
+++ b/absl/log/log_sink.cc
@@ -0,0 +1,23 @@
+// Copyright 2022 The Abseil Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/log_sink.h"
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+void LogSink::KeyFunction() const {}
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/log/log_sink.h b/absl/log/log_sink.h
new file mode 100644
index 0000000..9bfa6f8
--- /dev/null
+++ b/absl/log/log_sink.h
@@ -0,0 +1,64 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/log_sink.h
+// -----------------------------------------------------------------------------
+//
+// This header declares the interface class `absl::LogSink`.
+
+#ifndef ABSL_LOG_LOG_SINK_H_
+#define ABSL_LOG_LOG_SINK_H_
+
+#include "absl/base/config.h"
+#include "absl/log/log_entry.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// absl::LogSink
+//
+// `absl::LogSink` is an interface which can be extended to intercept and
+// process particular messages (with `LOG.ToSinkOnly()` or
+// `LOG.ToSinkAlso()`) or all messages (if registered with
+// `absl::AddLogSink`).  Implementations must be thread-safe, and should take
+// care not to take any locks that might be held by the `LOG` caller.
+class LogSink {
+ public:
+  virtual ~LogSink() = default;
+
+  // LogSink::Send()
+  //
+  // `Send` is called synchronously during the log statement.
+  //
+  // It is safe to use `LOG` within an implementation of `Send`.  `ToSinkOnly`
+  // and `ToSinkAlso` are safe in general but can be used to create an infinite
+  // loop if you try.
+  virtual void Send(const absl::LogEntry& entry) = 0;
+
+  // LogSink::Flush()
+  //
+  // Sinks that buffer messages should override this method to flush the buffer
+  // and return.
+  virtual void Flush() {}
+
+ private:
+  // https://lld.llvm.org/missingkeyfunction.html#missing-key-function
+  virtual void KeyFunction() const final;  // NOLINT(readability/inheritance)
+};
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_LOG_LOG_SINK_H_
diff --git a/absl/log/log_sink_registry.h b/absl/log/log_sink_registry.h
new file mode 100644
index 0000000..bf76cce
--- /dev/null
+++ b/absl/log/log_sink_registry.h
@@ -0,0 +1,61 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/log_sink_registry.h
+// -----------------------------------------------------------------------------
+//
+// This header declares APIs to operate on global set of registered log sinks.
+
+#ifndef ABSL_LOG_LOG_SINK_REGISTRY_H_
+#define ABSL_LOG_LOG_SINK_REGISTRY_H_
+
+#include "absl/base/config.h"
+#include "absl/log/internal/log_sink_set.h"
+#include "absl/log/log_sink.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// AddLogSink(), RemoveLogSink()
+//
+// Adds or removes a `absl::LogSink` as a consumer of logging data.
+//
+// These functions are thread-safe.
+//
+// It is an error to attempt to add a sink that's already registered or to
+// attempt to remove one that isn't.
+//
+// To avoid unbounded recursion, dispatch to registered `absl::LogSink`s is
+// disabled per-thread while running the `Send()` method of registered
+// `absl::LogSink`s.  Affected messages are dispatched to a special internal
+// sink instead which writes them to `stderr`.
+//
+// Do not call these inside `absl::LogSink::Send`.
+inline void AddLogSink(absl::LogSink* sink) { log_internal::AddLogSink(sink); }
+inline void RemoveLogSink(absl::LogSink* sink) {
+  log_internal::RemoveLogSink(sink);
+}
+
+// FlushLogSinks()
+//
+// Calls `absl::LogSink::Flush` on all registered sinks.
+//
+// Do not call this inside `absl::LogSink::Send`.
+inline void FlushLogSinks() { log_internal::FlushLogSinks(); }
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_LOG_LOG_SINK_REGISTRY_H_
diff --git a/absl/log/log_sink_test.cc b/absl/log/log_sink_test.cc
new file mode 100644
index 0000000..8903da7
--- /dev/null
+++ b/absl/log/log_sink_test.cc
@@ -0,0 +1,419 @@
+//
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/log_sink.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/attributes.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/log/internal/test_actions.h"
+#include "absl/log/internal/test_helpers.h"
+#include "absl/log/internal/test_matchers.h"
+#include "absl/log/log.h"
+#include "absl/log/log_sink_registry.h"
+#include "absl/log/scoped_mock_log.h"
+#include "absl/strings/string_view.h"
+
+namespace {
+
+using ::absl::log_internal::DeathTestExpectedLogging;
+using ::absl::log_internal::DeathTestUnexpectedLogging;
+using ::absl::log_internal::DeathTestValidateExpectations;
+using ::absl::log_internal::DiedOfFatal;
+using ::testing::_;
+using ::testing::AnyNumber;
+using ::testing::HasSubstr;
+using ::testing::InSequence;
+
+auto* test_env ABSL_ATTRIBUTE_UNUSED = ::testing::AddGlobalTestEnvironment(
+    new absl::log_internal::LogTestEnvironment);
+
+// Tests for global log sink registration.
+// ---------------------------------------
+
+TEST(LogSinkRegistryTest, AddLogSink) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  InSequence s;
+  EXPECT_CALL(test_sink, Log(_, _, "hello world")).Times(0);
+  EXPECT_CALL(test_sink, Log(absl::LogSeverity::kInfo, __FILE__, "Test : 42"));
+  EXPECT_CALL(test_sink,
+              Log(absl::LogSeverity::kWarning, __FILE__, "Danger ahead"));
+  EXPECT_CALL(test_sink,
+              Log(absl::LogSeverity::kError, __FILE__, "This is an error"));
+
+  LOG(INFO) << "hello world";
+  test_sink.StartCapturingLogs();
+
+  LOG(INFO) << "Test : " << 42;
+  LOG(WARNING) << "Danger" << ' ' << "ahead";
+  LOG(ERROR) << "This is an error";
+
+  test_sink.StopCapturingLogs();
+  LOG(INFO) << "Goodby world";
+}
+
+TEST(LogSinkRegistryTest, MultipleLogSinks) {
+  absl::ScopedMockLog test_sink1(absl::MockLogDefault::kDisallowUnexpected);
+  absl::ScopedMockLog test_sink2(absl::MockLogDefault::kDisallowUnexpected);
+
+  ::testing::InSequence seq;
+  EXPECT_CALL(test_sink1, Log(absl::LogSeverity::kInfo, _, "First")).Times(1);
+  EXPECT_CALL(test_sink2, Log(absl::LogSeverity::kInfo, _, "First")).Times(0);
+
+  EXPECT_CALL(test_sink1, Log(absl::LogSeverity::kInfo, _, "Second")).Times(1);
+  EXPECT_CALL(test_sink2, Log(absl::LogSeverity::kInfo, _, "Second")).Times(1);
+
+  EXPECT_CALL(test_sink1, Log(absl::LogSeverity::kInfo, _, "Third")).Times(0);
+  EXPECT_CALL(test_sink2, Log(absl::LogSeverity::kInfo, _, "Third")).Times(1);
+
+  LOG(INFO) << "Before first";
+
+  test_sink1.StartCapturingLogs();
+  LOG(INFO) << "First";
+
+  test_sink2.StartCapturingLogs();
+  LOG(INFO) << "Second";
+
+  test_sink1.StopCapturingLogs();
+  LOG(INFO) << "Third";
+
+  test_sink2.StopCapturingLogs();
+  LOG(INFO) << "Fourth";
+}
+
+TEST(LogSinkRegistrationDeathTest, DuplicateSinkRegistration) {
+  ASSERT_DEATH_IF_SUPPORTED(
+      {
+        absl::ScopedMockLog sink;
+        sink.StartCapturingLogs();
+        absl::AddLogSink(&sink.UseAsLocalSink());
+      },
+      HasSubstr("Duplicate log sinks"));
+}
+
+TEST(LogSinkRegistrationDeathTest, MismatchSinkRemoval) {
+  ASSERT_DEATH_IF_SUPPORTED(
+      {
+        absl::ScopedMockLog sink;
+        absl::RemoveLogSink(&sink.UseAsLocalSink());
+      },
+      HasSubstr("Mismatched log sink"));
+}
+
+// Tests for log sink semantic.
+// ---------------------------------------
+
+TEST(LogSinkTest, FlushSinks) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(test_sink, Flush()).Times(2);
+
+  test_sink.StartCapturingLogs();
+
+  absl::FlushLogSinks();
+  absl::FlushLogSinks();
+}
+
+TEST(LogSinkDeathTest, DeathInSend) {
+  class FatalSendSink : public absl::LogSink {
+   public:
+    void Send(const absl::LogEntry&) override { LOG(FATAL) << "goodbye world"; }
+  };
+
+  FatalSendSink sink;
+  EXPECT_EXIT({ LOG(INFO).ToSinkAlso(&sink) << "hello world"; }, DiedOfFatal,
+              _);
+}
+
+// Tests for explicit log sink redirection.
+// ---------------------------------------
+
+TEST(LogSinkTest, ToSinkAlso) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+  absl::ScopedMockLog another_sink(absl::MockLogDefault::kDisallowUnexpected);
+  EXPECT_CALL(test_sink, Log(_, _, "hello world"));
+  EXPECT_CALL(another_sink, Log(_, _, "hello world"));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO).ToSinkAlso(&another_sink.UseAsLocalSink()) << "hello world";
+}
+
+TEST(LogSinkTest, ToSinkOnly) {
+  absl::ScopedMockLog another_sink(absl::MockLogDefault::kDisallowUnexpected);
+  EXPECT_CALL(another_sink, Log(_, _, "hello world"));
+  LOG(INFO).ToSinkOnly(&another_sink.UseAsLocalSink()) << "hello world";
+}
+
+TEST(LogSinkTest, ToManySinks) {
+  absl::ScopedMockLog sink1(absl::MockLogDefault::kDisallowUnexpected);
+  absl::ScopedMockLog sink2(absl::MockLogDefault::kDisallowUnexpected);
+  absl::ScopedMockLog sink3(absl::MockLogDefault::kDisallowUnexpected);
+  absl::ScopedMockLog sink4(absl::MockLogDefault::kDisallowUnexpected);
+  absl::ScopedMockLog sink5(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(sink3, Log(_, _, "hello world"));
+  EXPECT_CALL(sink4, Log(_, _, "hello world"));
+  EXPECT_CALL(sink5, Log(_, _, "hello world"));
+
+  LOG(INFO)
+          .ToSinkAlso(&sink1.UseAsLocalSink())
+          .ToSinkAlso(&sink2.UseAsLocalSink())
+          .ToSinkOnly(&sink3.UseAsLocalSink())
+          .ToSinkAlso(&sink4.UseAsLocalSink())
+          .ToSinkAlso(&sink5.UseAsLocalSink())
+      << "hello world";
+}
+
+class ReentrancyTest : public ::testing::Test {
+ protected:
+  ReentrancyTest() = default;
+  enum class LogMode : int { kNormal, kToSinkAlso, kToSinkOnly };
+
+  class ReentrantSendLogSink : public absl::LogSink {
+   public:
+    explicit ReentrantSendLogSink(absl::LogSeverity severity,
+                                  absl::LogSink* sink, LogMode mode)
+        : severity_(severity), sink_(sink), mode_(mode) {}
+    explicit ReentrantSendLogSink(absl::LogSeverity severity)
+        : ReentrantSendLogSink(severity, nullptr, LogMode::kNormal) {}
+
+    void Send(const absl::LogEntry&) override {
+      switch (mode_) {
+        case LogMode::kNormal:
+          LOG(LEVEL(severity_)) << "The log is coming from *inside the sink*.";
+          break;
+        case LogMode::kToSinkAlso:
+          LOG(LEVEL(severity_)).ToSinkAlso(sink_)
+              << "The log is coming from *inside the sink*.";
+          break;
+        case LogMode::kToSinkOnly:
+          LOG(LEVEL(severity_)).ToSinkOnly(sink_)
+              << "The log is coming from *inside the sink*.";
+          break;
+        default:
+          ABSL_RAW_LOG(FATAL, "Invalid mode %d.\n", static_cast<int>(mode_));
+      }
+    }
+
+   private:
+    absl::LogSeverity severity_;
+    absl::LogSink* sink_;
+    LogMode mode_;
+  };
+
+  static absl::string_view LogAndReturn(absl::LogSeverity severity,
+                                        absl::string_view to_log,
+                                        absl::string_view to_return) {
+    LOG(LEVEL(severity)) << to_log;
+    return to_return;
+  }
+};
+
+TEST_F(ReentrancyTest, LogFunctionThatLogs) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  InSequence seq;
+  EXPECT_CALL(test_sink, Log(absl::LogSeverity::kInfo, _, "hello"));
+  EXPECT_CALL(test_sink, Log(absl::LogSeverity::kInfo, _, "world"));
+  EXPECT_CALL(test_sink, Log(absl::LogSeverity::kWarning, _, "danger"));
+  EXPECT_CALL(test_sink, Log(absl::LogSeverity::kInfo, _, "here"));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << LogAndReturn(absl::LogSeverity::kInfo, "hello", "world");
+  LOG(INFO) << LogAndReturn(absl::LogSeverity::kWarning, "danger", "here");
+}
+
+TEST_F(ReentrancyTest, RegisteredLogSinkThatLogsInSend) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+  ReentrantSendLogSink renentrant_sink(absl::LogSeverity::kInfo);
+  EXPECT_CALL(test_sink, Log(_, _, "hello world"));
+
+  test_sink.StartCapturingLogs();
+  absl::AddLogSink(&renentrant_sink);
+  LOG(INFO) << "hello world";
+  absl::RemoveLogSink(&renentrant_sink);
+}
+
+TEST_F(ReentrancyTest, AlsoLogSinkThatLogsInSend) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+  ReentrantSendLogSink reentrant_sink(absl::LogSeverity::kInfo);
+  EXPECT_CALL(test_sink, Log(_, _, "hello world"));
+  EXPECT_CALL(test_sink,
+              Log(_, _, "The log is coming from *inside the sink*."));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO).ToSinkAlso(&reentrant_sink) << "hello world";
+}
+
+TEST_F(ReentrancyTest, RegisteredAlsoLogSinkThatLogsInSend) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+  ReentrantSendLogSink reentrant_sink(absl::LogSeverity::kInfo);
+  EXPECT_CALL(test_sink, Log(_, _, "hello world"));
+  // We only call into the test_log sink once with this message, since the
+  // second time log statement is run we are in "ThreadIsLogging" mode and all
+  // the log statements are redirected into stderr.
+  EXPECT_CALL(test_sink,
+              Log(_, _, "The log is coming from *inside the sink*."));
+
+  test_sink.StartCapturingLogs();
+  absl::AddLogSink(&reentrant_sink);
+  LOG(INFO).ToSinkAlso(&reentrant_sink) << "hello world";
+  absl::RemoveLogSink(&reentrant_sink);
+}
+
+TEST_F(ReentrancyTest, OnlyLogSinkThatLogsInSend) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+  ReentrantSendLogSink reentrant_sink(absl::LogSeverity::kInfo);
+  EXPECT_CALL(test_sink,
+              Log(_, _, "The log is coming from *inside the sink*."));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO).ToSinkOnly(&reentrant_sink) << "hello world";
+}
+
+TEST_F(ReentrancyTest, RegisteredOnlyLogSinkThatLogsInSend) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+  ReentrantSendLogSink reentrant_sink(absl::LogSeverity::kInfo);
+  EXPECT_CALL(test_sink,
+              Log(_, _, "The log is coming from *inside the sink*."));
+
+  test_sink.StartCapturingLogs();
+  absl::AddLogSink(&reentrant_sink);
+  LOG(INFO).ToSinkOnly(&reentrant_sink) << "hello world";
+  absl::RemoveLogSink(&reentrant_sink);
+}
+
+using ReentrancyDeathTest = ReentrancyTest;
+
+TEST_F(ReentrancyDeathTest, LogFunctionThatLogsFatal) {
+  EXPECT_EXIT(
+      {
+        absl::ScopedMockLog test_sink;
+
+        EXPECT_CALL(test_sink, Log)
+            .Times(AnyNumber())
+            .WillRepeatedly(DeathTestUnexpectedLogging());
+        EXPECT_CALL(test_sink, Log(_, _, "hello"))
+            .WillOnce(DeathTestExpectedLogging());
+
+        test_sink.StartCapturingLogs();
+        LOG(INFO) << LogAndReturn(absl::LogSeverity::kFatal, "hello", "world");
+      },
+      DiedOfFatal, DeathTestValidateExpectations());
+}
+
+TEST_F(ReentrancyDeathTest, RegisteredLogSinkThatLogsFatalInSend) {
+  EXPECT_EXIT(
+      {
+        absl::ScopedMockLog test_sink;
+        ReentrantSendLogSink reentrant_sink(absl::LogSeverity::kFatal);
+        EXPECT_CALL(test_sink, Log)
+            .Times(AnyNumber())
+            .WillRepeatedly(DeathTestUnexpectedLogging());
+        EXPECT_CALL(test_sink, Log(_, _, "hello world"))
+            .WillOnce(DeathTestExpectedLogging());
+
+        test_sink.StartCapturingLogs();
+        absl::AddLogSink(&reentrant_sink);
+        LOG(INFO) << "hello world";
+        // No need to call RemoveLogSink - process is dead at this point.
+      },
+      DiedOfFatal, DeathTestValidateExpectations());
+}
+
+TEST_F(ReentrancyDeathTest, AlsoLogSinkThatLogsFatalInSend) {
+  EXPECT_EXIT(
+      {
+        absl::ScopedMockLog test_sink;
+        ReentrantSendLogSink reentrant_sink(absl::LogSeverity::kFatal);
+
+        EXPECT_CALL(test_sink, Log)
+            .Times(AnyNumber())
+            .WillRepeatedly(DeathTestUnexpectedLogging());
+        EXPECT_CALL(test_sink, Log(_, _, "hello world"))
+            .WillOnce(DeathTestExpectedLogging());
+        EXPECT_CALL(test_sink,
+                    Log(_, _, "The log is coming from *inside the sink*."))
+            .WillOnce(DeathTestExpectedLogging());
+
+        test_sink.StartCapturingLogs();
+        LOG(INFO).ToSinkAlso(&reentrant_sink) << "hello world";
+      },
+      DiedOfFatal, DeathTestValidateExpectations());
+}
+
+TEST_F(ReentrancyDeathTest, RegisteredAlsoLogSinkThatLogsFatalInSend) {
+  EXPECT_EXIT(
+      {
+        absl::ScopedMockLog test_sink;
+        ReentrantSendLogSink reentrant_sink(absl::LogSeverity::kFatal);
+        EXPECT_CALL(test_sink, Log)
+            .Times(AnyNumber())
+            .WillRepeatedly(DeathTestUnexpectedLogging());
+        EXPECT_CALL(test_sink, Log(_, _, "hello world"))
+            .WillOnce(DeathTestExpectedLogging());
+        EXPECT_CALL(test_sink,
+                    Log(_, _, "The log is coming from *inside the sink*."))
+            .WillOnce(DeathTestExpectedLogging());
+
+        test_sink.StartCapturingLogs();
+        absl::AddLogSink(&reentrant_sink);
+        LOG(INFO).ToSinkAlso(&reentrant_sink) << "hello world";
+        // No need to call RemoveLogSink - process is dead at this point.
+      },
+      DiedOfFatal, DeathTestValidateExpectations());
+}
+
+TEST_F(ReentrancyDeathTest, OnlyLogSinkThatLogsFatalInSend) {
+  EXPECT_EXIT(
+      {
+        absl::ScopedMockLog test_sink;
+        ReentrantSendLogSink reentrant_sink(absl::LogSeverity::kFatal);
+        EXPECT_CALL(test_sink, Log)
+            .Times(AnyNumber())
+            .WillRepeatedly(DeathTestUnexpectedLogging());
+        EXPECT_CALL(test_sink,
+                    Log(_, _, "The log is coming from *inside the sink*."))
+            .WillOnce(DeathTestExpectedLogging());
+
+        test_sink.StartCapturingLogs();
+        LOG(INFO).ToSinkOnly(&reentrant_sink) << "hello world";
+      },
+      DiedOfFatal, DeathTestValidateExpectations());
+}
+
+TEST_F(ReentrancyDeathTest, RegisteredOnlyLogSinkThatLogsFatalInSend) {
+  EXPECT_EXIT(
+      {
+        absl::ScopedMockLog test_sink;
+        ReentrantSendLogSink reentrant_sink(absl::LogSeverity::kFatal);
+        EXPECT_CALL(test_sink, Log)
+            .Times(AnyNumber())
+            .WillRepeatedly(DeathTestUnexpectedLogging());
+        EXPECT_CALL(test_sink,
+                    Log(_, _, "The log is coming from *inside the sink*."))
+            .WillOnce(DeathTestExpectedLogging());
+
+        test_sink.StartCapturingLogs();
+        absl::AddLogSink(&reentrant_sink);
+        LOG(INFO).ToSinkOnly(&reentrant_sink) << "hello world";
+        // No need to call RemoveLogSink - process is dead at this point.
+      },
+      DiedOfFatal, DeathTestValidateExpectations());
+}
+
+}  // namespace
diff --git a/absl/log/log_streamer.h b/absl/log/log_streamer.h
new file mode 100644
index 0000000..c3776ce
--- /dev/null
+++ b/absl/log/log_streamer.h
@@ -0,0 +1,176 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/log_streamer.h
+// -----------------------------------------------------------------------------
+//
+// This header declares the class `LogStreamer` and convenience functions to
+// construct LogStreamer objects with different associated log severity levels.
+
+#ifndef ABSL_LOG_LOG_STREAMER_H_
+#define ABSL_LOG_LOG_STREAMER_H_
+
+#include <ios>
+#include <memory>
+#include <ostream>
+#include <string>
+#include <utility>
+
+#include "absl/base/config.h"
+#include "absl/base/log_severity.h"
+#include "absl/log/log.h"
+#include "absl/memory/memory.h"
+#include "absl/strings/internal/ostringstream.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// LogStreamer
+//
+// Although you can stream into `LOG(INFO)`, you can't pass it into a function
+// that takes a `std::ostream` parameter. `LogStreamer::stream()` provides a
+// `std::ostream` that buffers everything that's streamed in.  The buffer's
+// contents are logged as if by `LOG` when the `LogStreamer` is destroyed.
+// If nothing is streamed in, an empty message is logged.  If the specified
+// severity is `absl::LogSeverity::kFatal`, the program will be terminated when
+// the `LogStreamer` is destroyed regardless of whether any data were streamed
+// in.
+//
+// Factory functions corresponding to the `absl::LogSeverity` enumerators
+// are provided for convenience; if the desired severity is variable, invoke the
+// constructor directly.
+//
+// LogStreamer is movable, but not copyable.
+//
+// Examples:
+//
+//   ShaveYakAndWriteToStream(
+//       yak, absl::LogInfoStreamer(__FILE__, __LINE__).stream());
+//
+//   {
+//     // This logs a single line containing data streamed by all three function
+//     // calls.
+//     absl::LogStreamer streamer(absl::LogSeverity::kInfo, __FILE__, __LINE__);
+//     ShaveYakAndWriteToStream(yak1, streamer.stream());
+//     streamer.stream() << " ";
+//     ShaveYakAndWriteToStream(yak2, streamer.stream());
+//     streamer.stream() << " ";
+//     ShaveYakAndWriteToStreamPointer(yak3, &streamer.stream());
+//   }
+class LogStreamer final {
+ public:
+  // LogStreamer::LogStreamer()
+  //
+  // Creates a LogStreamer with a given `severity` that will log a message
+  // attributed to the given `file` and `line`.
+  explicit LogStreamer(absl::LogSeverity severity, absl::string_view file,
+                       int line)
+      : severity_(severity),
+        line_(line),
+        file_(file),
+        stream_(
+            absl::make_unique<absl::strings_internal::OStringStream>(&buf_)) {
+    // To match `LOG`'s defaults:
+    stream_->setf(std::ios_base::showbase | std::ios_base::boolalpha);
+  }
+
+  // A moved-from `absl::LogStreamer` does not `LOG` when destroyed,
+  // and a program that streams into one has undefined behavior.
+  LogStreamer(LogStreamer&& that) noexcept
+      : severity_(that.severity_),
+        line_(that.line_),
+        file_(std::move(that.file_)),
+        buf_(std::move(that.buf_)),
+        stream_(that.stream_
+                    ? absl::make_unique<absl::strings_internal::OStringStream>(
+                          &buf_)
+                    : nullptr) {
+    that.stream_.reset();
+  }
+  LogStreamer& operator=(LogStreamer&& that) {
+    LOG_IF(LEVEL(severity_), stream_).AtLocation(file_, line_) << buf_;
+    severity_ = that.severity_;
+    file_ = std::move(that.file_);
+    line_ = that.line_;
+    buf_ = std::move(that.buf_);
+    stream_ =
+        that.stream_
+            ? absl::make_unique<absl::strings_internal::OStringStream>(&buf_)
+            : nullptr;
+    that.stream_.reset();
+    return *this;
+  }
+
+  // LogStreamer::~LogStreamer()
+  //
+  // Logs this LogStreamer's buffered content as if by LOG.
+  ~LogStreamer() {
+    LOG_IF(LEVEL(severity_), stream_).AtLocation(file_, line_) << buf_;
+  }
+
+  // LogStreamer::stream()
+  //
+  // Returns the `std::ostream` to use to write into this LogStreamer' internal
+  // buffer.
+  std::ostream& stream() { return *stream_; }
+
+ private:
+  absl::LogSeverity severity_;
+  int line_;
+  std::string file_;
+  std::string buf_;
+  // TODO(durandal): de-pointerize this once we are off of our old mostly-C++11
+  // libstdc++ (which lacks move constructors for std streams).
+  // `stream_` is null in a moved-from `LogStreamer`; this is in fact how we
+  // recognize one to avoid logging when it is destroyed or reassigned.
+  std::unique_ptr<absl::strings_internal::OStringStream> stream_;
+};
+
+// LogInfoStreamer()
+//
+// Returns a LogStreamer that writes at level LogSeverity::kInfo.
+inline LogStreamer LogInfoStreamer(absl::string_view file, int line) {
+  return absl::LogStreamer(absl::LogSeverity::kInfo, file, line);
+}
+
+// LogWarningStreamer()
+//
+// Returns a LogStreamer that writes at level LogSeverity::kWarning.
+inline LogStreamer LogWarningStreamer(absl::string_view file, int line) {
+  return absl::LogStreamer(absl::LogSeverity::kWarning, file, line);
+}
+
+// LogErrorStreamer()
+//
+// Returns a LogStreamer that writes at level LogSeverity::kError.
+inline LogStreamer LogErrorStreamer(absl::string_view file, int line) {
+  return absl::LogStreamer(absl::LogSeverity::kError, file, line);
+}
+
+// LogFatalStreamer()
+//
+// Returns a LogStreamer that writes at level LogSeverity::kFatal.
+//
+// The program will be terminated when this `LogStreamer` is destroyed,
+// regardless of whether any data were streamed in.
+inline LogStreamer LogFatalStreamer(absl::string_view file, int line) {
+  return absl::LogStreamer(absl::LogSeverity::kFatal, file, line);
+}
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_LOG_LOG_STREAMER_H_
diff --git a/absl/log/log_streamer_test.cc b/absl/log/log_streamer_test.cc
new file mode 100644
index 0000000..d7beb5b
--- /dev/null
+++ b/absl/log/log_streamer_test.cc
@@ -0,0 +1,361 @@
+//
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/log_streamer.h"
+
+#include <iostream>
+#include <utility>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/attributes.h"
+#include "absl/base/internal/sysinfo.h"
+#include "absl/base/log_severity.h"
+#include "absl/log/internal/test_actions.h"
+#include "absl/log/internal/test_helpers.h"
+#include "absl/log/internal/test_matchers.h"
+#include "absl/log/log.h"
+#include "absl/log/scoped_mock_log.h"
+#include "absl/strings/string_view.h"
+
+namespace {
+using ::absl::log_internal::DeathTestExpectedLogging;
+using ::absl::log_internal::DeathTestUnexpectedLogging;
+using ::absl::log_internal::DeathTestValidateExpectations;
+#if GTEST_HAS_DEATH_TEST
+using ::absl::log_internal::DiedOfFatal;
+#endif
+using ::absl::log_internal::LogSeverity;
+using ::absl::log_internal::Prefix;
+using ::absl::log_internal::SourceFilename;
+using ::absl::log_internal::SourceLine;
+using ::absl::log_internal::Stacktrace;
+using ::absl::log_internal::TextMessage;
+using ::absl::log_internal::ThreadID;
+using ::absl::log_internal::TimestampInMatchWindow;
+using ::testing::AnyNumber;
+using ::testing::Eq;
+using ::testing::HasSubstr;
+using ::testing::IsEmpty;
+using ::testing::IsTrue;
+
+auto* test_env ABSL_ATTRIBUTE_UNUSED = ::testing::AddGlobalTestEnvironment(
+    new absl::log_internal::LogTestEnvironment);
+
+void WriteToStream(absl::string_view data, std::ostream* os) {
+  *os << "WriteToStream: " << data;
+}
+void WriteToStreamRef(absl::string_view data, std::ostream& os) {
+  os << "WriteToStreamRef: " << data;
+}
+
+TEST(LogStreamerTest, LogInfoStreamer) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
+                 Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kInfo)),
+                 TimestampInMatchWindow(),
+                 ThreadID(Eq(absl::base_internal::GetTID())),
+                 TextMessage(Eq("WriteToStream: foo")),
+                 ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                    str: "WriteToStream: foo"
+                                                  })pb")),
+                 Stacktrace(IsEmpty()))));
+
+  test_sink.StartCapturingLogs();
+  WriteToStream("foo", &absl::LogInfoStreamer("path/file.cc", 1234).stream());
+}
+
+TEST(LogStreamerTest, LogWarningStreamer) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
+                 Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kWarning)),
+                 TimestampInMatchWindow(),
+                 ThreadID(Eq(absl::base_internal::GetTID())),
+                 TextMessage(Eq("WriteToStream: foo")),
+                 ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                    str: "WriteToStream: foo"
+                                                  })pb")),
+                 Stacktrace(IsEmpty()))));
+
+  test_sink.StartCapturingLogs();
+  WriteToStream("foo",
+                &absl::LogWarningStreamer("path/file.cc", 1234).stream());
+}
+
+TEST(LogStreamerTest, LogErrorStreamer) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
+                 Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kError)),
+                 TimestampInMatchWindow(),
+                 ThreadID(Eq(absl::base_internal::GetTID())),
+                 TextMessage(Eq("WriteToStream: foo")),
+                 ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                    str: "WriteToStream: foo"
+                                                  })pb")),
+                 Stacktrace(IsEmpty()))));
+
+  test_sink.StartCapturingLogs();
+  WriteToStream("foo", &absl::LogErrorStreamer("path/file.cc", 1234).stream());
+}
+
+#if GTEST_HAS_DEATH_TEST
+TEST(LogStreamerDeathTest, LogFatalStreamer) {
+  EXPECT_EXIT(
+      {
+        absl::ScopedMockLog test_sink;
+
+        EXPECT_CALL(test_sink, Send)
+            .Times(AnyNumber())
+            .WillRepeatedly(DeathTestUnexpectedLogging());
+
+        EXPECT_CALL(
+            test_sink,
+            Send(AllOf(
+                SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
+                Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kFatal)),
+                TimestampInMatchWindow(),
+                ThreadID(Eq(absl::base_internal::GetTID())),
+                TextMessage(Eq("WriteToStream: foo")),
+                ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                   str: "WriteToStream: foo"
+                                                 })pb")))))
+            .WillOnce(DeathTestExpectedLogging());
+
+        test_sink.StartCapturingLogs();
+        WriteToStream("foo",
+                      &absl::LogFatalStreamer("path/file.cc", 1234).stream());
+      },
+      DiedOfFatal, DeathTestValidateExpectations());
+}
+#endif
+
+TEST(LogStreamerTest, LogStreamer) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
+                 Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kError)),
+                 TimestampInMatchWindow(),
+                 ThreadID(Eq(absl::base_internal::GetTID())),
+                 TextMessage(Eq("WriteToStream: foo")),
+                 ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                    str: "WriteToStream: foo"
+                                                  })pb")),
+                 Stacktrace(IsEmpty()))));
+
+  test_sink.StartCapturingLogs();
+  WriteToStream(
+      "foo", &absl::LogStreamer(absl::LogSeverity::kError, "path/file.cc", 1234)
+                  .stream());
+}
+
+#if GTEST_HAS_DEATH_TEST
+TEST(LogStreamerDeathTest, LogStreamer) {
+  EXPECT_EXIT(
+      {
+        absl::ScopedMockLog test_sink;
+
+        EXPECT_CALL(test_sink, Send)
+            .Times(AnyNumber())
+            .WillRepeatedly(DeathTestUnexpectedLogging());
+
+        EXPECT_CALL(
+            test_sink,
+            Send(AllOf(
+                SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
+                Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kFatal)),
+                TimestampInMatchWindow(),
+                ThreadID(Eq(absl::base_internal::GetTID())),
+                TextMessage(Eq("WriteToStream: foo")),
+                ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                   str: "WriteToStream: foo"
+                                                 })pb")))))
+            .WillOnce(DeathTestExpectedLogging());
+
+        test_sink.StartCapturingLogs();
+        WriteToStream("foo", &absl::LogStreamer(absl::LogSeverity::kFatal,
+                                                "path/file.cc", 1234)
+                                  .stream());
+      },
+      DiedOfFatal, DeathTestValidateExpectations());
+}
+#endif
+
+TEST(LogStreamerTest, PassedByReference) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
+                 TextMessage(Eq("WriteToStreamRef: foo")),
+                 ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                    str: "WriteToStreamRef: foo"
+                                                  })pb")),
+                 Stacktrace(IsEmpty()))));
+
+  test_sink.StartCapturingLogs();
+  WriteToStreamRef("foo", absl::LogInfoStreamer("path/file.cc", 1234).stream());
+}
+
+TEST(LogStreamerTest, StoredAsLocal) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  auto streamer = absl::LogInfoStreamer("path/file.cc", 1234);
+  WriteToStream("foo", &streamer.stream());
+  streamer.stream() << " ";
+  WriteToStreamRef("bar", streamer.stream());
+
+  // The call should happen when `streamer` goes out of scope; if it
+  // happened before this `EXPECT_CALL` the call would be unexpected and the
+  // test would fail.
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
+                 TextMessage(Eq("WriteToStream: foo WriteToStreamRef: bar")),
+                 ENCODED_MESSAGE(EqualsProto(
+                     R"pb(value {
+                            str: "WriteToStream: foo WriteToStreamRef: bar"
+                          })pb")),
+                 Stacktrace(IsEmpty()))));
+
+  test_sink.StartCapturingLogs();
+}
+
+#if GTEST_HAS_DEATH_TEST
+TEST(LogStreamerDeathTest, StoredAsLocal) {
+  EXPECT_EXIT(
+      {
+        // This is fatal when it goes out of scope, but not until then:
+        auto streamer = absl::LogFatalStreamer("path/file.cc", 1234);
+        std::cerr << "I'm still alive" << std::endl;
+        WriteToStream("foo", &streamer.stream());
+      },
+      DiedOfFatal, HasSubstr("I'm still alive"));
+}
+#endif
+
+TEST(LogStreamerTest, LogsEmptyLine) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(test_sink, Send(AllOf(SourceFilename(Eq("path/file.cc")),
+                                    SourceLine(Eq(1234)), TextMessage(Eq("")),
+                                    ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                                       str: ""
+                                                                     })pb")),
+                                    Stacktrace(IsEmpty()))));
+
+  test_sink.StartCapturingLogs();
+  absl::LogInfoStreamer("path/file.cc", 1234);
+}
+
+#if GTEST_HAS_DEATH_TEST
+TEST(LogStreamerDeathTest, LogsEmptyLine) {
+  EXPECT_EXIT(
+      {
+        absl::ScopedMockLog test_sink;
+
+        EXPECT_CALL(test_sink, Log)
+            .Times(AnyNumber())
+            .WillRepeatedly(DeathTestUnexpectedLogging());
+
+        EXPECT_CALL(
+            test_sink,
+            Send(AllOf(
+                SourceFilename(Eq("path/file.cc")), TextMessage(Eq("")),
+                ENCODED_MESSAGE(EqualsProto(R"pb(value { str: "" })pb")))))
+            .WillOnce(DeathTestExpectedLogging());
+
+        test_sink.StartCapturingLogs();
+        // This is fatal even though it's never used:
+        auto streamer = absl::LogFatalStreamer("path/file.cc", 1234);
+      },
+      DiedOfFatal, DeathTestValidateExpectations());
+}
+#endif
+
+TEST(LogStreamerTest, MoveConstruction) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
+          LogSeverity(Eq(absl::LogSeverity::kInfo)),
+          TextMessage(Eq("hello world")),
+          ENCODED_MESSAGE(EqualsProto(R"pb(value { str: "hello world" })pb")),
+          Stacktrace(IsEmpty()))));
+
+  test_sink.StartCapturingLogs();
+  auto streamer1 = absl::LogInfoStreamer("path/file.cc", 1234);
+  streamer1.stream() << "hello";
+  absl::LogStreamer streamer2(std::move(streamer1));
+  streamer2.stream() << " world";
+}
+
+TEST(LogStreamerTest, MoveAssignment) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
+                 LogSeverity(Eq(absl::LogSeverity::kInfo)),
+                 TextMessage(Eq("hello")),
+                 ENCODED_MESSAGE(EqualsProto(R"pb(value { str: "hello" })pb")),
+                 Stacktrace(IsEmpty()))));
+
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(SourceFilename(Eq("elsewhere/name.cc")), SourceLine(Eq(5678)),
+                 LogSeverity(Eq(absl::LogSeverity::kWarning)),
+                 TextMessage(Eq("world; goodbye")),
+                 ENCODED_MESSAGE(EqualsProto(R"pb(value {
+                                                    str: "world; goodbye"
+                                                  })pb")),
+                 Stacktrace(IsEmpty()))));
+
+  test_sink.StartCapturingLogs();
+  auto streamer1 = absl::LogInfoStreamer("path/file.cc", 1234);
+  streamer1.stream() << "hello";
+  auto streamer2 = absl::LogWarningStreamer("elsewhere/name.cc", 5678);
+  streamer2.stream() << "world";
+  streamer1 = std::move(streamer2);
+  streamer1.stream() << "; goodbye";
+}
+
+TEST(LogStreamerTest, CorrectDefaultFlags) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  // The `boolalpha` and `showbase` flags should be set by default, to match
+  // `LOG`.
+  EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq("false0xdeadbeef")))))
+      .Times(2);
+
+  test_sink.StartCapturingLogs();
+  absl::LogInfoStreamer("path/file.cc", 1234).stream()
+      << false << std::hex << 0xdeadbeef;
+  LOG(INFO) << false << std::hex << 0xdeadbeef;
+}
+
+}  // namespace
diff --git a/absl/log/scoped_mock_log.cc b/absl/log/scoped_mock_log.cc
new file mode 100644
index 0000000..4ebc0a9
--- /dev/null
+++ b/absl/log/scoped_mock_log.cc
@@ -0,0 +1,86 @@
+//
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/scoped_mock_log.h"
+
+#include <atomic>
+#include <string>
+
+#include "gmock/gmock.h"
+#include "absl/base/config.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/log/log_entry.h"
+#include "absl/log/log_sink.h"
+#include "absl/log/log_sink_registry.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+ScopedMockLog::ScopedMockLog(MockLogDefault default_exp)
+    : sink_(this), is_capturing_logs_(false) {
+  if (default_exp == MockLogDefault::kIgnoreUnexpected) {
+    // Ignore all calls to Log we did not set expectations for.
+    EXPECT_CALL(*this, Log).Times(::testing::AnyNumber());
+  } else {
+    // Disallow all calls to Log we did not set expectations for.
+    EXPECT_CALL(*this, Log).Times(0);
+  }
+  // By default Send mock forwards to Log mock.
+  EXPECT_CALL(*this, Send)
+      .Times(::testing::AnyNumber())
+      .WillRepeatedly([this](const absl::LogEntry& entry) {
+        is_triggered_.store(true, std::memory_order_relaxed);
+        Log(entry.log_severity(), std::string(entry.source_filename()),
+            std::string(entry.text_message()));
+      });
+
+  // By default We ignore all Flush calls.
+  EXPECT_CALL(*this, Flush).Times(::testing::AnyNumber());
+}
+
+ScopedMockLog::~ScopedMockLog() {
+  ABSL_RAW_CHECK(is_triggered_.load(std::memory_order_relaxed),
+                 "Did you forget to call StartCapturingLogs()?");
+
+  if (is_capturing_logs_) StopCapturingLogs();
+}
+
+void ScopedMockLog::StartCapturingLogs() {
+  ABSL_RAW_CHECK(!is_capturing_logs_,
+                 "StartCapturingLogs() can be called only when the "
+                 "absl::ScopedMockLog object is not capturing logs.");
+
+  is_capturing_logs_ = true;
+  is_triggered_.store(true, std::memory_order_relaxed);
+  absl::AddLogSink(&sink_);
+}
+
+void ScopedMockLog::StopCapturingLogs() {
+  ABSL_RAW_CHECK(is_capturing_logs_,
+                 "StopCapturingLogs() can be called only when the "
+                 "absl::ScopedMockLog object is capturing logs.");
+
+  is_capturing_logs_ = false;
+  absl::RemoveLogSink(&sink_);
+}
+
+absl::LogSink& ScopedMockLog::UseAsLocalSink() {
+  is_triggered_.store(true, std::memory_order_relaxed);
+  return sink_;
+}
+
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/log/scoped_mock_log.h b/absl/log/scoped_mock_log.h
new file mode 100644
index 0000000..44470c1
--- /dev/null
+++ b/absl/log/scoped_mock_log.h
@@ -0,0 +1,194 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/scoped_mock_log.h
+// -----------------------------------------------------------------------------
+//
+// This header declares `class absl::ScopedMockLog`, for use in testing.
+
+#ifndef ABSL_LOG_SCOPED_MOCK_LOG_H_
+#define ABSL_LOG_SCOPED_MOCK_LOG_H_
+
+#include <atomic>
+#include <string>
+
+#include "gmock/gmock.h"
+#include "absl/base/config.h"
+#include "absl/base/log_severity.h"
+#include "absl/log/log_entry.h"
+#include "absl/log/log_sink.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// MockLogDefault
+//
+// Controls how ScopedMockLog responds to unexpected calls by default.
+enum class MockLogDefault { kIgnoreUnexpected, kDisallowUnexpected };
+
+// ScopedMockLog
+//
+// ScopedMockLog is a LogSink that intercepts LOG() messages issued during its
+// lifespan.
+//
+// Using this together with GoogleTest, it's easy to test how a piece of code
+// calls LOG(). The typical usage, noting the distinction between
+// "uninteresting" and "unexpected", looks like this:
+//
+//   using ::testing::_;
+//   using ::testing::AnyNumber;
+//   using ::testing::EndsWith;
+//   using ::testing::kDoNotCaptureLogsYet;
+//   using ::testing::Lt;
+//
+//   TEST(FooTest, LogsCorrectly) {
+//     // Simple robust setup, ignores unexpected logs.
+//     absl::ScopedMockLog log;
+//
+//     // We expect the WARNING "Something bad!" exactly twice.
+//     EXPECT_CALL(log, Log(absl::LogSeverity::kWarning, _, "Something bad!"))
+//         .Times(2);
+//
+//     // But we want no messages from foo.cc.
+//     EXPECT_CALL(log, Log(_, EndsWith("/foo.cc"), _)).Times(0);
+//
+//     log.StartCapturingLogs();  // Call this after done setting expectations.
+//     Foo();  // Exercises the code under test.
+//   }
+//
+//   TEST(BarTest, LogsExactlyCorrectly) {
+//     // Strict checking, fails for unexpected logs.
+//     absl::ScopedMockLog log(absl::MockLogDefault::kDisallowUnexpected);
+//
+//     // ... but ignore low severity messages
+//     EXPECT_CALL(log, Log(Lt(absl::LogSeverity::kWarning), _, _))
+//         .Times(AnyNumber());
+//
+//     // We expect the ERROR "Something bad!" exactly once.
+//     EXPECT_CALL(log, Log(absl::LogSeverity::kError, EndsWith("/foo.cc"),
+//                 "Something bad!"))
+//         .Times(1);
+//
+//     log.StartCapturingLogs();  // Call this after done setting expectations.
+//     Bar();  // Exercises the code under test.
+//    }
+//
+// Note that in a multi-threaded environment, all LOG() messages from a single
+// thread will be handled in sequence, but that cannot be guaranteed for
+// messages from different threads. In fact, if the same or multiple
+// expectations are matched on two threads concurrently, their actions will be
+// executed concurrently as well and may interleave.
+class ScopedMockLog final {
+ public:
+  // ScopedMockLog::ScopedMockLog()
+  //
+  // Sets up the log and adds default expectations.
+  explicit ScopedMockLog(
+      MockLogDefault default_exp = MockLogDefault::kIgnoreUnexpected);
+  ScopedMockLog(const ScopedMockLog&) = delete;
+  ScopedMockLog& operator=(const ScopedMockLog&) = delete;
+
+  // ScopedMockLog::~ScopedMockLog()
+  //
+  // Stops intercepting logs and destroys this ScopedMockLog.
+  ~ScopedMockLog();
+
+  // ScopedMockLog::StartCapturingLogs()
+  //
+  // Starts log capturing if the object isn't already doing so. Otherwise
+  // crashes.
+  //
+  // Usually this method is called in the same thread that created this
+  // ScopedMockLog. It is the user's responsibility to not call this method if
+  // another thread may be calling it or StopCapturingLogs() at the same time.
+  // It is undefined behavior to add expectations while capturing logs is
+  // enabled.
+  void StartCapturingLogs();
+
+  // ScopedMockLog::StopCapturingLogs()
+  //
+  // Stops log capturing if the object is capturing logs. Otherwise crashes.
+  //
+  // Usually this method is called in the same thread that created this object.
+  // It is the user's responsibility to not call this method if another thread
+  // may be calling it or StartCapturingLogs() at the same time.
+  //
+  // It is UB to add expectations, while capturing logs is enabled.
+  void StopCapturingLogs();
+
+  // ScopedMockLog::UseAsLocalSink()
+  //
+  // Each `ScopedMockLog` is implemented with an `absl::LogSink`; this method
+  // returns a reference to that sink (e.g. for use with
+  // `LOG(...).ToSinkOnly()`) and marks the `ScopedMockLog` as having been used
+  // even if `StartCapturingLogs` is never called.
+  absl::LogSink& UseAsLocalSink();
+
+  // Implements the mock method:
+  //
+  //   void Log(LogSeverity severity, absl::string_view file_path,
+  //            absl::string_view message);
+  //
+  // The second argument to Log() is the full path of the source file in
+  // which the LOG() was issued.
+  //
+  // This is a shorthand form, which should be used by most users. Use the
+  // `Send` mock only if you want to add expectations for other log message
+  // attributes.
+  MOCK_METHOD(void, Log,
+              (absl::LogSeverity severity, const std::string& file_path,
+               const std::string& message));
+
+  // Implements the mock method:
+  //
+  //   void Send(const absl::LogEntry& entry);
+  //
+  // This is the most generic form of mock that can be specified. Use this mock
+  // only if you want to add expectations for log message attributes different
+  // from the log message text, log message path and log message severity.
+  //
+  // If no expectations are specified for this mock, the default action is to
+  // forward the call to the `Log` mock.
+  MOCK_METHOD(void, Send, (const absl::LogEntry&));
+
+  // Implements the mock method:
+  //
+  //   void Flush();
+  //
+  // Use this mock only if you want to add expectations for log flush calls.
+  MOCK_METHOD(void, Flush, ());
+
+ private:
+  class ForwardingSink final : public absl::LogSink {
+   public:
+    explicit ForwardingSink(ScopedMockLog* sml) : sml_(sml) {}
+    ForwardingSink(const ForwardingSink&) = delete;
+    ForwardingSink& operator=(const ForwardingSink&) = delete;
+    void Send(const absl::LogEntry& entry) override { sml_->Send(entry); }
+    void Flush() override { sml_->Flush(); }
+
+   private:
+    ScopedMockLog* sml_;
+  };
+
+  ForwardingSink sink_;
+  bool is_capturing_logs_;
+  std::atomic<bool> is_triggered_;
+};
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_LOG_SCOPED_MOCK_LOG_H_
diff --git a/absl/log/scoped_mock_log_test.cc b/absl/log/scoped_mock_log_test.cc
new file mode 100644
index 0000000..50689a0
--- /dev/null
+++ b/absl/log/scoped_mock_log_test.cc
@@ -0,0 +1,290 @@
+//
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/scoped_mock_log.h"
+
+#include <memory>
+#include <thread>  // NOLINT(build/c++11)
+
+#include "gmock/gmock.h"
+#include "gtest/gtest-spi.h"
+#include "gtest/gtest.h"
+#include "absl/base/attributes.h"
+#include "absl/base/log_severity.h"
+#include "absl/log/globals.h"
+#include "absl/log/internal/test_helpers.h"
+#include "absl/log/internal/test_matchers.h"
+#include "absl/log/log.h"
+#include "absl/memory/memory.h"
+#include "absl/strings/match.h"
+#include "absl/strings/string_view.h"
+#include "absl/synchronization/barrier.h"
+#include "absl/synchronization/notification.h"
+
+namespace {
+
+using ::testing::_;
+using ::testing::AnyNumber;
+using ::testing::Eq;
+using ::testing::HasSubstr;
+using ::testing::InSequence;
+using ::testing::Lt;
+using ::testing::Truly;
+using absl::log_internal::SourceBasename;
+using absl::log_internal::SourceFilename;
+using absl::log_internal::SourceLine;
+using absl::log_internal::TextMessageWithPrefix;
+using absl::log_internal::ThreadID;
+
+auto* test_env ABSL_ATTRIBUTE_UNUSED = ::testing::AddGlobalTestEnvironment(
+    new absl::log_internal::LogTestEnvironment);
+
+#if GTEST_HAS_DEATH_TEST
+TEST(ScopedMockLogDeathTest,
+     StartCapturingLogsCannotBeCalledWhenAlreadyCapturing) {
+  EXPECT_DEATH(
+      {
+        absl::ScopedMockLog log;
+        log.StartCapturingLogs();
+        log.StartCapturingLogs();
+      },
+      "StartCapturingLogs");
+}
+
+TEST(ScopedMockLogDeathTest, StopCapturingLogsCannotBeCalledWhenNotCapturing) {
+  EXPECT_DEATH(
+      {
+        absl::ScopedMockLog log;
+        log.StopCapturingLogs();
+      },
+      "StopCapturingLogs");
+}
+#endif
+
+// Tests that ScopedMockLog intercepts LOG()s when it's alive.
+TEST(ScopedMockLogTest, LogMockCatchAndMatchStrictExpectations) {
+  absl::ScopedMockLog log;
+
+  // The following expectations must match in the order they appear.
+  InSequence s;
+  EXPECT_CALL(log,
+              Log(absl::LogSeverity::kWarning, HasSubstr(__FILE__), "Danger."));
+  EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, _, "Working...")).Times(2);
+  EXPECT_CALL(log, Log(absl::LogSeverity::kError, _, "Bad!!"));
+
+  log.StartCapturingLogs();
+  LOG(WARNING) << "Danger.";
+  LOG(INFO) << "Working...";
+  LOG(INFO) << "Working...";
+  LOG(ERROR) << "Bad!!";
+}
+
+TEST(ScopedMockLogTest, LogMockCatchAndMatchSendExpectations) {
+  absl::ScopedMockLog log;
+
+  EXPECT_CALL(
+      log,
+      Send(AllOf(SourceFilename(Eq("/my/very/very/very_long_source_file.cc")),
+                 SourceBasename(Eq("very_long_source_file.cc")),
+                 SourceLine(Eq(777)), ThreadID(Eq(1234)),
+                 TextMessageWithPrefix(Truly([](absl::string_view msg) {
+                   return absl::EndsWith(
+                       msg, " very_long_source_file.cc:777] Info message");
+                 })))));
+
+  log.StartCapturingLogs();
+  LOG(INFO)
+          .AtLocation("/my/very/very/very_long_source_file.cc", 777)
+          .WithThreadID(1234)
+      << "Info message";
+}
+
+TEST(ScopedMockLogTest, ScopedMockLogCanBeNice) {
+  absl::ScopedMockLog log;
+
+  InSequence s;
+  EXPECT_CALL(log,
+              Log(absl::LogSeverity::kWarning, HasSubstr(__FILE__), "Danger."));
+  EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, _, "Working...")).Times(2);
+  EXPECT_CALL(log, Log(absl::LogSeverity::kError, _, "Bad!!"));
+
+  log.StartCapturingLogs();
+
+  // Any number of these are OK.
+  LOG(INFO) << "Info message.";
+  // Any number of these are OK.
+  LOG(WARNING).AtLocation("SomeOtherFile.cc", 100) << "Danger ";
+
+  LOG(WARNING) << "Danger.";
+
+  // Any number of these are OK.
+  LOG(INFO) << "Info message.";
+  // Any number of these are OK.
+  LOG(WARNING).AtLocation("SomeOtherFile.cc", 100) << "Danger ";
+
+  LOG(INFO) << "Working...";
+
+  // Any number of these are OK.
+  LOG(INFO) << "Info message.";
+  // Any number of these are OK.
+  LOG(WARNING).AtLocation("SomeOtherFile.cc", 100) << "Danger ";
+
+  LOG(INFO) << "Working...";
+
+  // Any number of these are OK.
+  LOG(INFO) << "Info message.";
+  // Any number of these are OK.
+  LOG(WARNING).AtLocation("SomeOtherFile.cc", 100) << "Danger ";
+
+  LOG(ERROR) << "Bad!!";
+
+  // Any number of these are OK.
+  LOG(INFO) << "Info message.";
+  // Any number of these are OK.
+  LOG(WARNING).AtLocation("SomeOtherFile.cc", 100) << "Danger ";
+}
+
+// Tests that ScopedMockLog generates a test failure if a message is logged
+// that is not expected (here, that means ERROR or FATAL).
+TEST(ScopedMockLogTest, RejectsUnexpectedLogs) {
+  EXPECT_NONFATAL_FAILURE(
+      {
+        absl::ScopedMockLog log(absl::MockLogDefault::kDisallowUnexpected);
+        // Any INFO and WARNING messages are permitted.
+        EXPECT_CALL(log, Log(Lt(absl::LogSeverity::kError), _, _))
+            .Times(AnyNumber());
+        log.StartCapturingLogs();
+        LOG(INFO) << "Ignored";
+        LOG(WARNING) << "Ignored";
+        LOG(ERROR) << "Should not be ignored";
+      },
+      "Should not be ignored");
+}
+
+TEST(ScopedMockLogTest, CapturesLogsAfterStartCapturingLogs) {
+  absl::SetStderrThreshold(absl::LogSeverityAtLeast::kInfinity);
+  absl::ScopedMockLog log;
+
+  // The ScopedMockLog object shouldn't see these LOGs, as it hasn't
+  // started capturing LOGs yet.
+  LOG(INFO) << "Ignored info";
+  LOG(WARNING) << "Ignored warning";
+  LOG(ERROR) << "Ignored error";
+
+  EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, _, "Expected info"));
+  log.StartCapturingLogs();
+
+  // Only this LOG will be seen by the ScopedMockLog.
+  LOG(INFO) << "Expected info";
+}
+
+TEST(ScopedMockLogTest, DoesNotCaptureLogsAfterStopCapturingLogs) {
+  absl::ScopedMockLog log;
+  EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, _, "Expected info"));
+
+  log.StartCapturingLogs();
+
+  // This LOG should be seen by the ScopedMockLog.
+  LOG(INFO) << "Expected info";
+
+  log.StopCapturingLogs();
+
+  // The ScopedMockLog object shouldn't see these LOGs, as it has
+  // stopped capturing LOGs.
+  LOG(INFO) << "Ignored info";
+  LOG(WARNING) << "Ignored warning";
+  LOG(ERROR) << "Ignored error";
+}
+
+// Tests that all messages are intercepted regardless of issuing thread. The
+// purpose of this test is NOT to exercise thread-safety.
+TEST(ScopedMockLogTest, LogFromMultipleThreads) {
+  absl::ScopedMockLog log;
+
+  // We don't establish an order to expectations here, since the threads may
+  // execute their log statements in different order.
+  EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, __FILE__, "Thread 1"));
+  EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, __FILE__, "Thread 2"));
+
+  log.StartCapturingLogs();
+
+  absl::Barrier barrier(2);
+  std::thread thread1([&barrier]() {
+    barrier.Block();
+    LOG(INFO) << "Thread 1";
+  });
+  std::thread thread2([&barrier]() {
+    barrier.Block();
+    LOG(INFO) << "Thread 2";
+  });
+
+  thread1.join();
+  thread2.join();
+}
+
+// Tests that no sequence will be imposed on two LOG message expectations from
+// different threads. This test would actually deadlock if replaced to two LOG
+// statements from the same thread.
+TEST(ScopedMockLogTest, NoSequenceWithMultipleThreads) {
+  absl::ScopedMockLog log;
+
+  absl::Barrier barrier(2);
+  EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, _, _))
+      .Times(2)
+      .WillRepeatedly([&barrier]() { barrier.Block(); });
+
+  log.StartCapturingLogs();
+
+  std::thread thread1([]() { LOG(INFO) << "Thread 1"; });
+  std::thread thread2([]() { LOG(INFO) << "Thread 2"; });
+
+  thread1.join();
+  thread2.join();
+}
+
+TEST(ScopedMockLogTsanTest,
+     ScopedMockLogCanBeDeletedWhenAnotherThreadIsLogging) {
+  auto log = absl::make_unique<absl::ScopedMockLog>();
+  EXPECT_CALL(*log, Log(absl::LogSeverity::kInfo, __FILE__, "Thread log"))
+      .Times(AnyNumber());
+
+  log->StartCapturingLogs();
+
+  absl::Notification logging_started;
+
+  std::thread thread([&logging_started]() {
+    for (int i = 0; i < 100; ++i) {
+      if (i == 50) logging_started.Notify();
+      LOG(INFO) << "Thread log";
+    }
+  });
+
+  logging_started.WaitForNotification();
+  log.reset();
+  thread.join();
+}
+
+TEST(ScopedMockLogTest, AsLocalSink) {
+  absl::ScopedMockLog log(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(log, Log(_, _, "two"));
+  EXPECT_CALL(log, Log(_, _, "three"));
+
+  LOG(INFO) << "one";
+  LOG(INFO).ToSinkOnly(&log.UseAsLocalSink()) << "two";
+  LOG(INFO).ToSinkAlso(&log.UseAsLocalSink()) << "three";
+}
+
+}  // namespace
diff --git a/absl/log/stripping_test.cc b/absl/log/stripping_test.cc
new file mode 100644
index 0000000..1672e3a
--- /dev/null
+++ b/absl/log/stripping_test.cc
@@ -0,0 +1,339 @@
+//
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Tests for stripping of literal strings.
+// ---------------------------------------
+//
+// When a `LOG` statement can be trivially proved at compile time to never fire,
+// e.g. due to `ABSL_MIN_LOG_LEVEL`, `NDEBUG`, or some explicit condition, data
+// streamed in can be dropped from the compiled program completely if they are
+// not used elsewhere.  This most commonly affects string literals, which users
+// often want to strip to reduce binary size and/or redact information about
+// their program's internals (e.g. in a release build).
+//
+// These tests log strings and then validate whether they appear in the compiled
+// binary.  This is done by opening the file corresponding to the running test
+// and running a simple string search on its contents.  The strings to be logged
+// and searched for must be unique, and we must take care not to emit them into
+// the binary in any other place, e.g. when searching for them.  The latter is
+// accomplished by computing them using base64; the source string appears in the
+// binary but the target string is computed at runtime.
+
+#include <stdio.h>
+
+#if defined(__MACH__)
+#include <mach-o/dyld.h>
+#elif defined(_WIN32)
+#include <Windows.h>
+#include <tchar.h>
+#endif
+
+#include <algorithm>
+#include <functional>
+#include <memory>
+#include <ostream>
+#include <string>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/internal/strerror.h"
+#include "absl/flags/internal/program_name.h"
+#include "absl/log/check.h"
+#include "absl/log/internal/test_helpers.h"
+#include "absl/log/log.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/string_view.h"
+
+namespace {
+using ::testing::_;
+using ::testing::Eq;
+using ::testing::NotNull;
+
+using absl::log_internal::kAbslMinLogLevel;
+
+std::string Base64UnescapeOrDie(absl::string_view data) {
+  std::string decoded;
+  CHECK(absl::Base64Unescape(data, &decoded));
+  return decoded;
+}
+
+// -----------------------------------------------------------------------------
+// A Googletest matcher which searches the running binary for a given string
+// -----------------------------------------------------------------------------
+
+// This matcher is used to validate that literal strings streamed into
+// `LOG` statements that ought to be compiled out (e.g. `LOG_IF(INFO, false)`)
+// do not appear in the binary.
+//
+// Note that passing the string to be sought directly to `FileHasSubstr()` all
+// but forces its inclusion in the binary regardless of the logging library's
+// behavior. For example:
+//
+//   LOG_IF(INFO, false) << "you're the man now dog";
+//   // This will always pass:
+//   // EXPECT_THAT(fp, FileHasSubstr("you're the man now dog"));
+//   // So use this instead:
+//   EXPECT_THAT(fp, FileHasSubstr(
+//       Base64UnescapeOrDie("eW91J3JlIHRoZSBtYW4gbm93IGRvZw==")));
+
+class FileHasSubstrMatcher final : public ::testing::MatcherInterface<FILE*> {
+ public:
+  explicit FileHasSubstrMatcher(absl::string_view needle) : needle_(needle) {}
+
+  bool MatchAndExplain(
+      FILE* fp, ::testing::MatchResultListener* listener) const override {
+    std::string buf(
+        std::max<std::string::size_type>(needle_.size() * 2, 163840000), '\0');
+    size_t buf_start_offset = 0;  // The file offset of the byte at `buf[0]`.
+    size_t buf_data_size = 0;     // The number of bytes of `buf` which contain
+                                  // data.
+
+    ::fseek(fp, 0, SEEK_SET);
+    while (true) {
+      // Fill the buffer to capacity or EOF:
+      while (buf_data_size < buf.size()) {
+        const size_t ret = fread(&buf[buf_data_size], sizeof(char),
+                                 buf.size() - buf_data_size, fp);
+        if (ret == 0) break;
+        buf_data_size += ret;
+      }
+      if (ferror(fp)) {
+        *listener << "error reading file";
+        return false;
+      }
+      const absl::string_view haystack(&buf[0], buf_data_size);
+      const auto off = haystack.find(needle_);
+      if (off != haystack.npos) {
+        *listener << "string found at offset " << buf_start_offset + off;
+        return true;
+      }
+      if (feof(fp)) {
+        *listener << "string not found";
+        return false;
+      }
+      // Copy the end of `buf` to the beginning so we catch matches that span
+      // buffer boundaries.  `buf` and `buf_data_size` are always large enough
+      // that these ranges don't overlap.
+      memcpy(&buf[0], &buf[buf_data_size - needle_.size()], needle_.size());
+      buf_start_offset += buf_data_size - needle_.size();
+      buf_data_size = needle_.size();
+    }
+  }
+  void DescribeTo(std::ostream* os) const override {
+    *os << "contains the string \"" << needle_ << "\" (base64(\""
+        << Base64UnescapeOrDie(needle_) << "\"))";
+  }
+
+  void DescribeNegationTo(std::ostream* os) const override {
+    *os << "does not ";
+    DescribeTo(os);
+  }
+
+ private:
+  std::string needle_;
+};
+
+class StrippingTest : public ::testing::Test {
+ protected:
+  void SetUp() override {
+#ifndef NDEBUG
+    // Non-optimized builds don't necessarily eliminate dead code at all, so we
+    // don't attempt to validate stripping against such builds.
+    GTEST_SKIP() << "StrippingTests skipped since this build is not optimized";
+#elif defined(__EMSCRIPTEN__)
+    // These tests require a way to examine the running binary and look for
+    // strings; there's no portable way to do that.
+    GTEST_SKIP()
+        << "StrippingTests skipped since this platform is not optimized";
+#endif
+  }
+
+  // Opens this program's executable file.  Returns `nullptr` and writes to
+  // `stderr` on failure.
+  std::unique_ptr<FILE, std::function<void(FILE*)>> OpenTestExecutable() {
+#if defined(__linux__)
+    std::unique_ptr<FILE, std::function<void(FILE*)>> fp(
+        fopen("/proc/self/exe", "rb"), [](FILE* fp) { fclose(fp); });
+    if (!fp) {
+      const std::string err = absl::base_internal::StrError(errno);
+      absl::FPrintF(stderr, "Failed to open /proc/self/exe: %s\n", err);
+    }
+    return fp;
+#elif defined(__Fuchsia__)
+    // TODO(b/242579714): We need to restore the test coverage on this platform.
+    std::unique_ptr<FILE, std::function<void(FILE*)>> fp(
+        fopen(absl::StrCat("/pkg/bin/",
+                           absl::flags_internal::ShortProgramInvocationName())
+                  .c_str(),
+              "rb"),
+        [](FILE* fp) { fclose(fp); });
+    if (!fp) {
+      const std::string err = absl::base_internal::StrError(errno);
+      absl::FPrintF(stderr, "Failed to open /pkg/bin/<binary name>: %s\n", err);
+    }
+    return fp;
+#elif defined(__MACH__)
+    uint32_t size = 0;
+    int ret = _NSGetExecutablePath(nullptr, &size);
+    if (ret != -1) {
+      absl::FPrintF(stderr,
+                    "Failed to get executable path: "
+                    "_NSGetExecutablePath(nullptr) returned %d\n",
+                    ret);
+      return nullptr;
+    }
+    std::string path(size, '\0');
+    ret = _NSGetExecutablePath(&path[0], &size);
+    if (ret != 0) {
+      absl::FPrintF(
+          stderr,
+          "Failed to get executable path: _NSGetExecutablePath(buffer) "
+          "returned %d\n",
+          ret);
+      return nullptr;
+    }
+    std::unique_ptr<FILE, std::function<void(FILE*)>> fp(
+        fopen(path.c_str(), "rb"), [](FILE* fp) { fclose(fp); });
+    if (!fp) {
+      const std::string err = absl::base_internal::StrError(errno);
+      absl::FPrintF(stderr, "Failed to open executable at %s: %s\n", path, err);
+    }
+    return fp;
+#elif defined(_WIN32)
+    std::basic_string<TCHAR> path(4096, _T('\0'));
+    while (true) {
+      const uint32_t ret = ::GetModuleFileName(nullptr, &path[0], path.size());
+      if (ret == 0) {
+        absl::FPrintF(
+            stderr,
+            "Failed to get executable path: GetModuleFileName(buffer) "
+            "returned 0\n");
+        return nullptr;
+      }
+      if (ret < path.size()) break;
+      path.resize(path.size() * 2, _T('\0'));
+    }
+    std::unique_ptr<FILE, std::function<void(FILE*)>> fp(
+        _tfopen(path.c_str(), "rb"), [](FILE* fp) { fclose(fp); });
+    if (!fp) absl::FPrintF(stderr, "Failed to open executable\n");
+    return fp;
+#else
+    absl::FPrintF(stderr,
+                  "OpenTestExecutable() unimplemented on this platform\n");
+    return nullptr;
+#endif
+  }
+
+  ::testing::Matcher<FILE*> FileHasSubstr(absl::string_view needle) {
+    return MakeMatcher(new FileHasSubstrMatcher(needle));
+  }
+};
+
+// This tests whether out methodology for testing stripping works on this
+// platform by looking for one string that definitely ought to be there and one
+// that definitely ought not to.  If this fails, none of the `StrippingTest`s
+// are going to produce meaningful results.
+TEST_F(StrippingTest, Control) {
+  constexpr char kEncodedPositiveControl[] =
+      "U3RyaXBwaW5nVGVzdC5Qb3NpdGl2ZUNvbnRyb2w=";
+  const std::string encoded_negative_control =
+      absl::Base64Escape("StrippingTest.NegativeControl");
+
+  // Verify this mainly so we can encode other strings and know definitely they
+  // won't encode to `kEncodedPositiveControl`.
+  EXPECT_THAT(Base64UnescapeOrDie("U3RyaXBwaW5nVGVzdC5Qb3NpdGl2ZUNvbnRyb2w="),
+              Eq("StrippingTest.PositiveControl"));
+
+  auto exe = OpenTestExecutable();
+  ASSERT_THAT(exe, NotNull());
+  EXPECT_THAT(exe.get(), FileHasSubstr(kEncodedPositiveControl));
+  EXPECT_THAT(exe.get(), Not(FileHasSubstr(encoded_negative_control)));
+}
+
+TEST_F(StrippingTest, Literal) {
+  // We need to load a copy of the needle string into memory (so we can search
+  // for it) without leaving it lying around in plaintext in the executable file
+  // as would happen if we used a literal.  We might (or might not) leave it
+  // lying around later; that's what the tests are for!
+  const std::string needle = absl::Base64Escape("StrippingTest.Literal");
+  LOG(INFO) << "U3RyaXBwaW5nVGVzdC5MaXRlcmFs";
+  auto exe = OpenTestExecutable();
+  ASSERT_THAT(exe, NotNull());
+  if (absl::LogSeverity::kInfo >= kAbslMinLogLevel) {
+    EXPECT_THAT(exe.get(), FileHasSubstr(needle));
+  } else {
+    EXPECT_THAT(exe.get(), Not(FileHasSubstr(needle)));
+  }
+}
+
+TEST_F(StrippingTest, LiteralInExpression) {
+  // We need to load a copy of the needle string into memory (so we can search
+  // for it) without leaving it lying around in plaintext in the executable file
+  // as would happen if we used a literal.  We might (or might not) leave it
+  // lying around later; that's what the tests are for!
+  const std::string needle =
+      absl::Base64Escape("StrippingTest.LiteralInExpression");
+  LOG(INFO) << absl::StrCat("secret: ",
+                            "U3RyaXBwaW5nVGVzdC5MaXRlcmFsSW5FeHByZXNzaW9u");
+  std::unique_ptr<FILE, std::function<void(FILE*)>> exe = OpenTestExecutable();
+  ASSERT_THAT(exe, NotNull());
+  if (absl::LogSeverity::kInfo >= kAbslMinLogLevel) {
+    EXPECT_THAT(exe.get(), FileHasSubstr(needle));
+  } else {
+    EXPECT_THAT(exe.get(), Not(FileHasSubstr(needle)));
+  }
+}
+
+TEST_F(StrippingTest, Fatal) {
+  // We need to load a copy of the needle string into memory (so we can search
+  // for it) without leaving it lying around in plaintext in the executable file
+  // as would happen if we used a literal.  We might (or might not) leave it
+  // lying around later; that's what the tests are for!
+  const std::string needle = absl::Base64Escape("StrippingTest.Fatal");
+  EXPECT_DEATH_IF_SUPPORTED(LOG(FATAL) << "U3RyaXBwaW5nVGVzdC5GYXRhbA==", "");
+  std::unique_ptr<FILE, std::function<void(FILE*)>> exe = OpenTestExecutable();
+  ASSERT_THAT(exe, NotNull());
+  if (absl::LogSeverity::kFatal >= kAbslMinLogLevel) {
+    EXPECT_THAT(exe.get(), FileHasSubstr(needle));
+  } else {
+    EXPECT_THAT(exe.get(), Not(FileHasSubstr(needle)));
+  }
+}
+
+TEST_F(StrippingTest, Level) {
+  const std::string needle = absl::Base64Escape("StrippingTest.Level");
+  volatile auto severity = absl::LogSeverity::kWarning;
+  // Ensure that `severity` is not a compile-time constant to prove that
+  // stripping works regardless:
+  LOG(LEVEL(severity)) << "U3RyaXBwaW5nVGVzdC5MZXZlbA==";
+  std::unique_ptr<FILE, std::function<void(FILE*)>> exe = OpenTestExecutable();
+  ASSERT_THAT(exe, NotNull());
+  if (absl::LogSeverity::kFatal >= kAbslMinLogLevel) {
+    // This can't be stripped at compile-time because it might evaluate to a
+    // level that shouldn't be stripped.
+    EXPECT_THAT(exe.get(), FileHasSubstr(needle));
+  } else {
+#if defined(_MSC_VER) || defined(__APPLE__)
+    // Dead code elimination misses this case.
+#else
+    // All levels should be stripped, so it doesn't matter what the severity
+    // winds up being.
+    EXPECT_THAT(exe.get(), Not(FileHasSubstr(needle)));
+#endif
+  }
+}
+
+}  // namespace