Add logging to internal error

Internal error call sites are propagated through the code, and might be
triggered multiple times in the course of a request, which makes them
difficult to track the source of.

This commit changes the internalError() method to include a print of
which invocation within bmcweb triggered the error, using c++20s
std::source_location mechanism.

Note:
clang-13 still doesn't implement std::source_location, so this commit
pulls source_location.hpp from lg2 to be able to support all compilers.

Tested:
Loaded in qemu, and added an internalError() call into systems.hpp for
the /redfish/v1/Systems handler.  Observed that
[CRITICAL "error_messages.cpp":234] Internal Error
../../../../../../workspace/sources/bmcweb/redfish-core/include/../lib/systems.hpp(2820:40)
`redfish::requestRoutesSystemsCollection(App&)::<lambda(const
crow::Request&, const std::shared_ptr<bmcweb::AsyncResp>&)>`:

Got printed to the bmcweb logs.

Signed-off-by: Ed Tanous <edtanous@google.com>
Change-Id: Ic1b4240422445357bc87404de814ad14f86b9edf
diff --git a/include/source_location.hpp b/include/source_location.hpp
new file mode 100644
index 0000000..9880752
--- /dev/null
+++ b/include/source_location.hpp
@@ -0,0 +1,27 @@
+#pragma once
+
+// As of clang-12, clang still doesn't support std::source_location, which
+// means that clang-tidy also doesn't support std::source_location.
+// Inside the libstdc++ implementation of <source_location> is this check of
+// __builtin_source_location to determine if the compiler supports the
+// necessary bits for std::source_location, and if not the header ends up doing
+// nothing.  Use this same builtin-check to detect when we're running under
+// an "older" clang and fallback to std::experimental::source_location instead.
+
+#if __has_builtin(__builtin_source_location)
+#include <source_location>
+
+namespace bmcweb
+{
+using source_location = std::source_location;
+}
+
+#else
+#include <experimental/source_location>
+
+namespace bmcweb
+{
+using source_location = std::experimental::source_location;
+}
+
+#endif
diff --git a/redfish-core/include/error_messages.hpp b/redfish-core/include/error_messages.hpp
index 3d11cc4..c9a919a 100644
--- a/redfish-core/include/error_messages.hpp
+++ b/redfish-core/include/error_messages.hpp
@@ -17,6 +17,7 @@
 #include "http_response.hpp"
 
 #include <nlohmann/json.hpp>
+#include <source_location.hpp>
 
 namespace redfish
 {
@@ -88,7 +89,8 @@
  * @returns Message InternalError formatted to JSON */
 nlohmann::json internalError();
 
-void internalError(crow::Response& res);
+void internalError(crow::Response& res, const bmcweb::source_location location =
+                                            bmcweb::source_location::current());
 
 /**
  * @brief Formats UnrecognizedRequestBody message into JSON
diff --git a/redfish-core/src/error_messages.cpp b/redfish-core/src/error_messages.cpp
index 9c28e8f..cb4d69c 100644
--- a/redfish-core/src/error_messages.cpp
+++ b/redfish-core/src/error_messages.cpp
@@ -229,8 +229,11 @@
                        "consider resetting the service."}};
 }
 
-void internalError(crow::Response& res)
+void internalError(crow::Response& res, const bmcweb::source_location location)
 {
+    BMCWEB_LOG_CRITICAL << "Internal Error " << location.file_name() << "("
+                        << location.line() << ":" << location.column() << ") `"
+                        << location.function_name() << "`: ";
     res.result(boost::beast::http::status::internal_server_error);
     addMessageToErrorJson(res.jsonValue, internalError());
 }