You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by zw...@apache.org on 2018/08/09 22:43:54 UTC

[trafficserver] 01/05: Collapses LogAccess and LogAccessHttp into LogAccess

This is an automated email from the ASF dual-hosted git repository.

zwoop pushed a commit to branch 8.0.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git

commit 988ab108bca8231a51561cc19b8cc981b0084bd7
Author: Randall Meyer <ra...@yahoo.com>
AuthorDate: Tue Jul 31 11:31:10 2018 -0700

    Collapses LogAccess and LogAccessHttp into LogAccess
    
    * make ProxyError::str inline so traffic_logstats/logcat doesn't need
      to pull in an even larger number of dependencies.
    
    (cherry picked from commit 9296bd984c76651730cd2256b2187908e3bd76f8)
---
 CMakeLists.txt                    |    2 -
 proxy/ProxyClientSession.cc       |   18 -
 proxy/ProxyClientSession.h        |   18 +-
 proxy/http/HttpBodyFactory.cc     |    7 +-
 proxy/http/HttpSM.cc              |    6 +-
 proxy/logging/Log.cc              |    7 -
 proxy/logging/Log.h               |    4 +-
 proxy/logging/LogAccess.cc        | 3138 +++++++++++++++++++++++++------------
 proxy/logging/LogAccess.h         |  301 ++--
 proxy/logging/LogAccessHttp.cc    | 1801 ---------------------
 proxy/logging/LogAccessHttp.h     |  222 ---
 proxy/logging/LogAccessTest.h     |    5 +-
 proxy/logging/Makefile.am         |    2 -
 src/traffic_logcat/Makefile.inc   |    1 +
 src/traffic_logstats/Makefile.inc |    1 +
 15 files changed, 2349 insertions(+), 3184 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3f1ee4f..6dd5719 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -878,8 +878,6 @@ add_executable(ats
         proxy/logging/Log.h
         proxy/logging/LogAccess.cc
         proxy/logging/LogAccess.h
-        proxy/logging/LogAccessHttp.cc
-        proxy/logging/LogAccessHttp.h
         proxy/logging/LogAccessTest.cc
         proxy/logging/LogAccessTest.h
         proxy/logging/LogBuffer.cc
diff --git a/proxy/ProxyClientSession.cc b/proxy/ProxyClientSession.cc
index e24f43b..2f80f3b 100644
--- a/proxy/ProxyClientSession.cc
+++ b/proxy/ProxyClientSession.cc
@@ -27,24 +27,6 @@
 
 static int64_t next_cs_id = 0;
 
-size_t
-ProxyError::str(char *buf, size_t buf_len)
-{
-  size_t len = 0;
-
-  if (this->cls == ProxyErrorClass::NONE) {
-    buf[0] = '-';
-    return 1;
-  }
-
-  buf[0] = (this->cls == ProxyErrorClass::SSN) ? 'S' : 'T';
-  ++len;
-
-  len += snprintf(buf + len, buf_len - len, "%" PRIx32, this->code);
-
-  return len;
-}
-
 ProxyClientSession::ProxyClientSession() : VConnection(nullptr)
 {
   ink_zero(this->user_args);
diff --git a/proxy/ProxyClientSession.h b/proxy/ProxyClientSession.h
index 1730ef7..e08162c 100644
--- a/proxy/ProxyClientSession.h
+++ b/proxy/ProxyClientSession.h
@@ -47,7 +47,23 @@ enum class ProxyErrorClass {
 struct ProxyError {
   ProxyError() {}
   ProxyError(ProxyErrorClass cl, uint32_t co) : cls(cl), code(co) {}
-  size_t str(char *buf, size_t buf_len);
+  size_t
+  str(char *buf, size_t buf_len) const
+  {
+    size_t len = 0;
+
+    if (this->cls == ProxyErrorClass::NONE) {
+      buf[0] = '-';
+      return 1;
+    }
+
+    buf[0] = (this->cls == ProxyErrorClass::SSN) ? 'S' : 'T';
+    ++len;
+
+    len += snprintf(buf + len, buf_len - len, "%" PRIx32, this->code);
+
+    return len;
+  }
 
   ProxyErrorClass cls = ProxyErrorClass::NONE;
   uint32_t code       = 0;
diff --git a/proxy/http/HttpBodyFactory.cc b/proxy/http/HttpBodyFactory.cc
index 5b73337..f5a61e5 100644
--- a/proxy/http/HttpBodyFactory.cc
+++ b/proxy/http/HttpBodyFactory.cc
@@ -37,9 +37,8 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include "URL.h"
-#include <logging/Log.h>
-#include <logging/LogAccess.h>
-#include <logging/LogAccessHttp.h>
+#include "logging/Log.h"
+#include "logging/LogAccess.h"
 #include "HttpCompat.h"
 #include "ts/I_Layout.h"
 
@@ -1049,7 +1048,7 @@ HttpBodyTemplate::build_instantiated_buffer(HttpTransact::State *context, int64_
 
   Debug("body_factory_instantiation", "    before instantiation: [%s]", template_buffer);
 
-  LogAccessHttp la(context->state_machine);
+  LogAccess la(context->state_machine);
 
   buffer = resolve_logfield_string(&la, template_buffer);
 
diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc
index b3f645f..8bb6317 100644
--- a/proxy/http/HttpSM.cc
+++ b/proxy/http/HttpSM.cc
@@ -33,7 +33,7 @@
 #include "P_Net.h"
 #include "StatPages.h"
 #include "Log.h"
-#include "LogAccessHttp.h"
+#include "LogAccess.h"
 #include "PluginVC.h"
 #include "ReverseProxy.h"
 #include "RemapProcessor.h"
@@ -6837,7 +6837,7 @@ HttpSM::kill_this()
     //////////////
     SMDebug("http_seq", "[HttpSM::update_stats] Logging transaction");
     if (Log::transaction_logging_enabled() && t_state.api_info.logging_enabled) {
-      LogAccessHttp accessor(this);
+      LogAccess accessor(this);
 
       int ret = Log::access(&accessor);
 
@@ -7576,7 +7576,7 @@ HttpSM::do_redirect()
   if (is_redirect_required()) {
     if (redirect_url != nullptr || t_state.hdr_info.client_response.field_find(MIME_FIELD_LOCATION, MIME_LEN_LOCATION)) {
       if (Log::transaction_logging_enabled() && t_state.api_info.logging_enabled) {
-        LogAccessHttp accessor(this);
+        LogAccess accessor(this);
         if (redirect_url == nullptr) {
           if (t_state.squid_codes.log_code == SQUID_LOG_TCP_HIT) {
             t_state.squid_codes.log_code = SQUID_LOG_TCP_HIT_REDIRECT;
diff --git a/proxy/logging/Log.cc b/proxy/logging/Log.cc
index c10d39c..930dcf2 100644
--- a/proxy/logging/Log.cc
+++ b/proxy/logging/Log.cc
@@ -864,13 +864,6 @@ Log::init_fields()
   global_field_list.add(field, false);
   ink_hash_table_insert(field_symbol_hash, "ctid", field);
 
-  Ptr<LogFieldAliasTable> entry_type_map = make_ptr(new LogFieldAliasTable);
-  entry_type_map->init(N_LOG_ENTRY_TYPES, LOG_ENTRY_HTTP, "LOG_ENTRY_HTTP");
-  field = new LogField("log_entry_type", "etype", LogField::sINT, &LogAccess::marshal_entry_type, &LogAccess::unmarshal_entry_type,
-                       make_alias_map(entry_type_map));
-  global_field_list.add(field, false);
-  ink_hash_table_insert(field_symbol_hash, "etype", field);
-
   init_status |= FIELDS_INITIALIZED;
 }
 
diff --git a/proxy/logging/Log.h b/proxy/logging/Log.h
index cdf0e56..5906d92 100644
--- a/proxy/logging/Log.h
+++ b/proxy/logging/Log.h
@@ -43,8 +43,8 @@
   @section example Example usage of the API
 
   @code
-  LogAccessHttpSM entry (this);
-  int ret = Log::access (&entry);
+  LogAccess entry(this);
+  int ret = Log::access(&entry);
   @endcode
 
 */
diff --git a/proxy/logging/LogAccess.cc b/proxy/logging/LogAccess.cc
index 505e60b..d9a2ca4 100644
--- a/proxy/logging/LogAccess.cc
+++ b/proxy/logging/LogAccess.cc
@@ -20,324 +20,1410 @@
   See the License for the specific language governing permissions and
   limitations under the License.
 
-  @section description
-  This file implements the LogAccess class.  However, LogAccess is an
-  abstract base class, providing an interface that logging uses to get
-  information from a module, such as HTTP.  Each module derives a
-  specific implementation from this base class (such as LogAccessHttp), and
-  implements the virtual accessor functions there.
-
-  The LogAccess class also defines a set of static functions that are used
-  to provide support for marshalling and unmarshalling support for the other
-  LogAccess derived classes.
  */
-#include "ts/ink_platform.h"
 
-#include "HTTP.h"
+#include "LogAccess.h"
 
-#include "P_Net.h"
-#include "P_Cache.h"
+#include "http/HttpSM.h"
+#include "MIME.h"
 #include "I_Machine.h"
-#include "LogAccess.h"
-#include "LogField.h"
-#include "LogFilter.h"
-#include "LogUtils.h"
 #include "LogFormat.h"
-#include "LogObject.h"
-#include "LogConfig.h"
 #include "LogBuffer.h"
-#include "Log.h"
 
 char INVALID_STR[] = "!INVALID_STR!";
 
-#define LOG_ACCESS_DEFAULT_FIELD(name, impl) \
-  int LogAccess::name(char *buf) { impl; }
-/*-------------------------------------------------------------------------
-  LogAccess::init
-  -------------------------------------------------------------------------*/
+#define HIDDEN_CONTENT_TYPE "@Content-Type"
+#define HIDDEN_CONTENT_TYPE_LEN 13
 
-void
-LogAccess::init()
+// should be at least 22 bytes to always accommodate a converted
+// MgmtInt, MgmtIntCounter or  MgmtFloat. 22 bytes is enough for 64 bit
+// ints + sign + eos, and enough for %e floating point representation
+// + eos
+//
+#define MARSHAL_RECORD_LENGTH 32
+
+/*-------------------------------------------------------------------------
+  LogAccess
+
+  Initialize the private data members and assert that we got a valid state
+  machine pointer.
+  -------------------------------------------------------------------------*/
+
+LogAccess::LogAccess(HttpSM *sm)
+  : m_http_sm(sm),
+    m_arena(),
+    m_client_request(nullptr),
+    m_proxy_response(nullptr),
+    m_proxy_request(nullptr),
+    m_server_response(nullptr),
+    m_cache_response(nullptr),
+    m_client_req_url_str(nullptr),
+    m_client_req_url_len(0),
+    m_client_req_url_canon_str(nullptr),
+    m_client_req_url_canon_len(0),
+    m_client_req_unmapped_url_canon_str(nullptr),
+    m_client_req_unmapped_url_canon_len(0),
+    m_client_req_unmapped_url_path_str(nullptr),
+    m_client_req_unmapped_url_path_len(0),
+    m_client_req_unmapped_url_host_str(nullptr),
+    m_client_req_unmapped_url_host_len(0),
+    m_client_req_url_path_str(nullptr),
+    m_client_req_url_path_len(0),
+    m_proxy_resp_content_type_str(nullptr),
+    m_proxy_resp_content_type_len(0),
+    m_proxy_resp_reason_phrase_str(nullptr),
+    m_proxy_resp_reason_phrase_len(0),
+    m_cache_lookup_url_canon_str(nullptr),
+    m_cache_lookup_url_canon_len(0)
 {
-  if (initialized) {
-    return;
-  }
-  //
-  // Here is where we would perform any initialization code.
-  //
-
-  initialized = true;
+  ink_assert(m_http_sm != nullptr);
 }
 
 /*-------------------------------------------------------------------------
-  The following functions provide a default implementation for the base
-  class marshalling routines so that each subsequent LogAccess* class only
-  has to implement those functions that are to override this default
-  implementation.
-  -------------------------------------------------------------------------*/
-
-LOG_ACCESS_DEFAULT_FIELD(marshal_plugin_identity_id, DEFAULT_INT_FIELD)
-
-LOG_ACCESS_DEFAULT_FIELD(marshal_plugin_identity_tag, DEFAULT_STR_FIELD)
-
-LOG_ACCESS_DEFAULT_FIELD(marshal_client_host_ip, DEFAULT_IP_FIELD)
-
-LOG_ACCESS_DEFAULT_FIELD(marshal_host_interface_ip, DEFAULT_IP_FIELD)
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-LOG_ACCESS_DEFAULT_FIELD(marshal_cache_lookup_url_canon, DEFAULT_STR_FIELD)
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-LOG_ACCESS_DEFAULT_FIELD(marshal_client_host_port, DEFAULT_INT_FIELD)
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-LOG_ACCESS_DEFAULT_FIELD(marshal_client_auth_user_name, DEFAULT_STR_FIELD)
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-LOG_ACCESS_DEFAULT_FIELD(marshal_client_req_text, DEFAULT_STR_FIELD)
-
-/*-------------------------------------------------------------------------
+  LogAccess::init
   -------------------------------------------------------------------------*/
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_client_req_http_method, DEFAULT_STR_FIELD)
+void
+LogAccess::init()
+{
+  HttpTransact::HeaderInfo *hdr = &(m_http_sm->t_state.hdr_info);
 
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
+  if (hdr->client_request.valid()) {
+    m_client_request = &(hdr->client_request);
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_client_req_url, DEFAULT_STR_FIELD)
+    // make a copy of the incoming url into the arena
+    const char *url_string_ref = m_client_request->url_string_get_ref(&m_client_req_url_len);
+    m_client_req_url_str       = m_arena.str_alloc(m_client_req_url_len + 1);
+    memcpy(m_client_req_url_str, url_string_ref, m_client_req_url_len);
+    m_client_req_url_str[m_client_req_url_len] = '\0';
 
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
+    m_client_req_url_canon_str =
+      LogUtils::escapify_url(&m_arena, m_client_req_url_str, m_client_req_url_len, &m_client_req_url_canon_len);
+    m_client_req_url_path_str = m_client_request->path_get(&m_client_req_url_path_len);
+  }
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_client_req_url_canon, DEFAULT_STR_FIELD)
+  if (hdr->client_response.valid()) {
+    m_proxy_response = &(hdr->client_response);
+    MIMEField *field = m_proxy_response->field_find(MIME_FIELD_CONTENT_TYPE, MIME_LEN_CONTENT_TYPE);
+    if (field) {
+      m_proxy_resp_content_type_str = (char *)field->value_get(&m_proxy_resp_content_type_len);
 
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
+      LogUtils::remove_content_type_attributes(m_proxy_resp_content_type_str, &m_proxy_resp_content_type_len);
+    } else {
+      // If Content-Type field is missing, check for @Content-Type
+      field = m_proxy_response->field_find(HIDDEN_CONTENT_TYPE, HIDDEN_CONTENT_TYPE_LEN);
+      if (field) {
+        m_proxy_resp_content_type_str = (char *)field->value_get(&m_proxy_resp_content_type_len);
+        LogUtils::remove_content_type_attributes(m_proxy_resp_content_type_str, &m_proxy_resp_content_type_len);
+      }
+    }
+    m_proxy_resp_reason_phrase_str = (char *)m_proxy_response->reason_get(&m_proxy_resp_reason_phrase_len);
+  }
+  if (hdr->server_request.valid()) {
+    m_proxy_request = &(hdr->server_request);
+  }
+  if (hdr->server_response.valid()) {
+    m_server_response = &(hdr->server_response);
+  }
+  if (hdr->cache_response.valid()) {
+    m_cache_response = &(hdr->cache_response);
+  }
+}
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_client_req_unmapped_url_canon, DEFAULT_STR_FIELD)
+int
+LogAccess::marshal_proxy_host_name(char *buf)
+{
+  char *str        = nullptr;
+  int len          = 0;
+  Machine *machine = Machine::instance();
 
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
+  if (machine) {
+    str = machine->hostname;
+  }
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_client_req_unmapped_url_path, DEFAULT_STR_FIELD)
+  len = LogAccess::strlen(str);
 
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
+  if (buf) {
+    marshal_str(buf, str, len);
+  }
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_client_req_unmapped_url_host, DEFAULT_STR_FIELD)
+  return len;
+}
 
 /*-------------------------------------------------------------------------
   -------------------------------------------------------------------------*/
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_client_req_url_path, DEFAULT_STR_FIELD)
+int
+LogAccess::marshal_proxy_host_ip(char *buf)
+{
+  return marshal_ip(buf, &Machine::instance()->ip.sa);
+}
 
 /*-------------------------------------------------------------------------
   -------------------------------------------------------------------------*/
+int
+LogAccess::marshal_process_uuid(char *buf)
+{
+  int len = round_strlen(TS_UUID_STRING_LEN + 1);
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_client_req_url_scheme, DEFAULT_STR_FIELD)
+  if (buf) {
+    const char *str = (char *)Machine::instance()->uuid.getString();
+    marshal_str(buf, str, len);
+  }
+  return len;
+}
 
 /*-------------------------------------------------------------------------
-  This case is special because it really stores 2 ints.
   -------------------------------------------------------------------------*/
 
 int
-LogAccess::marshal_client_req_http_version(char *buf)
+LogAccess::marshal_config_int_var(char *config_var, char *buf)
 {
   if (buf) {
-    int64_t major = 0;
-    int64_t minor = 0;
-    marshal_int(buf, major);
-    marshal_int((buf + INK_MIN_ALIGN), minor);
+    int64_t val = (int64_t)REC_ConfigReadInteger(config_var);
+    marshal_int(buf, val);
   }
-  return (2 * INK_MIN_ALIGN);
+  return INK_MIN_ALIGN;
 }
 
 /*-------------------------------------------------------------------------
   -------------------------------------------------------------------------*/
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_client_req_protocol_version, DEFAULT_STR_FIELD)
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
+int
+LogAccess::marshal_config_str_var(char *config_var, char *buf)
+{
+  char *str = nullptr;
+  str       = REC_ConfigReadString(config_var);
+  int len   = LogAccess::strlen(str);
+  if (buf) {
+    marshal_str(buf, str, len);
+  }
+  ats_free(str);
+  return len;
+}
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_client_req_header_len, DEFAULT_INT_FIELD)
+// To allow for a generic marshal_record function, rather than
+// multiple functions (one per data type) we always marshal a record
+// as a string of a fixed length.  We use a fixed length because the
+// marshal_record function can be called with a null *buf to request
+// the length of the record, and later with a non-null *buf to
+// actually request the record to be inserted in the buffer, and both
+// calls should return the same number of characters. If we did not
+// enforce a fixed size, this would not necessarily be the case
+// because records --statistics in particular-- can potentially change
+// between one call and the other.
+//
+int
+LogAccess::marshal_record(char *record, char *buf)
+{
+  const unsigned int max_chars = MARSHAL_RECORD_LENGTH;
 
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
+  if (nullptr == buf) {
+    return max_chars;
+  }
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_client_req_content_len, DEFAULT_INT_FIELD)
+  const char *record_not_found_msg          = "RECORD_NOT_FOUND";
+  const unsigned int record_not_found_chars = ::strlen(record_not_found_msg) + 1;
 
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
+  char ascii_buf[max_chars];
+  const char *out_buf;
+  unsigned int num_chars;
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_client_req_tcp_reused, DEFAULT_INT_FIELD)
+#define LOG_INTEGER RECD_INT
+#define LOG_COUNTER RECD_COUNTER
+#define LOG_FLOAT RECD_FLOAT
+#define LOG_STRING RECD_STRING
 
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
+  RecDataT stype = RECD_NULL;
+  bool found     = false;
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_client_req_is_ssl, DEFAULT_INT_FIELD)
+  if (RecGetRecordDataType(record, &stype) != REC_ERR_OKAY) {
+    out_buf   = "INVALID_RECORD";
+    num_chars = ::strlen(out_buf) + 1;
+  } else {
+    if (LOG_INTEGER == stype || LOG_COUNTER == stype) {
+      // we assume MgmtInt and MgmtIntCounter are int64_t for the
+      // conversion below, if this ever changes we should modify
+      // accordingly
+      //
+      ink_assert(sizeof(int64_t) >= sizeof(RecInt) && sizeof(int64_t) >= sizeof(RecCounter));
 
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
+      // so that a 64 bit integer will fit (including sign and eos)
+      //
+      ink_assert(max_chars > 21);
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_client_req_ssl_reused, DEFAULT_INT_FIELD)
+      int64_t val = (int64_t)(LOG_INTEGER == stype ? REC_readInteger(record, &found) : REC_readCounter(record, &found));
 
-/*-------------------------------------------------------------------------
--------------------------------------------------------------------------*/
+      if (found) {
+        out_buf = int64_to_str(ascii_buf, max_chars, val, &num_chars);
+        ink_assert(out_buf);
+      } else {
+        out_buf   = (char *)record_not_found_msg;
+        num_chars = record_not_found_chars;
+      }
+    } else if (LOG_FLOAT == stype) {
+      // we assume MgmtFloat is at least a float for the conversion below
+      // (the conversion itself assumes a double because of the %e)
+      // if this ever changes we should modify accordingly
+      //
+      ink_assert(sizeof(double) >= sizeof(RecFloat));
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_client_security_protocol, DEFAULT_STR_FIELD)
+      RecFloat val = REC_readFloat(record, &found);
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_client_security_cipher_suite, DEFAULT_STR_FIELD)
+      if (found) {
+        // snprintf does not support "%e" in the format
+        // and we want to use "%e" because it is the most concise
+        // notation
 
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
+        num_chars = snprintf(ascii_buf, sizeof(ascii_buf), "%e", val) + 1; // include eos
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_client_finish_status_code, DEFAULT_INT_FIELD)
+        // the "%e" field above should take 13 characters at most
+        //
+        ink_assert(num_chars <= max_chars);
 
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
+        // the following should never be true
+        //
+        if (num_chars > max_chars) {
+          // data does not fit, output asterisks
+          out_buf   = "***";
+          num_chars = ::strlen(out_buf) + 1;
+        } else {
+          out_buf = ascii_buf;
+        }
+      } else {
+        out_buf   = (char *)record_not_found_msg;
+        num_chars = record_not_found_chars;
+      }
+    } else if (LOG_STRING == stype) {
+      out_buf = REC_readString(record, &found);
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_client_req_id, DEFAULT_INT_FIELD)
+      if (found) {
+        if (out_buf != nullptr && out_buf[0] != 0) {
+          num_chars = ::strlen(out_buf) + 1;
+          if (num_chars > max_chars) {
+            // truncate string and write ellipsis at the end
+            memcpy(ascii_buf, out_buf, max_chars - 4);
+            ascii_buf[max_chars - 1] = 0;
+            ascii_buf[max_chars - 2] = '.';
+            ascii_buf[max_chars - 3] = '.';
+            ascii_buf[max_chars - 4] = '.';
+            out_buf                  = ascii_buf;
+            num_chars                = max_chars;
+          }
+        } else {
+          out_buf   = "NULL";
+          num_chars = ::strlen(out_buf) + 1;
+        }
+      } else {
+        out_buf   = (char *)record_not_found_msg;
+        num_chars = record_not_found_chars;
+      }
+    } else {
+      out_buf   = "INVALID_MgmtType";
+      num_chars = ::strlen(out_buf) + 1;
+      ink_assert(!"invalid MgmtType for requested record");
+    }
+  }
 
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
+  ink_assert(num_chars <= max_chars);
+  memcpy(buf, out_buf, num_chars);
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_client_req_uuid, DEFAULT_STR_FIELD)
+  return max_chars;
+}
 
 /*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-LOG_ACCESS_DEFAULT_FIELD(marshal_client_rx_error_code, DEFAULT_STR_FIELD)
-LOG_ACCESS_DEFAULT_FIELD(marshal_client_tx_error_code, DEFAULT_STR_FIELD)
+  LogAccess::marshal_str
 
-/*-------------------------------------------------------------------------
+  Copy the given string to the destination buffer, including the trailing
+  NULL.  For binary formatting, we need the NULL to distinguish the end of
+  the string, and we'll remove it for ascii formatting.
+  ASSUMES dest IS NOT NULL.
+  The array pointed to by dest must be at least padded_len in length.
   -------------------------------------------------------------------------*/
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_client_req_timestamp_sec, DEFAULT_INT_FIELD)
-LOG_ACCESS_DEFAULT_FIELD(marshal_client_req_timestamp_ms, DEFAULT_INT_FIELD)
+void
+LogAccess::marshal_str(char *dest, const char *source, int padded_len)
+{
+  if (source == nullptr || source[0] == 0 || padded_len == 0) {
+    source = DEFAULT_STR;
+  }
+  ink_strlcpy(dest, source, padded_len);
+
+#ifdef DEBUG
+  //
+  // what padded_len should be, if there is no padding, is strlen()+1.
+  // if not, then we needed to pad and should touch the intermediate
+  // bytes to avoid UMR errors when the buffer is written.
+  //
+  size_t real_len = (::strlen(source) + 1);
+  while ((int)real_len < padded_len) {
+    dest[real_len] = '$';
+    real_len++;
+  }
+#endif
+}
+
+/*-------------------------------------------------------------------------
+  LogAccess::marshal_mem
+
+  This is a version of marshal_str that works with unterminated strings.
+  In this case, we'll copy the buffer and then add a trailing null that
+  the rest of the system assumes.
+  -------------------------------------------------------------------------*/
+
+void
+LogAccess::marshal_mem(char *dest, const char *source, int actual_len, int padded_len)
+{
+  if (source == nullptr || source[0] == 0 || actual_len == 0) {
+    source     = DEFAULT_STR;
+    actual_len = DEFAULT_STR_LEN;
+    ink_assert(actual_len < padded_len);
+  }
+  memcpy(dest, source, actual_len);
+  dest[actual_len] = 0; // add terminating null
+
+#ifdef DEBUG
+  //
+  // what len should be, if there is no padding, is strlen()+1.
+  // if not, then we needed to pad and should touch the intermediate
+  // bytes to avoid UMR errors when the buffer is written.
+  //
+  int real_len = actual_len + 1;
+  while (real_len < padded_len) {
+    dest[real_len] = '$';
+    real_len++;
+  }
+#endif
+}
+
+/*-------------------------------------------------------------------------
+  LogAccess::marshal_ip
+
+  Marshal an IP address in a reasonably compact way. If the address isn't
+  valid (NULL or not IP) then marshal an invalid address record.
+  -------------------------------------------------------------------------*/
+
+int
+LogAccess::marshal_ip(char *dest, sockaddr const *ip)
+{
+  LogFieldIpStorage data;
+  int len = sizeof(data._ip);
+  if (nullptr == ip) {
+    data._ip._family = AF_UNSPEC;
+  } else if (ats_is_ip4(ip)) {
+    if (dest) {
+      data._ip4._family = AF_INET;
+      data._ip4._addr   = ats_ip4_addr_cast(ip);
+    }
+    len = sizeof(data._ip4);
+  } else if (ats_is_ip6(ip)) {
+    if (dest) {
+      data._ip6._family = AF_INET6;
+      data._ip6._addr   = ats_ip6_addr_cast(ip);
+    }
+    len = sizeof(data._ip6);
+  } else {
+    data._ip._family = AF_UNSPEC;
+  }
+
+  if (dest) {
+    memcpy(dest, &data, len);
+  }
+  return INK_ALIGN_DEFAULT(len);
+}
+
+inline int
+LogAccess::unmarshal_with_map(int64_t code, char *dest, int len, Ptr<LogFieldAliasMap> map, const char *msg)
+{
+  long int codeStrLen = 0;
+
+  switch (map->asString(code, dest, len, (size_t *)&codeStrLen)) {
+  case LogFieldAliasMap::INVALID_INT:
+    if (msg) {
+      const int bufSize = 64;
+      char invalidCodeMsg[bufSize];
+      codeStrLen = snprintf(invalidCodeMsg, 64, "%s(%" PRId64 ")", msg, code);
+      if (codeStrLen < bufSize && codeStrLen < len) {
+        ink_strlcpy(dest, invalidCodeMsg, len);
+      } else {
+        codeStrLen = -1;
+      }
+    } else {
+      codeStrLen = -1;
+    }
+    break;
+  case LogFieldAliasMap::BUFFER_TOO_SMALL:
+    codeStrLen = -1;
+    break;
+  }
+
+  return codeStrLen;
+}
+
+/*-------------------------------------------------------------------------
+  LogAccess::unmarshal_int
+
+  Return the integer pointed at by the buffer and advance the buffer
+  pointer past the int.  The int will be converted back to host byte order.
+  -------------------------------------------------------------------------*/
+
+int64_t
+LogAccess::unmarshal_int(char **buf)
+{
+  ink_assert(buf != nullptr);
+  ink_assert(*buf != nullptr);
+  int64_t val;
+
+  // TODO: this used to do nthol, do we need to worrry? TS-1156.
+  val = *((int64_t *)(*buf));
+  *buf += INK_MIN_ALIGN;
+  return val;
+}
+
+/*-------------------------------------------------------------------------
+  unmarshal_itoa
+
+  This routine provides a fast conversion from a binary int to a string.
+  It returns the number of characters formatted.  "dest" must point to the
+  LAST character of an array large enough to store the complete formatted
+  number.
+  -------------------------------------------------------------------------*/
+
+int
+LogAccess::unmarshal_itoa(int64_t val, char *dest, int field_width, char leading_char)
+{
+  ink_assert(dest != nullptr);
+
+  char *p = dest;
+
+  if (val <= 0) {
+    *p-- = '0';
+    while (dest - p < field_width) {
+      *p-- = leading_char;
+    }
+    return (int)(dest - p);
+  }
+
+  while (val) {
+    *p-- = '0' + (val % 10);
+    val /= 10;
+  }
+  while (dest - p < field_width) {
+    *p-- = leading_char;
+  }
+  return (int)(dest - p);
+}
+
+/*-------------------------------------------------------------------------
+  unmarshal_itox
+
+  This routine provides a fast conversion from a binary int to a hex string.
+  It returns the number of characters formatted.  "dest" must point to the
+  LAST character of an array large enough to store the complete formatted
+  number.
+  -------------------------------------------------------------------------*/
+
+int
+LogAccess::unmarshal_itox(int64_t val, char *dest, int field_width, char leading_char)
+{
+  ink_assert(dest != nullptr);
+
+  char *p             = dest;
+  static char table[] = "0123456789abcdef?";
+
+  for (int i = 0; i < (int)(sizeof(int64_t) * 2); i++) {
+    *p-- = table[val & 0xf];
+    val >>= 4;
+  }
+  while (dest - p < field_width) {
+    *p-- = leading_char;
+  }
+
+  return (int64_t)(dest - p);
+}
+
+/*-------------------------------------------------------------------------
+  LogAccess::unmarshal_int_to_str
+
+  Return the string representation of the integer pointed at by buf.
+  -------------------------------------------------------------------------*/
+
+int
+LogAccess::unmarshal_int_to_str(char **buf, char *dest, int len)
+{
+  ink_assert(buf != nullptr);
+  ink_assert(*buf != nullptr);
+  ink_assert(dest != nullptr);
+
+  char val_buf[128];
+  int64_t val = unmarshal_int(buf);
+  int val_len = unmarshal_itoa(val, val_buf + 127);
+
+  if (val_len < len) {
+    memcpy(dest, val_buf + 128 - val_len, val_len);
+    return val_len;
+  }
+  return -1;
+}
+
+/*-------------------------------------------------------------------------
+  LogAccess::unmarshal_int_to_str_hex
+
+  Return the string representation (hexadecimal) of the integer pointed at by buf.
+  -------------------------------------------------------------------------*/
+
+int
+LogAccess::unmarshal_int_to_str_hex(char **buf, char *dest, int len)
+{
+  ink_assert(buf != nullptr);
+  ink_assert(*buf != nullptr);
+  ink_assert(dest != nullptr);
+
+  char val_buf[128];
+  int64_t val = unmarshal_int(buf);
+  int val_len = unmarshal_itox(val, val_buf + 127);
+
+  if (val_len < len) {
+    memcpy(dest, val_buf + 128 - val_len, val_len);
+    return val_len;
+  }
+  return -1;
+}
+
+/*-------------------------------------------------------------------------
+  LogAccess::unmarshal_str
+
+  Retrieve the string from the location pointed at by the buffer and
+  advance the pointer past the string.  The local strlen function is used
+  to advance the pointer, thus matching the corresponding strlen that was
+  used to lay the string into the buffer.
+  -------------------------------------------------------------------------*/
+
+int
+LogAccess::unmarshal_str(char **buf, char *dest, int len, LogSlice *slice)
+{
+  ink_assert(buf != nullptr);
+  ink_assert(*buf != nullptr);
+  ink_assert(dest != nullptr);
+
+  char *val_buf = *buf;
+  int val_len   = (int)::strlen(val_buf);
+
+  *buf += LogAccess::strlen(val_buf); // this is how it was stored
+
+  if (slice && slice->m_enable) {
+    int offset, n;
+
+    n = slice->toStrOffset(val_len, &offset);
+    if (n <= 0) {
+      return 0;
+    }
+
+    if (n >= len) {
+      return -1;
+    }
+
+    memcpy(dest, (val_buf + offset), n);
+    return n;
+  }
+
+  if (val_len < len) {
+    memcpy(dest, val_buf, val_len);
+    return val_len;
+  }
+  return -1;
+}
+
+int
+LogAccess::unmarshal_ttmsf(char **buf, char *dest, int len)
+{
+  ink_assert(buf != nullptr);
+  ink_assert(*buf != nullptr);
+  ink_assert(dest != nullptr);
+
+  int64_t val = unmarshal_int(buf);
+  double secs = (double)val / 1000;
+  int val_len = snprintf(dest, len, "%.3f", secs);
+  return val_len;
+}
+
+int
+LogAccess::unmarshal_int_to_date_str(char **buf, char *dest, int len)
+{
+  ink_assert(buf != nullptr);
+  ink_assert(*buf != nullptr);
+  ink_assert(dest != nullptr);
+
+  int64_t value = unmarshal_int(buf);
+  char *strval  = LogUtils::timestamp_to_date_str(value);
+  int strlen    = (int)::strlen(strval);
+
+  memcpy(dest, strval, strlen);
+  return strlen;
+}
+
+int
+LogAccess::unmarshal_int_to_time_str(char **buf, char *dest, int len)
+{
+  ink_assert(buf != nullptr);
+  ink_assert(*buf != nullptr);
+  ink_assert(dest != nullptr);
+
+  int64_t value = unmarshal_int(buf);
+  char *strval  = LogUtils::timestamp_to_time_str(value);
+  int strlen    = (int)::strlen(strval);
+
+  memcpy(dest, strval, strlen);
+  return strlen;
+}
+
+int
+LogAccess::unmarshal_int_to_netscape_str(char **buf, char *dest, int len)
+{
+  ink_assert(buf != nullptr);
+  ink_assert(*buf != nullptr);
+  ink_assert(dest != nullptr);
+
+  int64_t value = unmarshal_int(buf);
+  char *strval  = LogUtils::timestamp_to_netscape_str(value);
+  int strlen    = (int)::strlen(strval);
+
+  memcpy(dest, strval, strlen);
+  return strlen;
+}
+
+/*-------------------------------------------------------------------------
+  LogAccess::unmarshal_http_method
+
+  Retrieve the int pointed at by the buffer and treat as an HttpMethod
+  enumerated type.  Then lookup the string representation for that enum and
+  return the string.  Advance the buffer pointer past the enum.
+  -------------------------------------------------------------------------*/
+/*
+int
+LogAccess::unmarshal_http_method (char **buf, char *dest, int len)
+{
+    return unmarshal_str (buf, dest, len);
+}
+*/
+/*-------------------------------------------------------------------------
+  LogAccess::unmarshal_http_version
+
+  The http version is marshalled as two consecutive integers, the first for
+  the major number and the second for the minor number.  Retrieve both
+  numbers and return the result as "HTTP/major.minor".
+  -------------------------------------------------------------------------*/
+
+int
+LogAccess::unmarshal_http_version(char **buf, char *dest, int len)
+{
+  ink_assert(buf != nullptr);
+  ink_assert(*buf != nullptr);
+  ink_assert(dest != nullptr);
+
+  static const char *http = "HTTP/";
+  static int http_len     = (int)::strlen(http);
+
+  char val_buf[128];
+  char *p = val_buf;
+
+  memcpy(p, http, http_len);
+  p += http_len;
+
+  int res1 = unmarshal_int_to_str(buf, p, 128 - http_len);
+  if (res1 < 0) {
+    return -1;
+  }
+  p += res1;
+  *p++     = '.';
+  int res2 = unmarshal_int_to_str(buf, p, 128 - http_len - res1 - 1);
+  if (res2 < 0) {
+    return -1;
+  }
+
+  int val_len = http_len + res1 + res2 + 1;
+  if (val_len < len) {
+    memcpy(dest, val_buf, val_len);
+    return val_len;
+  }
+  return -1;
+}
+
+/*-------------------------------------------------------------------------
+  LogAccess::unmarshal_http_text
+
+  The http text is simply the fields http_method (cqhm) + url (cqu) +
+  http_version (cqhv), all right next to each other, in that order.
+  -------------------------------------------------------------------------*/
+
+int
+LogAccess::unmarshal_http_text(char **buf, char *dest, int len, LogSlice *slice)
+{
+  ink_assert(buf != nullptr);
+  ink_assert(*buf != nullptr);
+  ink_assert(dest != nullptr);
+
+  char *p = dest;
+
+  //    int res1 = unmarshal_http_method (buf, p, len);
+  int res1 = unmarshal_str(buf, p, len);
+  if (res1 < 0) {
+    return -1;
+  }
+  p += res1;
+  *p++     = ' ';
+  int res2 = unmarshal_str(buf, p, len - res1 - 1, slice);
+  if (res2 < 0) {
+    return -1;
+  }
+  p += res2;
+  *p++     = ' ';
+  int res3 = unmarshal_http_version(buf, p, len - res1 - res2 - 2);
+  if (res3 < 0) {
+    return -1;
+  }
+  return res1 + res2 + res3 + 2;
+}
+
+/*-------------------------------------------------------------------------
+  LogAccess::unmarshal_http_status
+
+  An http response status code (pssc,sssc) is just an INT, but it's always
+  formatted with three digits and leading zeros.  So, we need a special
+  version of unmarshal_int_to_str that does this leading zero formatting.
+  -------------------------------------------------------------------------*/
+
+int
+LogAccess::unmarshal_http_status(char **buf, char *dest, int len)
+{
+  ink_assert(buf != nullptr);
+  ink_assert(*buf != nullptr);
+  ink_assert(dest != nullptr);
+
+  char val_buf[128];
+  int64_t val = unmarshal_int(buf);
+  int val_len = unmarshal_itoa(val, val_buf + 127, 3, '0');
+  if (val_len < len) {
+    memcpy(dest, val_buf + 128 - val_len, val_len);
+    return val_len;
+  }
+  return -1;
+}
+
+/*-------------------------------------------------------------------------
+  LogAccess::unmarshal_ip
+
+  Retrieve an IP address directly.
+  -------------------------------------------------------------------------*/
+int
+LogAccess::unmarshal_ip(char **buf, IpEndpoint *dest)
+{
+  int len = sizeof(LogFieldIp); // of object processed.
+
+  ink_assert(buf != nullptr);
+  ink_assert(*buf != nullptr);
+  ink_assert(dest != nullptr);
+
+  LogFieldIp *raw = reinterpret_cast<LogFieldIp *>(*buf);
+  if (AF_INET == raw->_family) {
+    LogFieldIp4 *ip4 = static_cast<LogFieldIp4 *>(raw);
+    ats_ip4_set(dest, ip4->_addr);
+    len = sizeof(*ip4);
+  } else if (AF_INET6 == raw->_family) {
+    LogFieldIp6 *ip6 = static_cast<LogFieldIp6 *>(raw);
+    ats_ip6_set(dest, ip6->_addr);
+    len = sizeof(*ip6);
+  } else {
+    ats_ip_invalidate(dest);
+  }
+  len = INK_ALIGN_DEFAULT(len);
+  *buf += len;
+  return len;
+}
+
+/*-------------------------------------------------------------------------
+  LogAccess::unmarshal_ip_to_str
+
+  Retrieve the IP addresspointed at by the buffer and convert to a
+  string in standard format. The string is written to @a dest and its
+  length (not including nul) is returned. @a *buf is advanced.
+  -------------------------------------------------------------------------*/
+
+int
+LogAccess::unmarshal_ip_to_str(char **buf, char *dest, int len)
+{
+  IpEndpoint ip;
+  int zret = -1;
+
+  if (len > 0) {
+    unmarshal_ip(buf, &ip);
+    if (!ats_is_ip(&ip)) {
+      *dest = '0';
+      zret  = 1;
+    } else if (ats_ip_ntop(&ip, dest, len)) {
+      zret = static_cast<int>(::strlen(dest));
+    }
+  }
+  return zret;
+}
+
+/*-------------------------------------------------------------------------
+  LogAccess::unmarshal_ip_to_hex
+
+  Retrieve the int pointed at by the buffer and treat as an IP
+  address.  Convert to a string in byte oriented hexadeciaml and
+  return the string.  Advance the buffer pointer.
+  -------------------------------------------------------------------------*/
+
+int
+LogAccess::unmarshal_ip_to_hex(char **buf, char *dest, int len)
+{
+  int zret = -1;
+  IpEndpoint ip;
+
+  if (len > 0) {
+    unmarshal_ip(buf, &ip);
+    if (!ats_is_ip(&ip)) {
+      *dest = '0';
+      zret  = 1;
+    } else {
+      zret = ats_ip_to_hex(&ip.sa, dest, len);
+    }
+  }
+  return zret;
+}
+
+/*-------------------------------------------------------------------------
+  LogAccess::unmarshal_hierarchy
+
+  Retrieve the int pointed at by the buffer and treat as a
+  SquidHierarchyCode.  Use this as an index into the local string
+  conversion tables and return the string equivalent to the enum.
+  Advance the buffer pointer.
+  -------------------------------------------------------------------------*/
+
+int
+LogAccess::unmarshal_hierarchy(char **buf, char *dest, int len, Ptr<LogFieldAliasMap> map)
+{
+  ink_assert(buf != nullptr);
+  ink_assert(*buf != nullptr);
+  ink_assert(dest != nullptr);
+
+  return (LogAccess::unmarshal_with_map(unmarshal_int(buf), dest, len, map, "INVALID_CODE"));
+}
+
+/*-------------------------------------------------------------------------
+  LogAccess::unmarshal_finish_status
+
+  Retrieve the int pointed at by the buffer and treat as a finish code.
+  Use the enum as an index into a string table and return the string equiv
+  of the enum.  Advance the pointer.
+  -------------------------------------------------------------------------*/
+
+int
+LogAccess::unmarshal_finish_status(char **buf, char *dest, int len, Ptr<LogFieldAliasMap> map)
+{
+  ink_assert(buf != nullptr);
+  ink_assert(*buf != nullptr);
+  ink_assert(dest != nullptr);
+
+  return (LogAccess::unmarshal_with_map(unmarshal_int(buf), dest, len, map, "UNKNOWN_FINISH_CODE"));
+}
+
+/*-------------------------------------------------------------------------
+  LogAccess::unmarshal_cache_code
+
+  Retrieve the int pointed at by the buffer and treat as a SquidLogCode.
+  Use this to index into the local string tables and return the string
+  equiv of the enum.  Advance the pointer.
+  -------------------------------------------------------------------------*/
+
+int
+LogAccess::unmarshal_cache_code(char **buf, char *dest, int len, Ptr<LogFieldAliasMap> map)
+{
+  ink_assert(buf != nullptr);
+  ink_assert(*buf != nullptr);
+  ink_assert(dest != nullptr);
+
+  return (LogAccess::unmarshal_with_map(unmarshal_int(buf), dest, len, map, "ERROR_UNKNOWN"));
+}
+
+/*-------------------------------------------------------------------------
+  LogAccess::unmarshal_cache_hit_miss
+
+  Retrieve the int pointed at by the buffer and treat as a SquidHitMissCode.
+  Use this to index into the local string tables and return the string
+  equiv of the enum.  Advance the pointer.
+  -------------------------------------------------------------------------*/
+
+int
+LogAccess::unmarshal_cache_hit_miss(char **buf, char *dest, int len, Ptr<LogFieldAliasMap> map)
+{
+  ink_assert(buf != nullptr);
+  ink_assert(*buf != nullptr);
+  ink_assert(dest != nullptr);
+
+  return (LogAccess::unmarshal_with_map(unmarshal_int(buf), dest, len, map, "HIT_MISS_UNKNOWN"));
+}
+
+int
+LogAccess::unmarshal_cache_write_code(char **buf, char *dest, int len, Ptr<LogFieldAliasMap> map)
+{
+  ink_assert(buf != nullptr);
+  ink_assert(*buf != nullptr);
+  ink_assert(dest != nullptr);
+
+  return (LogAccess::unmarshal_with_map(unmarshal_int(buf), dest, len, map, "UNKNOWN_CACHE_WRITE_CODE"));
+}
+
+int
+LogAccess::unmarshal_record(char **buf, char *dest, int len)
+{
+  ink_assert(buf != nullptr);
+  ink_assert(*buf != nullptr);
+  ink_assert(dest != nullptr);
+
+  char *val_buf = *buf;
+  int val_len   = (int)::strlen(val_buf);
+  *buf += MARSHAL_RECORD_LENGTH; // this is how it was stored
+  if (val_len < len) {
+    memcpy(dest, val_buf, val_len);
+    return val_len;
+  }
+  return -1;
+}
 
 /*-------------------------------------------------------------------------
+  resolve_logfield_string
+
+  This function resolves the given custom log format string using the given
+  LogAccess context and returns the resulting string, which is ats_malloc'd.
+  The caller is responsible for ats_free'ing the return result.  If there are
+  any problems, NULL is returned.
   -------------------------------------------------------------------------*/
+char *
+resolve_logfield_string(LogAccess *context, const char *format_str)
+{
+  if (!context) {
+    Debug("log-resolve", "No context to resolve?");
+    return nullptr;
+  }
+
+  if (!format_str) {
+    Debug("log-resolve", "No format to resolve?");
+    return nullptr;
+  }
+
+  Debug("log-resolve", "Resolving: %s", format_str);
+
+  //
+  // Divide the format string into two parts: one for the printf-style
+  // string and one for the symbols.
+  //
+  char *printf_str = nullptr;
+  char *fields_str = nullptr;
+  int n_fields     = LogFormat::parse_format_string(format_str, &printf_str, &fields_str);
+
+  //
+  // Perhaps there were no fields to resolve?  Then just return the
+  // format_str. Nothing to free here either.
+  //
+  if (!n_fields) {
+    Debug("log-resolve", "No fields found; returning copy of format_str");
+    ats_free(printf_str);
+    ats_free(fields_str);
+    return ats_strdup(format_str);
+  }
+
+  Debug("log-resolve", "%d fields: %s", n_fields, fields_str);
+  Debug("log-resolve", "printf string: %s", printf_str);
+
+  LogFieldList fields;
+  bool contains_aggregates;
+  int field_count = LogFormat::parse_symbol_string(fields_str, &fields, &contains_aggregates);
+
+  if (field_count != n_fields) {
+    Error("format_str contains %d invalid field symbols", n_fields - field_count);
+    ats_free(printf_str);
+    ats_free(fields_str);
+    return nullptr;
+  }
+  //
+  // Ok, now marshal the data out of the LogAccess object and into a
+  // temporary storage buffer.  Make sure the LogAccess context is
+  // initialized first.
+  //
+  Debug("log-resolve", "Marshaling data from LogAccess into buffer ...");
+  context->init();
+  unsigned bytes_needed = fields.marshal_len(context);
+  char *buf             = (char *)ats_malloc(bytes_needed);
+  unsigned bytes_used   = fields.marshal(context, buf);
+
+  ink_assert(bytes_needed == bytes_used);
+  Debug("log-resolve", "    %u bytes marshalled", bytes_used);
+
+  //
+  // Now we can "unmarshal" the data from the buffer into a string,
+  // combining it with the data from the printf string.  The problem is,
+  // we're not sure how much space it will take when it's unmarshalled.
+  // So, we'll just guess.
+  //
+  char *result = (char *)ats_malloc(8192);
+  unsigned bytes_resolved =
+    LogBuffer::resolve_custom_entry(&fields, printf_str, buf, result, 8191, LogUtils::timestamp(), 0, LOG_SEGMENT_VERSION);
+  ink_assert(bytes_resolved < 8192);
+
+  if (!bytes_resolved) {
+    ats_free(result);
+    result = nullptr;
+  } else {
+    result[bytes_resolved] = 0; // NULL terminate
+  }
+
+  ats_free(printf_str);
+  ats_free(fields_str);
+  ats_free(buf);
+
+  return result;
+}
+void
+LogAccess::set_client_req_url(char *buf, int len)
+{
+  if (buf) {
+    m_client_req_url_len = len;
+    ink_strlcpy(m_client_req_url_str, buf, m_client_req_url_len + 1);
+  }
+}
+
+void
+LogAccess::set_client_req_url_canon(char *buf, int len)
+{
+  if (buf) {
+    m_client_req_url_canon_len = len;
+    ink_strlcpy(m_client_req_url_canon_str, buf, m_client_req_url_canon_len + 1);
+  }
+}
+
+void
+LogAccess::set_client_req_unmapped_url_canon(char *buf, int len)
+{
+  if (buf) {
+    m_client_req_unmapped_url_canon_len = len;
+    ink_strlcpy(m_client_req_unmapped_url_canon_str, buf, m_client_req_unmapped_url_canon_len + 1);
+  }
+}
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_proxy_resp_content_type, DEFAULT_STR_FIELD)
+void
+LogAccess::set_client_req_unmapped_url_path(char *buf, int len)
+{
+  if (buf) {
+    m_client_req_unmapped_url_path_len = len;
+    ink_strlcpy(m_client_req_unmapped_url_path_str, buf, m_client_req_unmapped_url_path_len + 1);
+  }
+}
 
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
+void
+LogAccess::set_client_req_unmapped_url_host(char *buf, int len)
+{
+  if (buf) {
+    m_client_req_unmapped_url_host_len = len;
+    ink_strlcpy(m_client_req_unmapped_url_host_str, buf, m_client_req_unmapped_url_host_len + 1);
+  }
+}
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_proxy_resp_reason_phrase, DEFAULT_STR_FIELD)
+void
+LogAccess::set_client_req_url_path(char *buf, int len)
+{
+  //?? use m_client_req_unmapped_url_path_str for now..may need to enhance later..
+  if (buf) {
+    m_client_req_url_path_len = len;
+    ink_strlcpy(m_client_req_unmapped_url_path_str, buf, m_client_req_url_path_len + 1);
+  }
+}
 
 /*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-LOG_ACCESS_DEFAULT_FIELD(marshal_proxy_resp_squid_len, DEFAULT_INT_FIELD)
-LOG_ACCESS_DEFAULT_FIELD(marshal_client_req_squid_len, DEFAULT_INT_FIELD)
-LOG_ACCESS_DEFAULT_FIELD(marshal_proxy_req_squid_len, DEFAULT_INT_FIELD)
-LOG_ACCESS_DEFAULT_FIELD(marshal_server_resp_squid_len, DEFAULT_INT_FIELD)
-LOG_ACCESS_DEFAULT_FIELD(marshal_cache_resp_squid_len, DEFAULT_INT_FIELD)
+  The marshalling routines ...
 
-/*-------------------------------------------------------------------------
+  We know that m_http_sm is a valid pointer (we assert so in the ctor), but
+  we still need to check the other header pointers before using them in the
+  routines.
   -------------------------------------------------------------------------*/
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_proxy_resp_content_len, DEFAULT_INT_FIELD)
-
 /*-------------------------------------------------------------------------
   -------------------------------------------------------------------------*/
+int
+LogAccess::marshal_plugin_identity_id(char *buf)
+{
+  if (buf) {
+    marshal_int(buf, m_http_sm->plugin_id);
+  }
+  return INK_MIN_ALIGN;
+}
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_proxy_resp_status_code, DEFAULT_INT_FIELD)
+int
+LogAccess::marshal_plugin_identity_tag(char *buf)
+{
+  int len         = INK_MIN_ALIGN;
+  const char *tag = m_http_sm->plugin_tag;
 
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
+  if (!tag) {
+    tag = "*";
+  } else {
+    len = LogAccess::strlen(tag);
+  }
+
+  if (buf) {
+    marshal_str(buf, tag, len);
+  }
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_proxy_resp_header_len, DEFAULT_INT_FIELD)
+  return len;
+}
 
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
+int
+LogAccess::marshal_client_host_ip(char *buf)
+{
+  return marshal_ip(buf, &m_http_sm->t_state.client_info.src_addr.sa);
+}
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_proxy_finish_status_code, DEFAULT_INT_FIELD)
+int
+LogAccess::marshal_host_interface_ip(char *buf)
+{
+  return marshal_ip(buf, &m_http_sm->t_state.client_info.dst_addr.sa);
+}
 
 /*-------------------------------------------------------------------------
   -------------------------------------------------------------------------*/
+int
+LogAccess::marshal_cache_lookup_url_canon(char *buf)
+{
+  int len = INK_MIN_ALIGN;
+
+  validate_lookup_url();
+  if (m_cache_lookup_url_canon_str == INVALID_STR) {
+    // If the lookup URL isn't populated, we'll fall back to the request URL.
+    len = marshal_client_req_url_canon(buf);
+  } else {
+    len = round_strlen(m_cache_lookup_url_canon_len + 1); // +1 for eos
+    if (buf) {
+      marshal_mem(buf, m_cache_lookup_url_canon_str, m_cache_lookup_url_canon_len, len);
+    }
+  }
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_cache_result_code, DEFAULT_INT_FIELD)
+  return len;
+}
 
 /*-------------------------------------------------------------------------
   -------------------------------------------------------------------------*/
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_cache_result_subcode, DEFAULT_INT_FIELD)
+int
+LogAccess::marshal_client_host_port(char *buf)
+{
+  if (buf) {
+    uint16_t port = ntohs(m_http_sm->t_state.client_info.src_addr.port());
+    marshal_int(buf, port);
+  }
+  return INK_MIN_ALIGN;
+}
 
 /*-------------------------------------------------------------------------
+  user authenticated to the proxy (RFC931)
   -------------------------------------------------------------------------*/
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_cache_hit_miss, DEFAULT_INT_FIELD)
+int
+LogAccess::marshal_client_auth_user_name(char *buf)
+{
+  char *str = nullptr;
+  int len   = INK_MIN_ALIGN;
+
+  // Jira TS-40:
+  // NOTE: Authentication related code and modules were removed/disabled.
+  //       Uncomment code path below when re-added/enabled.
+  /*if (m_http_sm->t_state.auth_params.user_name) {
+    str = m_http_sm->t_state.auth_params.user_name;
+    len = LogAccess::strlen(str);
+    } */
+  if (buf) {
+    marshal_str(buf, str, len);
+  }
+  return len;
+}
 
 /*-------------------------------------------------------------------------
+  Private utility function to validate m_client_req_unmapped_url_canon_str &
+  m_client_req_unmapped_url_canon_len fields.
   -------------------------------------------------------------------------*/
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_proxy_req_header_len, DEFAULT_INT_FIELD)
+void
+LogAccess::validate_unmapped_url()
+{
+  if (m_client_req_unmapped_url_canon_str == nullptr) {
+    // prevent multiple validations
+    m_client_req_unmapped_url_canon_str = INVALID_STR;
 
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
+    if (m_http_sm->t_state.unmapped_url.valid()) {
+      int unmapped_url_len;
+      char *unmapped_url = m_http_sm->t_state.unmapped_url.string_get_ref(&unmapped_url_len);
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_proxy_req_content_len, DEFAULT_INT_FIELD)
+      if (unmapped_url && unmapped_url[0] != 0) {
+        m_client_req_unmapped_url_canon_str =
+          LogUtils::escapify_url(&m_arena, unmapped_url, unmapped_url_len, &m_client_req_unmapped_url_canon_len);
+      }
+    }
+  }
+}
 
 /*-------------------------------------------------------------------------
+  Private utility function to validate m_client_req_unmapped_url_path_str &
+  m_client_req_unmapped_url_path_len fields.
   -------------------------------------------------------------------------*/
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_proxy_req_server_ip, DEFAULT_IP_FIELD)
+void
+LogAccess::validate_unmapped_url_path()
+{
+  int len;
+  char *c;
+
+  if (m_client_req_unmapped_url_path_str == nullptr && m_client_req_unmapped_url_host_str == nullptr) {
+    // Use unmapped canonical URL as default
+    m_client_req_unmapped_url_path_str = m_client_req_unmapped_url_canon_str;
+    m_client_req_unmapped_url_path_len = m_client_req_unmapped_url_canon_len;
+    // Incase the code below fails, we prevent it from being used.
+    m_client_req_unmapped_url_host_str = INVALID_STR;
+
+    if (m_client_req_unmapped_url_path_len >= 6) { // xxx:// - minimum schema size
+      c = (char *)memchr((void *)m_client_req_unmapped_url_path_str, ':', m_client_req_unmapped_url_path_len - 1);
+      if (c && (len = (int)(c - m_client_req_unmapped_url_path_str)) <= 5) { // 5 - max schema size
+        if (len + 2 <= m_client_req_unmapped_url_canon_len && c[1] == '/' && c[2] == '/') {
+          len += 3; // Skip "://"
+          m_client_req_unmapped_url_host_str = &m_client_req_unmapped_url_canon_str[len];
+          m_client_req_unmapped_url_host_len = m_client_req_unmapped_url_path_len - len;
+          // Attempt to find first '/' in the path
+          if (m_client_req_unmapped_url_host_len > 0 && (c = (char *)memchr((void *)m_client_req_unmapped_url_host_str, '/',
+                                                                            m_client_req_unmapped_url_path_len)) != nullptr) {
+            m_client_req_unmapped_url_host_len = (int)(c - m_client_req_unmapped_url_host_str);
+            m_client_req_unmapped_url_path_str = &m_client_req_unmapped_url_host_str[m_client_req_unmapped_url_host_len];
+            m_client_req_unmapped_url_path_len = m_client_req_unmapped_url_path_len - len - m_client_req_unmapped_url_host_len;
+          }
+        }
+      }
+    }
+  }
+}
 
 /*-------------------------------------------------------------------------
+  Private utility function to validate m_cache_lookup_url_canon_str &
+  m_cache_lookup__url_canon_len fields.
   -------------------------------------------------------------------------*/
+void
+LogAccess::validate_lookup_url()
+{
+  if (m_cache_lookup_url_canon_str == nullptr) {
+    // prevent multiple validations
+    m_cache_lookup_url_canon_str = INVALID_STR;
+
+    if (m_http_sm->t_state.cache_info.lookup_url_storage.valid()) {
+      int lookup_url_len;
+      char *lookup_url = m_http_sm->t_state.cache_info.lookup_url_storage.string_get_ref(&lookup_url_len);
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_proxy_req_server_port, DEFAULT_INT_FIELD)
+      if (lookup_url && lookup_url[0] != 0) {
+        m_cache_lookup_url_canon_str = LogUtils::escapify_url(&m_arena, lookup_url, lookup_url_len, &m_cache_lookup_url_canon_len);
+      }
+    }
+  }
+}
 
 /*-------------------------------------------------------------------------
+  This is the method, url, and version all rolled into one.  Use the
+  respective marshalling routines to do the job.
   -------------------------------------------------------------------------*/
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_proxy_hierarchy_route, DEFAULT_INT_FIELD)
+int
+LogAccess::marshal_client_req_text(char *buf)
+{
+  int len = marshal_client_req_http_method(nullptr) + marshal_client_req_url(nullptr) + marshal_client_req_http_version(nullptr);
+
+  if (buf) {
+    int offset = 0;
+    offset += marshal_client_req_http_method(&buf[offset]);
+    offset += marshal_client_req_url(&buf[offset]);
+    offset += marshal_client_req_http_version(&buf[offset]);
+    len = offset;
+  }
+  return len;
+}
 
 /*-------------------------------------------------------------------------
   -------------------------------------------------------------------------*/
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_next_hop_ip, DEFAULT_IP_FIELD)
+int
+LogAccess::marshal_client_req_timestamp_sec(char *buf)
+{
+  return marshal_milestone_fmt_sec(TS_MILESTONE_UA_BEGIN, buf);
+}
 
 /*-------------------------------------------------------------------------
   -------------------------------------------------------------------------*/
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_next_hop_port, DEFAULT_INT_FIELD)
+int
+LogAccess::marshal_client_req_timestamp_ms(char *buf)
+{
+  return marshal_milestone_fmt_ms(TS_MILESTONE_UA_BEGIN, buf);
+}
 
 /*-------------------------------------------------------------------------
   -------------------------------------------------------------------------*/
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_client_retry_after_time, DEFAULT_INT_FIELD)
+int
+LogAccess::marshal_client_req_http_method(char *buf)
+{
+  char *str = nullptr;
+  int alen  = 0;
+  int plen  = INK_MIN_ALIGN;
+
+  if (m_client_request) {
+    str = (char *)m_client_request->method_get(&alen);
+
+    // calculate the the padded length only if the actual length
+    // is not zero. We don't want the padded length to be zero
+    // because marshal_mem should write the DEFAULT_STR to the
+    // buffer if str is nil, and we need room for this.
+    //
+    if (alen) {
+      plen = round_strlen(alen + 1); // +1 for trailing 0
+    }
+  }
+
+  if (buf) {
+    marshal_mem(buf, str, alen, plen);
+  }
+  return plen;
+}
 
 /*-------------------------------------------------------------------------
   -------------------------------------------------------------------------*/
 
 int
-LogAccess::marshal_proxy_host_name(char *buf)
+LogAccess::marshal_client_req_url(char *buf)
 {
-  char *str        = nullptr;
-  int len          = 0;
-  Machine *machine = Machine::instance();
+  int len = round_strlen(m_client_req_url_len + 1); // +1 for trailing 0
 
-  if (machine) {
-    str = machine->hostname;
+  if (buf) {
+    marshal_mem(buf, m_client_req_url_str, m_client_req_url_len, len);
   }
+  return len;
+}
 
-  len = LogAccess::strlen(str);
+/*-------------------------------------------------------------------------
+  -------------------------------------------------------------------------*/
+
+int
+LogAccess::marshal_client_req_url_canon(char *buf)
+{
+  int len = round_strlen(m_client_req_url_canon_len + 1);
 
   if (buf) {
-    marshal_str(buf, str, len);
+    marshal_mem(buf, m_client_req_url_canon_str, m_client_req_url_canon_len, len);
   }
-
   return len;
 }
 
@@ -345,51 +1431,124 @@ LogAccess::marshal_proxy_host_name(char *buf)
   -------------------------------------------------------------------------*/
 
 int
-LogAccess::marshal_proxy_host_ip(char *buf)
+LogAccess::marshal_client_req_unmapped_url_canon(char *buf)
 {
-  return marshal_ip(buf, &Machine::instance()->ip.sa);
+  int len = INK_MIN_ALIGN;
+
+  validate_unmapped_url();
+  if (m_client_req_unmapped_url_canon_str == INVALID_STR) {
+    // If the unmapped URL isn't populated, we'll fall back to the original
+    // client URL. This helps for example server intercepts to continue to
+    // log the requests, even when there is no remap rule for it.
+    len = marshal_client_req_url_canon(buf);
+  } else {
+    len = round_strlen(m_client_req_unmapped_url_canon_len + 1); // +1 for eos
+    if (buf) {
+      marshal_mem(buf, m_client_req_unmapped_url_canon_str, m_client_req_unmapped_url_canon_len, len);
+    }
+  }
+
+  return len;
 }
 
 /*-------------------------------------------------------------------------
   -------------------------------------------------------------------------*/
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_proxy_req_is_ssl, DEFAULT_INT_FIELD)
+int
+LogAccess::marshal_client_req_unmapped_url_path(char *buf)
+{
+  int len = INK_MIN_ALIGN;
 
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
+  validate_unmapped_url();
+  validate_unmapped_url_path();
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_server_host_ip, DEFAULT_IP_FIELD)
+  if (m_client_req_unmapped_url_path_str == INVALID_STR) {
+    len = marshal_client_req_url_path(buf);
+  } else {
+    len = round_strlen(m_client_req_unmapped_url_path_len + 1); // +1 for eos
+    if (buf) {
+      marshal_mem(buf, m_client_req_unmapped_url_path_str, m_client_req_unmapped_url_path_len, len);
+    }
+  }
+  return len;
+}
 
 /*-------------------------------------------------------------------------
   -------------------------------------------------------------------------*/
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_server_host_name, DEFAULT_STR_FIELD)
+int
+LogAccess::marshal_client_req_unmapped_url_host(char *buf)
+{
+  validate_unmapped_url();
+  validate_unmapped_url_path();
+
+  int len = round_strlen(m_client_req_unmapped_url_host_len + 1); // +1 for eos
+  if (buf) {
+    marshal_mem(buf, m_client_req_unmapped_url_host_str, m_client_req_unmapped_url_host_len, len);
+  }
 
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
+  return len;
+}
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_server_resp_status_code, DEFAULT_INT_FIELD)
+int
+LogAccess::marshal_client_req_url_path(char *buf)
+{
+  int len = round_strlen(m_client_req_url_path_len + 1);
+  if (buf) {
+    marshal_mem(buf, m_client_req_url_path_str, m_client_req_url_path_len, len);
+  }
+  return len;
+}
 
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
+int
+LogAccess::marshal_client_req_url_scheme(char *buf)
+{
+  int scheme      = m_http_sm->t_state.orig_scheme;
+  const char *str = nullptr;
+  int alen;
+  int plen = INK_MIN_ALIGN;
+
+  // If the transaction aborts very early, the scheme may not be set, or so ASAN reports.
+  if (scheme >= 0) {
+    str  = hdrtoken_index_to_wks(scheme);
+    alen = hdrtoken_index_to_length(scheme);
+  } else {
+    str  = "UNKNOWN";
+    alen = strlen(str);
+  }
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_server_resp_content_len, DEFAULT_INT_FIELD)
+  // calculate the the padded length only if the actual length
+  // is not zero. We don't want the padded length to be zero
+  // because marshal_mem should write the DEFAULT_STR to the
+  // buffer if str is nil, and we need room for this.
+  //
+  if (alen) {
+    plen = round_strlen(alen + 1); // +1 for trailing 0
+  }
 
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
+  if (buf) {
+    marshal_mem(buf, str, alen, plen);
+  }
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_server_resp_header_len, DEFAULT_INT_FIELD)
+  return plen;
+}
 
 /*-------------------------------------------------------------------------
-  This case is special because it really stores 2 ints.
+  For this one we're going to marshal two INTs, one the first representing
+  the major number and the second representing the minor.
   -------------------------------------------------------------------------*/
 
 int
-LogAccess::marshal_server_resp_http_version(char *buf)
+LogAccess::marshal_client_req_http_version(char *buf)
 {
   if (buf) {
     int64_t major = 0;
     int64_t minor = 0;
+    if (m_client_request) {
+      HTTPVersion versionObject = m_client_request->version_get();
+      major                     = HTTP_MAJOR(versionObject.m_version);
+      minor                     = HTTP_MINOR(versionObject.m_version);
+    }
     marshal_int(buf, major);
     marshal_int((buf + INK_MIN_ALIGN), minor);
   }
@@ -397,1118 +1556,1175 @@ LogAccess::marshal_server_resp_http_version(char *buf)
 }
 
 /*-------------------------------------------------------------------------
--------------------------------------------------------------------------*/
-
-LOG_ACCESS_DEFAULT_FIELD(marshal_server_resp_time_ms, DEFAULT_INT_FIELD)
-
-LOG_ACCESS_DEFAULT_FIELD(marshal_server_resp_time_s, DEFAULT_INT_FIELD)
+  -------------------------------------------------------------------------*/
 
-/*-------------------------------------------------------------------------
--------------------------------------------------------------------------*/
+int
+LogAccess::marshal_client_req_protocol_version(char *buf)
+{
+  const char *protocol_str = m_http_sm->client_protocol;
+  int len                  = LogAccess::strlen(protocol_str);
+
+  // Set major & minor versions when protocol_str is not "http/2".
+  if (::strlen(protocol_str) == 4 && strncmp("http", protocol_str, 4) == 0) {
+    if (m_client_request) {
+      HTTPVersion versionObject = m_client_request->version_get();
+      int64_t major             = HTTP_MAJOR(versionObject.m_version);
+      int64_t minor             = HTTP_MINOR(versionObject.m_version);
+      if (major == 1 && minor == 1) {
+        protocol_str = "http/1.1";
+      } else if (major == 1 && minor == 0) {
+        protocol_str = "http/1.0";
+      } // else invalid http version
+    } else {
+      protocol_str = "*";
+    }
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_server_transact_count, DEFAULT_INT_FIELD)
+    len = LogAccess::strlen(protocol_str);
+  }
 
-/*-------------------------------------------------------------------------
--------------------------------------------------------------------------*/
+  if (buf) {
+    marshal_str(buf, protocol_str, len);
+  }
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_server_connect_attempts, DEFAULT_INT_FIELD)
+  return len;
+}
 
 /*-------------------------------------------------------------------------
   -------------------------------------------------------------------------*/
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_cache_resp_status_code, DEFAULT_INT_FIELD)
+int
+LogAccess::marshal_client_req_header_len(char *buf)
+{
+  if (buf) {
+    int64_t len = 0;
+    if (m_client_request) {
+      len = m_client_request->length_get();
+    }
+    marshal_int(buf, len);
+  }
+  return INK_MIN_ALIGN;
+}
 
 /*-------------------------------------------------------------------------
   -------------------------------------------------------------------------*/
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_cache_resp_content_len, DEFAULT_INT_FIELD)
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
+int
+LogAccess::marshal_client_req_content_len(char *buf)
+{
+  if (buf) {
+    int64_t len = 0;
+    if (m_client_request) {
+      len = m_http_sm->client_request_body_bytes;
+    }
+    marshal_int(buf, len);
+  }
+  return INK_MIN_ALIGN;
+}
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_cache_resp_header_len, DEFAULT_INT_FIELD)
+int
+LogAccess::marshal_client_req_squid_len(char *buf)
+{
+  if (buf) {
+    int64_t val = 0;
+    if (m_client_request) {
+      val = m_client_request->length_get() + m_http_sm->client_request_body_bytes;
+    }
+    marshal_int(buf, val);
+  }
+  return INK_MIN_ALIGN;
+}
 
 /*-------------------------------------------------------------------------
-  This case is special because it really stores 2 ints.
   -------------------------------------------------------------------------*/
 
 int
-LogAccess::marshal_cache_resp_http_version(char *buf)
+LogAccess::marshal_client_req_tcp_reused(char *buf)
 {
   if (buf) {
-    int64_t major = 0;
-    int64_t minor = 0;
-    marshal_int(buf, major);
-    marshal_int((buf + INK_MIN_ALIGN), minor);
+    int64_t tcp_reused;
+    tcp_reused = m_http_sm->client_tcp_reused;
+    marshal_int(buf, tcp_reused);
   }
-  return (2 * INK_MIN_ALIGN);
+  return INK_MIN_ALIGN;
 }
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_cache_write_code, DEFAULT_INT_FIELD)
-
-LOG_ACCESS_DEFAULT_FIELD(marshal_cache_write_transform_code, DEFAULT_INT_FIELD)
-
 /*-------------------------------------------------------------------------
   -------------------------------------------------------------------------*/
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_transfer_time_ms, DEFAULT_INT_FIELD)
-
-LOG_ACCESS_DEFAULT_FIELD(marshal_transfer_time_s, DEFAULT_INT_FIELD)
+int
+LogAccess::marshal_client_req_is_ssl(char *buf)
+{
+  if (buf) {
+    int64_t is_ssl;
+    is_ssl = m_http_sm->client_connection_is_ssl;
+    marshal_int(buf, is_ssl);
+  }
+  return INK_MIN_ALIGN;
+}
 
 /*-------------------------------------------------------------------------
   -------------------------------------------------------------------------*/
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_file_size, DEFAULT_INT_FIELD)
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
 int
-LogAccess::marshal_http_header_field(LogField::Container /* container ATS_UNUSED */, char * /* field ATS_UNUSED */, char *buf)
+LogAccess::marshal_client_req_ssl_reused(char *buf)
 {
-  DEFAULT_STR_FIELD;
+  if (buf) {
+    int64_t ssl_session_reused;
+    ssl_session_reused = m_http_sm->client_ssl_reused;
+    marshal_int(buf, ssl_session_reused);
+  }
+  return INK_MIN_ALIGN;
 }
 
 /*-------------------------------------------------------------------------
-
   -------------------------------------------------------------------------*/
+
 int
-LogAccess::marshal_http_header_field_escapify(LogField::Container /* container ATS_UNUSED */, char * /* field ATS_UNUSED */,
-                                              char *buf)
+LogAccess::marshal_client_finish_status_code(char *buf)
 {
-  DEFAULT_STR_FIELD;
+  if (buf) {
+    int code                                  = LOG_FINISH_FIN;
+    HttpTransact::AbortState_t cl_abort_state = m_http_sm->t_state.client_info.abort;
+    if (cl_abort_state == HttpTransact::ABORTED) {
+      // Check to see if the abort is due to a timeout
+      if (m_http_sm->t_state.client_info.state == HttpTransact::ACTIVE_TIMEOUT ||
+          m_http_sm->t_state.client_info.state == HttpTransact::INACTIVE_TIMEOUT) {
+        code = LOG_FINISH_TIMEOUT;
+      } else {
+        code = LOG_FINISH_INTR;
+      }
+    }
+    marshal_int(buf, code);
+  }
+  return INK_MIN_ALIGN;
 }
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_proxy_host_port, DEFAULT_INT_FIELD)
-
-/*-------------------------------------------------------------------------
-
-  The following functions have a non-virtual base-class implementation.
-  -------------------------------------------------------------------------*/
-
 /*-------------------------------------------------------------------------
   -------------------------------------------------------------------------*/
 
 int
-LogAccess::marshal_entry_type(char *buf)
+LogAccess::marshal_client_req_id(char *buf)
 {
   if (buf) {
-    int64_t val = (int64_t)entry_type();
-    marshal_int(buf, val);
+    marshal_int(buf, m_http_sm->sm_id);
   }
   return INK_MIN_ALIGN;
 }
 
 /*-------------------------------------------------------------------------
   -------------------------------------------------------------------------*/
+
 int
-LogAccess::marshal_process_uuid(char *buf)
+LogAccess::marshal_client_req_uuid(char *buf)
 {
-  int len = round_strlen(TS_UUID_STRING_LEN + 1);
+  char str[TS_CRUUID_STRING_LEN + 1];
+  const char *uuid = Machine::instance()->uuid.getString();
+  int len          = snprintf(str, sizeof(str), "%s-%" PRId64 "", uuid, m_http_sm->sm_id);
+
+  ink_assert(len <= TS_CRUUID_STRING_LEN);
+  len = round_strlen(len + 1);
 
   if (buf) {
-    const char *str = (char *)Machine::instance()->uuid.getString();
-    marshal_str(buf, str, len);
+    marshal_str(buf, str, len); // This will pad the remaning bytes properly ...
   }
+
   return len;
 }
 
 /*-------------------------------------------------------------------------
   -------------------------------------------------------------------------*/
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_client_http_connection_id, DEFAULT_INT_FIELD)
+// 1 ('S'/'T' flag) + 8 (Error Code) + 1 ('\0')
+static constexpr size_t MAX_PROXY_ERROR_CODE_SIZE = 10;
 
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
+int
+LogAccess::marshal_client_rx_error_code(char *buf)
+{
+  char error_code[MAX_PROXY_ERROR_CODE_SIZE] = {0};
+  m_http_sm->t_state.client_info.rx_error_code.str(error_code, sizeof(error_code));
+  int round_len = LogAccess::strlen(error_code);
 
-LOG_ACCESS_DEFAULT_FIELD(marshal_client_http_transaction_id, DEFAULT_INT_FIELD)
+  if (buf) {
+    marshal_str(buf, error_code, round_len);
+  }
 
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
+  return round_len;
+}
 
 int
-LogAccess::marshal_config_int_var(char *config_var, char *buf)
+LogAccess::marshal_client_tx_error_code(char *buf)
 {
+  char error_code[MAX_PROXY_ERROR_CODE_SIZE] = {0};
+  m_http_sm->t_state.client_info.tx_error_code.str(error_code, sizeof(error_code));
+  int round_len = LogAccess::strlen(error_code);
+
   if (buf) {
-    int64_t val = (int64_t)REC_ConfigReadInteger(config_var);
-    marshal_int(buf, val);
+    marshal_str(buf, error_code, round_len);
   }
-  return INK_MIN_ALIGN;
+
+  return round_len;
 }
 
 /*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
+-------------------------------------------------------------------------*/
 int
-LogAccess::marshal_config_str_var(char *config_var, char *buf)
+LogAccess::marshal_client_security_protocol(char *buf)
 {
-  char *str = nullptr;
-  str       = REC_ConfigReadString(config_var);
-  int len   = LogAccess::strlen(str);
+  const char *proto = m_http_sm->client_sec_protocol;
+  int round_len     = LogAccess::strlen(proto);
+
   if (buf) {
-    marshal_str(buf, str, len);
+    marshal_str(buf, proto, round_len);
   }
-  ats_free(str);
-  return len;
-}
 
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
+  return round_len;
+}
 
 int
-LogAccess::marshal_milestone(TSMilestonesType ms, char *buf)
+LogAccess::marshal_client_security_cipher_suite(char *buf)
 {
-  DEFAULT_INT_FIELD;
+  const char *cipher = m_http_sm->client_cipher_suite;
+  int round_len      = LogAccess::strlen(cipher);
+
+  if (buf) {
+    marshal_str(buf, cipher, round_len);
+  }
+
+  return round_len;
 }
 
 /*-------------------------------------------------------------------------
   -------------------------------------------------------------------------*/
 
 int
-LogAccess::marshal_milestone_fmt_sec(TSMilestonesType ms, char *buf)
+LogAccess::marshal_proxy_resp_content_type(char *buf)
 {
-  DEFAULT_INT_FIELD;
+  int len = round_strlen(m_proxy_resp_content_type_len + 1);
+  if (buf) {
+    marshal_mem(buf, m_proxy_resp_content_type_str, m_proxy_resp_content_type_len, len);
+  }
+  return len;
 }
 
 /*-------------------------------------------------------------------------
   -------------------------------------------------------------------------*/
 
 int
-LogAccess::marshal_milestone_fmt_squid(TSMilestonesType ms, char *buf)
+LogAccess::marshal_proxy_resp_reason_phrase(char *buf)
 {
-  DEFAULT_STR_FIELD;
+  int len = round_strlen(m_proxy_resp_reason_phrase_len + 1);
+  if (buf) {
+    marshal_mem(buf, m_proxy_resp_reason_phrase_str, m_proxy_resp_reason_phrase_len, len);
+  }
+  return len;
 }
 
 /*-------------------------------------------------------------------------
+  Squid returns the content-length + header length as the total length.
   -------------------------------------------------------------------------*/
 
 int
-LogAccess::marshal_milestone_fmt_netscape(TSMilestonesType ms, char *buf)
+LogAccess::marshal_proxy_resp_squid_len(char *buf)
 {
-  DEFAULT_STR_FIELD;
+  if (buf) {
+    int64_t val = m_http_sm->client_response_hdr_bytes + m_http_sm->client_response_body_bytes;
+    marshal_int(buf, val);
+  }
+  return INK_MIN_ALIGN;
 }
 
 /*-------------------------------------------------------------------------
   -------------------------------------------------------------------------*/
 
 int
-LogAccess::marshal_milestone_fmt_date(TSMilestonesType ms, char *buf)
+LogAccess::marshal_proxy_resp_content_len(char *buf)
 {
-  DEFAULT_STR_FIELD;
+  if (buf) {
+    int64_t val = m_http_sm->client_response_body_bytes;
+    marshal_int(buf, val);
+  }
+  return INK_MIN_ALIGN;
 }
 
 /*-------------------------------------------------------------------------
   -------------------------------------------------------------------------*/
 
 int
-LogAccess::marshal_milestone_fmt_time(TSMilestonesType ms, char *buf)
+LogAccess::marshal_proxy_resp_status_code(char *buf)
 {
-  DEFAULT_STR_FIELD;
+  if (buf) {
+    HTTPStatus status;
+    if (m_proxy_response && m_client_request) {
+      if (m_client_request->version_get() >= HTTPVersion(1, 0)) {
+        status = m_proxy_response->status_get();
+      }
+      // INKqa10788
+      // For bad/incomplete request, the request version may be 0.9.
+      // However, we can still log the status code if there is one.
+      else if (m_proxy_response->valid()) {
+        status = m_proxy_response->status_get();
+      } else {
+        status = HTTP_STATUS_OK;
+      }
+    } else {
+      status = HTTP_STATUS_NONE;
+    }
+    marshal_int(buf, (int64_t)status);
+  }
+  return INK_MIN_ALIGN;
 }
 
 /*-------------------------------------------------------------------------
   -------------------------------------------------------------------------*/
 
 int
-LogAccess::marshal_milestone_diff(TSMilestonesType ms1, TSMilestonesType ms2, char *buf)
+LogAccess::marshal_proxy_resp_header_len(char *buf)
 {
-  DEFAULT_INT_FIELD;
+  if (buf) {
+    int64_t val = m_http_sm->client_response_hdr_bytes;
+    marshal_int(buf, val);
+  }
+  return INK_MIN_ALIGN;
 }
 
-// To allow for a generic marshal_record function, rather than
-// multiple functions (one per data type) we always marshal a record
-// as a string of a fixed length.  We use a fixed length because the
-// marshal_record function can be called with a null *buf to request
-// the length of the record, and later with a non-null *buf to
-// actually request the record to be inserted in the buffer, and both
-// calls should return the same number of characters. If we did not
-// enforce a fixed size, this would not necessarily be the case
-// because records --statistics in particular-- can potentially change
-// between one call and the other.
-//
 int
-LogAccess::marshal_record(char *record, char *buf)
+LogAccess::marshal_proxy_finish_status_code(char *buf)
 {
-  const unsigned int max_chars = MARSHAL_RECORD_LENGTH;
-
-  if (nullptr == buf) {
-    return max_chars;
-  }
-
-  const char *record_not_found_msg          = "RECORD_NOT_FOUND";
-  const unsigned int record_not_found_chars = ::strlen(record_not_found_msg) + 1;
-
-  char ascii_buf[max_chars];
-  const char *out_buf;
-  unsigned int num_chars;
-
-#define LOG_INTEGER RECD_INT
-#define LOG_COUNTER RECD_COUNTER
-#define LOG_FLOAT RECD_FLOAT
-#define LOG_STRING RECD_STRING
-
-  RecDataT stype = RECD_NULL;
-  bool found     = false;
-
-  if (RecGetRecordDataType(record, &stype) != REC_ERR_OKAY) {
-    out_buf   = "INVALID_RECORD";
-    num_chars = ::strlen(out_buf) + 1;
-  } else {
-    if (LOG_INTEGER == stype || LOG_COUNTER == stype) {
-      // we assume MgmtInt and MgmtIntCounter are int64_t for the
-      // conversion below, if this ever changes we should modify
-      // accordingly
-      //
-      ink_assert(sizeof(int64_t) >= sizeof(RecInt) && sizeof(int64_t) >= sizeof(RecCounter));
-
-      // so that a 64 bit integer will fit (including sign and eos)
-      //
-      ink_assert(max_chars > 21);
-
-      int64_t val = (int64_t)(LOG_INTEGER == stype ? REC_readInteger(record, &found) : REC_readCounter(record, &found));
-
-      if (found) {
-        out_buf = int64_to_str(ascii_buf, max_chars, val, &num_chars);
-        ink_assert(out_buf);
-      } else {
-        out_buf   = (char *)record_not_found_msg;
-        num_chars = record_not_found_chars;
-      }
-    } else if (LOG_FLOAT == stype) {
-      // we assume MgmtFloat is at least a float for the conversion below
-      // (the conversion itself assumes a double because of the %e)
-      // if this ever changes we should modify accordingly
-      //
-      ink_assert(sizeof(double) >= sizeof(RecFloat));
-
-      RecFloat val = REC_readFloat(record, &found);
-
-      if (found) {
-        // snprintf does not support "%e" in the format
-        // and we want to use "%e" because it is the most concise
-        // notation
-
-        num_chars = snprintf(ascii_buf, sizeof(ascii_buf), "%e", val) + 1; // include eos
-
-        // the "%e" field above should take 13 characters at most
-        //
-        ink_assert(num_chars <= max_chars);
-
-        // the following should never be true
-        //
-        if (num_chars > max_chars) {
-          // data does not fit, output asterisks
-          out_buf   = "***";
-          num_chars = ::strlen(out_buf) + 1;
-        } else {
-          out_buf = ascii_buf;
-        }
-      } else {
-        out_buf   = (char *)record_not_found_msg;
-        num_chars = record_not_found_chars;
-      }
-    } else if (LOG_STRING == stype) {
-      out_buf = REC_readString(record, &found);
-
-      if (found) {
-        if (out_buf != nullptr && out_buf[0] != 0) {
-          num_chars = ::strlen(out_buf) + 1;
-          if (num_chars > max_chars) {
-            // truncate string and write ellipsis at the end
-            memcpy(ascii_buf, out_buf, max_chars - 4);
-            ascii_buf[max_chars - 1] = 0;
-            ascii_buf[max_chars - 2] = '.';
-            ascii_buf[max_chars - 3] = '.';
-            ascii_buf[max_chars - 4] = '.';
-            out_buf                  = ascii_buf;
-            num_chars                = max_chars;
-          }
-        } else {
-          out_buf   = "NULL";
-          num_chars = ::strlen(out_buf) + 1;
+  /* FIXME: Should there be no server transaction code if
+     the result comes out of the cache.  Right now we default
+     to FIN */
+  if (buf) {
+    int code = LOG_FINISH_FIN;
+    if (m_http_sm->t_state.current.server) {
+      switch (m_http_sm->t_state.current.server->state) {
+      case HttpTransact::ACTIVE_TIMEOUT:
+      case HttpTransact::INACTIVE_TIMEOUT:
+        code = LOG_FINISH_TIMEOUT;
+        break;
+      case HttpTransact::CONNECTION_ERROR:
+        code = LOG_FINISH_INTR;
+        break;
+      default:
+        if (m_http_sm->t_state.current.server->abort == HttpTransact::ABORTED) {
+          code = LOG_FINISH_INTR;
         }
-      } else {
-        out_buf   = (char *)record_not_found_msg;
-        num_chars = record_not_found_chars;
+        break;
       }
-    } else {
-      out_buf   = "INVALID_MgmtType";
-      num_chars = ::strlen(out_buf) + 1;
-      ink_assert(!"invalid MgmtType for requested record");
     }
-  }
 
-  ink_assert(num_chars <= max_chars);
-  memcpy(buf, out_buf, num_chars);
+    marshal_int(buf, code);
+  }
 
-  return max_chars;
+  return INK_MIN_ALIGN;
 }
 
 /*-------------------------------------------------------------------------
-  LogAccess::marshal_str
+-------------------------------------------------------------------------*/
+int
+LogAccess::marshal_proxy_host_port(char *buf)
+{
+  if (buf) {
+    uint16_t port = m_http_sm->t_state.request_data.incoming_port;
+    marshal_int(buf, port);
+  }
+  return INK_MIN_ALIGN;
+}
 
-  Copy the given string to the destination buffer, including the trailing
-  NULL.  For binary formatting, we need the NULL to distinguish the end of
-  the string, and we'll remove it for ascii formatting.
-  ASSUMES dest IS NOT NULL.
-  The array pointed to by dest must be at least padded_len in length.
+/*-------------------------------------------------------------------------
   -------------------------------------------------------------------------*/
 
-void
-LogAccess::marshal_str(char *dest, const char *source, int padded_len)
+int
+LogAccess::marshal_cache_result_code(char *buf)
 {
-  if (source == nullptr || source[0] == 0 || padded_len == 0) {
-    source = DEFAULT_STR;
-  }
-  ink_strlcpy(dest, source, padded_len);
-
-#ifdef DEBUG
-  //
-  // what padded_len should be, if there is no padding, is strlen()+1.
-  // if not, then we needed to pad and should touch the intermediate
-  // bytes to avoid UMR errors when the buffer is written.
-  //
-  size_t real_len = (::strlen(source) + 1);
-  while ((int)real_len < padded_len) {
-    dest[real_len] = '$';
-    real_len++;
+  if (buf) {
+    SquidLogCode code = m_http_sm->t_state.squid_codes.log_code;
+    marshal_int(buf, (int64_t)code);
   }
-#endif
+  return INK_MIN_ALIGN;
 }
 
 /*-------------------------------------------------------------------------
-  LogAccess::marshal_mem
-
-  This is a version of marshal_str that works with unterminated strings.
-  In this case, we'll copy the buffer and then add a trailing null that
-  the rest of the system assumes.
   -------------------------------------------------------------------------*/
 
-void
-LogAccess::marshal_mem(char *dest, const char *source, int actual_len, int padded_len)
+int
+LogAccess::marshal_cache_result_subcode(char *buf)
 {
-  if (source == nullptr || source[0] == 0 || actual_len == 0) {
-    source     = DEFAULT_STR;
-    actual_len = DEFAULT_STR_LEN;
-    ink_assert(actual_len < padded_len);
+  if (buf) {
+    SquidSubcode code = m_http_sm->t_state.squid_codes.subcode;
+    marshal_int(buf, (int64_t)code);
   }
-  memcpy(dest, source, actual_len);
-  dest[actual_len] = 0; // add terminating null
+  return INK_MIN_ALIGN;
+}
 
-#ifdef DEBUG
-  //
-  // what len should be, if there is no padding, is strlen()+1.
-  // if not, then we needed to pad and should touch the intermediate
-  // bytes to avoid UMR errors when the buffer is written.
-  //
-  int real_len = actual_len + 1;
-  while (real_len < padded_len) {
-    dest[real_len] = '$';
-    real_len++;
+/*-------------------------------------------------------------------------
+  -------------------------------------------------------------------------*/
+
+int
+LogAccess::marshal_cache_hit_miss(char *buf)
+{
+  if (buf) {
+    SquidHitMissCode code = m_http_sm->t_state.squid_codes.hit_miss_code;
+    marshal_int(buf, (int64_t)code);
   }
-#endif
+  return INK_MIN_ALIGN;
 }
 
 /*-------------------------------------------------------------------------
-  LogAccess::marshal_ip
-
-  Marshal an IP address in a reasonably compact way. If the address isn't
-  valid (NULL or not IP) then marshal an invalid address record.
   -------------------------------------------------------------------------*/
 
 int
-LogAccess::marshal_ip(char *dest, sockaddr const *ip)
+LogAccess::marshal_proxy_req_header_len(char *buf)
 {
-  LogFieldIpStorage data;
-  int len = sizeof(data._ip);
-  if (nullptr == ip) {
-    data._ip._family = AF_UNSPEC;
-  } else if (ats_is_ip4(ip)) {
-    if (dest) {
-      data._ip4._family = AF_INET;
-      data._ip4._addr   = ats_ip4_addr_cast(ip);
-    }
-    len = sizeof(data._ip4);
-  } else if (ats_is_ip6(ip)) {
-    if (dest) {
-      data._ip6._family = AF_INET6;
-      data._ip6._addr   = ats_ip6_addr_cast(ip);
+  if (buf) {
+    int64_t val = 0;
+    if (m_proxy_request) {
+      val = m_proxy_request->length_get();
     }
-    len = sizeof(data._ip6);
-  } else {
-    data._ip._family = AF_UNSPEC;
+    marshal_int(buf, val);
   }
+  return INK_MIN_ALIGN;
+}
 
-  if (dest) {
-    memcpy(dest, &data, len);
+/*-------------------------------------------------------------------------
+  -------------------------------------------------------------------------*/
+
+int
+LogAccess::marshal_proxy_req_content_len(char *buf)
+{
+  if (buf) {
+    int64_t val = 0;
+    if (m_proxy_request) {
+      val = m_http_sm->server_request_body_bytes;
+    }
+    marshal_int(buf, val);
   }
-  return INK_ALIGN_DEFAULT(len);
+  return INK_MIN_ALIGN;
 }
 
-inline int
-LogAccess::unmarshal_with_map(int64_t code, char *dest, int len, Ptr<LogFieldAliasMap> map, const char *msg)
+int
+LogAccess::marshal_proxy_req_squid_len(char *buf)
 {
-  long int codeStrLen = 0;
-
-  switch (map->asString(code, dest, len, (size_t *)&codeStrLen)) {
-  case LogFieldAliasMap::INVALID_INT:
-    if (msg) {
-      const int bufSize = 64;
-      char invalidCodeMsg[bufSize];
-      codeStrLen = snprintf(invalidCodeMsg, 64, "%s(%" PRId64 ")", msg, code);
-      if (codeStrLen < bufSize && codeStrLen < len) {
-        ink_strlcpy(dest, invalidCodeMsg, len);
-      } else {
-        codeStrLen = -1;
-      }
-    } else {
-      codeStrLen = -1;
+  if (buf) {
+    int64_t val = 0;
+    if (m_proxy_request) {
+      val = m_proxy_request->length_get() + m_http_sm->server_request_body_bytes;
     }
-    break;
-  case LogFieldAliasMap::BUFFER_TOO_SMALL:
-    codeStrLen = -1;
-    break;
+    marshal_int(buf, val);
   }
-
-  return codeStrLen;
+  return INK_MIN_ALIGN;
 }
 
-/*-------------------------------------------------------------------------
-  LogAccess::unmarshal_int
+// TODO: Change marshalling code to support both IPv4 and IPv6 addresses.
+int
+LogAccess::marshal_proxy_req_server_ip(char *buf)
+{
+  return marshal_ip(buf, m_http_sm->t_state.current.server != nullptr ? &m_http_sm->t_state.current.server->src_addr.sa : nullptr);
+}
 
-  Return the integer pointed at by the buffer and advance the buffer
-  pointer past the int.  The int will be converted back to host byte order.
-  -------------------------------------------------------------------------*/
+int
+LogAccess::marshal_proxy_req_server_port(char *buf)
+{
+  if (buf) {
+    uint16_t port = ntohs(m_http_sm->t_state.current.server != nullptr ? m_http_sm->t_state.current.server->src_addr.port() : 0);
+    marshal_int(buf, port);
+  }
+  return INK_MIN_ALIGN;
+}
 
-int64_t
-LogAccess::unmarshal_int(char **buf)
+int
+LogAccess::marshal_next_hop_ip(char *buf)
 {
-  ink_assert(buf != nullptr);
-  ink_assert(*buf != nullptr);
-  int64_t val;
+  return marshal_ip(buf, m_http_sm->t_state.current.server != nullptr ? &m_http_sm->t_state.current.server->dst_addr.sa : nullptr);
+}
 
-  // TODO: this used to do nthol, do we need to worrry? TS-1156.
-  val = *((int64_t *)(*buf));
-  *buf += INK_MIN_ALIGN;
-  return val;
+int
+LogAccess::marshal_next_hop_port(char *buf)
+{
+  if (buf) {
+    uint16_t port = ntohs(m_http_sm->t_state.current.server != nullptr ? m_http_sm->t_state.current.server->dst_addr.port() : 0);
+    marshal_int(buf, port);
+  }
+  return INK_MIN_ALIGN;
 }
 
 /*-------------------------------------------------------------------------
-  unmarshal_itoa
-
-  This routine provides a fast conversion from a binary int to a string.
-  It returns the number of characters formatted.  "dest" must point to the
-  LAST character of an array large enough to store the complete formatted
-  number.
   -------------------------------------------------------------------------*/
 
 int
-LogAccess::unmarshal_itoa(int64_t val, char *dest, int field_width, char leading_char)
+LogAccess::marshal_proxy_req_is_ssl(char *buf)
 {
-  ink_assert(dest != nullptr);
-
-  char *p = dest;
-
-  if (val <= 0) {
-    *p-- = '0';
-    while (dest - p < field_width) {
-      *p-- = leading_char;
-    }
-    return (int)(dest - p);
-  }
-
-  while (val) {
-    *p-- = '0' + (val % 10);
-    val /= 10;
-  }
-  while (dest - p < field_width) {
-    *p-- = leading_char;
+  if (buf) {
+    int64_t is_ssl;
+    is_ssl = m_http_sm->server_connection_is_ssl;
+    marshal_int(buf, is_ssl);
   }
-  return (int)(dest - p);
+  return INK_MIN_ALIGN;
 }
 
 /*-------------------------------------------------------------------------
-  unmarshal_itox
-
-  This routine provides a fast conversion from a binary int to a hex string.
-  It returns the number of characters formatted.  "dest" must point to the
-  LAST character of an array large enough to store the complete formatted
-  number.
   -------------------------------------------------------------------------*/
 
 int
-LogAccess::unmarshal_itox(int64_t val, char *dest, int field_width, char leading_char)
+LogAccess::marshal_proxy_hierarchy_route(char *buf)
 {
-  ink_assert(dest != nullptr);
-
-  char *p             = dest;
-  static char table[] = "0123456789abcdef?";
-
-  for (int i = 0; i < (int)(sizeof(int64_t) * 2); i++) {
-    *p-- = table[val & 0xf];
-    val >>= 4;
-  }
-  while (dest - p < field_width) {
-    *p-- = leading_char;
+  if (buf) {
+    SquidHierarchyCode code = m_http_sm->t_state.squid_codes.hier_code;
+    marshal_int(buf, (int64_t)code);
   }
-
-  return (int64_t)(dest - p);
+  return INK_MIN_ALIGN;
 }
 
 /*-------------------------------------------------------------------------
-  LogAccess::unmarshal_int_to_str
-
-  Return the string representation of the integer pointed at by buf.
   -------------------------------------------------------------------------*/
 
+// TODO: Change marshalling code to support both IPv4 and IPv6 addresses.
 int
-LogAccess::unmarshal_int_to_str(char **buf, char *dest, int len)
+LogAccess::marshal_server_host_ip(char *buf)
 {
-  ink_assert(buf != nullptr);
-  ink_assert(*buf != nullptr);
-  ink_assert(dest != nullptr);
-
-  char val_buf[128];
-  int64_t val = unmarshal_int(buf);
-  int val_len = unmarshal_itoa(val, val_buf + 127);
-
-  if (val_len < len) {
-    memcpy(dest, val_buf + 128 - val_len, val_len);
-    return val_len;
+  sockaddr const *ip = nullptr;
+  ip                 = &m_http_sm->t_state.server_info.dst_addr.sa;
+  if (!ats_is_ip(ip)) {
+    if (m_http_sm->t_state.current.server) {
+      ip = &m_http_sm->t_state.current.server->dst_addr.sa;
+      if (!ats_is_ip(ip)) {
+        ip = nullptr;
+      }
+    } else {
+      ip = nullptr;
+    }
   }
-  return -1;
+  return marshal_ip(buf, ip);
 }
 
 /*-------------------------------------------------------------------------
-  LogAccess::unmarshal_int_to_str_hex
-
-  Return the string representation (hexadecimal) of the integer pointed at by buf.
   -------------------------------------------------------------------------*/
 
 int
-LogAccess::unmarshal_int_to_str_hex(char **buf, char *dest, int len)
+LogAccess::marshal_server_host_name(char *buf)
 {
-  ink_assert(buf != nullptr);
-  ink_assert(*buf != nullptr);
-  ink_assert(dest != nullptr);
+  char *str = nullptr;
+  int len   = INK_MIN_ALIGN;
 
-  char val_buf[128];
-  int64_t val = unmarshal_int(buf);
-  int val_len = unmarshal_itox(val, val_buf + 127);
+  if (m_http_sm->t_state.current.server) {
+    str = m_http_sm->t_state.current.server->name;
+    len = LogAccess::strlen(str);
+  }
 
-  if (val_len < len) {
-    memcpy(dest, val_buf + 128 - val_len, val_len);
-    return val_len;
+  if (buf) {
+    marshal_str(buf, str, len);
   }
-  return -1;
+  return len;
 }
 
 /*-------------------------------------------------------------------------
-  LogAccess::unmarshal_str
-
-  Retrieve the string from the location pointed at by the buffer and
-  advance the pointer past the string.  The local strlen function is used
-  to advance the pointer, thus matching the corresponding strlen that was
-  used to lay the string into the buffer.
   -------------------------------------------------------------------------*/
 
 int
-LogAccess::unmarshal_str(char **buf, char *dest, int len, LogSlice *slice)
+LogAccess::marshal_server_resp_status_code(char *buf)
 {
-  ink_assert(buf != nullptr);
-  ink_assert(*buf != nullptr);
-  ink_assert(dest != nullptr);
-
-  char *val_buf = *buf;
-  int val_len   = (int)::strlen(val_buf);
-
-  *buf += LogAccess::strlen(val_buf); // this is how it was stored
-
-  if (slice && slice->m_enable) {
-    int offset, n;
-
-    n = slice->toStrOffset(val_len, &offset);
-    if (n <= 0) {
-      return 0;
-    }
-
-    if (n >= len) {
-      return -1;
+  if (buf) {
+    HTTPStatus status;
+    if (m_server_response) {
+      status = m_server_response->status_get();
+    } else {
+      status = HTTP_STATUS_NONE;
     }
-
-    memcpy(dest, (val_buf + offset), n);
-    return n;
+    marshal_int(buf, (int64_t)status);
   }
-
-  if (val_len < len) {
-    memcpy(dest, val_buf, val_len);
-    return val_len;
-  }
-  return -1;
+  return INK_MIN_ALIGN;
 }
 
+/*-------------------------------------------------------------------------
+  -------------------------------------------------------------------------*/
+
 int
-LogAccess::unmarshal_ttmsf(char **buf, char *dest, int len)
+LogAccess::marshal_server_resp_content_len(char *buf)
 {
-  ink_assert(buf != nullptr);
-  ink_assert(*buf != nullptr);
-  ink_assert(dest != nullptr);
-
-  int64_t val = unmarshal_int(buf);
-  double secs = (double)val / 1000;
-  int val_len = snprintf(dest, len, "%.3f", secs);
-  return val_len;
+  if (buf) {
+    int64_t val = 0;
+    if (m_server_response) {
+      val = m_http_sm->server_response_body_bytes;
+    }
+    marshal_int(buf, val);
+  }
+  return INK_MIN_ALIGN;
 }
 
+/*-------------------------------------------------------------------------
+  -------------------------------------------------------------------------*/
+
 int
-LogAccess::unmarshal_int_to_date_str(char **buf, char *dest, int len)
+LogAccess::marshal_server_resp_header_len(char *buf)
 {
-  ink_assert(buf != nullptr);
-  ink_assert(*buf != nullptr);
-  ink_assert(dest != nullptr);
-
-  int64_t value = unmarshal_int(buf);
-  char *strval  = LogUtils::timestamp_to_date_str(value);
-  int strlen    = (int)::strlen(strval);
-
-  memcpy(dest, strval, strlen);
-  return strlen;
+  if (buf) {
+    int64_t val = 0;
+    if (m_server_response) {
+      val = m_server_response->length_get();
+    }
+    marshal_int(buf, val);
+  }
+  return INK_MIN_ALIGN;
 }
 
 int
-LogAccess::unmarshal_int_to_time_str(char **buf, char *dest, int len)
+LogAccess::marshal_server_resp_squid_len(char *buf)
 {
-  ink_assert(buf != nullptr);
-  ink_assert(*buf != nullptr);
-  ink_assert(dest != nullptr);
-
-  int64_t value = unmarshal_int(buf);
-  char *strval  = LogUtils::timestamp_to_time_str(value);
-  int strlen    = (int)::strlen(strval);
-
-  memcpy(dest, strval, strlen);
-  return strlen;
+  if (buf) {
+    int64_t val = 0;
+    if (m_server_response) {
+      val = m_server_response->length_get() + m_http_sm->server_response_body_bytes;
+    }
+    marshal_int(buf, val);
+  }
+  return INK_MIN_ALIGN;
 }
 
 int
-LogAccess::unmarshal_int_to_netscape_str(char **buf, char *dest, int len)
+LogAccess::marshal_server_resp_http_version(char *buf)
 {
-  ink_assert(buf != nullptr);
-  ink_assert(*buf != nullptr);
-  ink_assert(dest != nullptr);
-
-  int64_t value = unmarshal_int(buf);
-  char *strval  = LogUtils::timestamp_to_netscape_str(value);
-  int strlen    = (int)::strlen(strval);
-
-  memcpy(dest, strval, strlen);
-  return strlen;
+  if (buf) {
+    int64_t major = 0;
+    int64_t minor = 0;
+    if (m_server_response) {
+      major = HTTP_MAJOR(m_server_response->version_get().m_version);
+      minor = HTTP_MINOR(m_server_response->version_get().m_version);
+    }
+    marshal_int(buf, major);
+    marshal_int((buf + INK_MIN_ALIGN), minor);
+  }
+  return (2 * INK_MIN_ALIGN);
 }
 
 /*-------------------------------------------------------------------------
-  LogAccess::unmarshal_http_method
+-------------------------------------------------------------------------*/
+int
+LogAccess::marshal_server_resp_time_ms(char *buf)
+{
+  if (buf) {
+    ink_hrtime elapsed = m_http_sm->milestones[TS_MILESTONE_SERVER_CLOSE] - m_http_sm->milestones[TS_MILESTONE_SERVER_CONNECT];
+    int64_t val        = (int64_t)ink_hrtime_to_msec(elapsed);
+    marshal_int(buf, val);
+  }
+  return INK_MIN_ALIGN;
+}
 
-  Retrieve the int pointed at by the buffer and treat as an HttpMethod
-  enumerated type.  Then lookup the string representation for that enum and
-  return the string.  Advance the buffer pointer past the enum.
-  -------------------------------------------------------------------------*/
-/*
 int
-LogAccess::unmarshal_http_method (char **buf, char *dest, int len)
+LogAccess::marshal_server_resp_time_s(char *buf)
 {
-    return unmarshal_str (buf, dest, len);
+  if (buf) {
+    ink_hrtime elapsed = m_http_sm->milestones[TS_MILESTONE_SERVER_CLOSE] - m_http_sm->milestones[TS_MILESTONE_SERVER_CONNECT];
+    int64_t val        = (int64_t)ink_hrtime_to_sec(elapsed);
+    marshal_int(buf, val);
+  }
+  return INK_MIN_ALIGN;
 }
-*/
-/*-------------------------------------------------------------------------
-  LogAccess::unmarshal_http_version
 
-  The http version is marshalled as two consecutive integers, the first for
-  the major number and the second for the minor number.  Retrieve both
-  numbers and return the result as "HTTP/major.minor".
+/*-------------------------------------------------------------------------
   -------------------------------------------------------------------------*/
 
 int
-LogAccess::unmarshal_http_version(char **buf, char *dest, int len)
+LogAccess::marshal_server_transact_count(char *buf)
 {
-  ink_assert(buf != nullptr);
-  ink_assert(*buf != nullptr);
-  ink_assert(dest != nullptr);
-
-  static const char *http = "HTTP/";
-  static int http_len     = (int)::strlen(http);
-
-  char val_buf[128];
-  char *p = val_buf;
-
-  memcpy(p, http, http_len);
-  p += http_len;
-
-  int res1 = unmarshal_int_to_str(buf, p, 128 - http_len);
-  if (res1 < 0) {
-    return -1;
-  }
-  p += res1;
-  *p++     = '.';
-  int res2 = unmarshal_int_to_str(buf, p, 128 - http_len - res1 - 1);
-  if (res2 < 0) {
-    return -1;
-  }
-
-  int val_len = http_len + res1 + res2 + 1;
-  if (val_len < len) {
-    memcpy(dest, val_buf, val_len);
-    return val_len;
+  if (buf) {
+    int64_t count;
+    count = m_http_sm->server_transact_count;
+    marshal_int(buf, count);
   }
-  return -1;
+  return INK_MIN_ALIGN;
 }
 
 /*-------------------------------------------------------------------------
-  LogAccess::unmarshal_http_text
-
-  The http text is simply the fields http_method (cqhm) + url (cqu) +
-  http_version (cqhv), all right next to each other, in that order.
   -------------------------------------------------------------------------*/
 
 int
-LogAccess::unmarshal_http_text(char **buf, char *dest, int len, LogSlice *slice)
+LogAccess::marshal_server_connect_attempts(char *buf)
 {
-  ink_assert(buf != nullptr);
-  ink_assert(*buf != nullptr);
-  ink_assert(dest != nullptr);
-
-  char *p = dest;
-
-  //    int res1 = unmarshal_http_method (buf, p, len);
-  int res1 = unmarshal_str(buf, p, len);
-  if (res1 < 0) {
-    return -1;
-  }
-  p += res1;
-  *p++     = ' ';
-  int res2 = unmarshal_str(buf, p, len - res1 - 1, slice);
-  if (res2 < 0) {
-    return -1;
-  }
-  p += res2;
-  *p++     = ' ';
-  int res3 = unmarshal_http_version(buf, p, len - res1 - res2 - 2);
-  if (res3 < 0) {
-    return -1;
+  if (buf) {
+    int64_t attempts = m_http_sm->t_state.current.attempts;
+    marshal_int(buf, attempts);
   }
-  return res1 + res2 + res3 + 2;
+  return INK_MIN_ALIGN;
 }
 
 /*-------------------------------------------------------------------------
-  LogAccess::unmarshal_http_status
-
-  An http response status code (pssc,sssc) is just an INT, but it's always
-  formatted with three digits and leading zeros.  So, we need a special
-  version of unmarshal_int_to_str that does this leading zero formatting.
   -------------------------------------------------------------------------*/
 
 int
-LogAccess::unmarshal_http_status(char **buf, char *dest, int len)
+LogAccess::marshal_cache_resp_status_code(char *buf)
 {
-  ink_assert(buf != nullptr);
-  ink_assert(*buf != nullptr);
-  ink_assert(dest != nullptr);
-
-  char val_buf[128];
-  int64_t val = unmarshal_int(buf);
-  int val_len = unmarshal_itoa(val, val_buf + 127, 3, '0');
-  if (val_len < len) {
-    memcpy(dest, val_buf + 128 - val_len, val_len);
-    return val_len;
+  if (buf) {
+    HTTPStatus status;
+    if (m_cache_response) {
+      status = m_cache_response->status_get();
+    } else {
+      status = HTTP_STATUS_NONE;
+    }
+    marshal_int(buf, (int64_t)status);
   }
-  return -1;
+  return INK_MIN_ALIGN;
 }
 
 /*-------------------------------------------------------------------------
-  LogAccess::unmarshal_ip
-
-  Retrieve an IP address directly.
   -------------------------------------------------------------------------*/
+
 int
-LogAccess::unmarshal_ip(char **buf, IpEndpoint *dest)
+LogAccess::marshal_cache_resp_content_len(char *buf)
 {
-  int len = sizeof(LogFieldIp); // of object processed.
-
-  ink_assert(buf != nullptr);
-  ink_assert(*buf != nullptr);
-  ink_assert(dest != nullptr);
+  if (buf) {
+    int64_t val = 0;
+    if (m_cache_response) {
+      val = m_http_sm->cache_response_body_bytes;
+    }
+    marshal_int(buf, val);
+  }
+  return INK_MIN_ALIGN;
+}
 
-  LogFieldIp *raw = reinterpret_cast<LogFieldIp *>(*buf);
-  if (AF_INET == raw->_family) {
-    LogFieldIp4 *ip4 = static_cast<LogFieldIp4 *>(raw);
-    ats_ip4_set(dest, ip4->_addr);
-    len = sizeof(*ip4);
-  } else if (AF_INET6 == raw->_family) {
-    LogFieldIp6 *ip6 = static_cast<LogFieldIp6 *>(raw);
-    ats_ip6_set(dest, ip6->_addr);
-    len = sizeof(*ip6);
-  } else {
-    ats_ip_invalidate(dest);
+int
+LogAccess::marshal_cache_resp_squid_len(char *buf)
+{
+  if (buf) {
+    int64_t val = 0;
+    if (m_cache_response) {
+      val = m_cache_response->length_get() + m_http_sm->cache_response_body_bytes;
+    }
+    marshal_int(buf, val);
   }
-  len = INK_ALIGN_DEFAULT(len);
-  *buf += len;
-  return len;
+  return INK_MIN_ALIGN;
 }
 
 /*-------------------------------------------------------------------------
-  LogAccess::unmarshal_ip_to_str
-
-  Retrieve the IP addresspointed at by the buffer and convert to a
-  string in standard format. The string is written to @a dest and its
-  length (not including nul) is returned. @a *buf is advanced.
   -------------------------------------------------------------------------*/
 
 int
-LogAccess::unmarshal_ip_to_str(char **buf, char *dest, int len)
+LogAccess::marshal_cache_resp_header_len(char *buf)
 {
-  IpEndpoint ip;
-  int zret = -1;
+  if (buf) {
+    int64_t val = 0;
+    if (m_cache_response) {
+      val = m_http_sm->cache_response_hdr_bytes;
+    }
+    marshal_int(buf, val);
+  }
+  return INK_MIN_ALIGN;
+}
 
-  if (len > 0) {
-    unmarshal_ip(buf, &ip);
-    if (!ats_is_ip(&ip)) {
-      *dest = '0';
-      zret  = 1;
-    } else if (ats_ip_ntop(&ip, dest, len)) {
-      zret = static_cast<int>(::strlen(dest));
+int
+LogAccess::marshal_cache_resp_http_version(char *buf)
+{
+  if (buf) {
+    int64_t major = 0;
+    int64_t minor = 0;
+    if (m_cache_response) {
+      major = HTTP_MAJOR(m_cache_response->version_get().m_version);
+      minor = HTTP_MINOR(m_cache_response->version_get().m_version);
     }
+    marshal_int(buf, major);
+    marshal_int((buf + INK_MIN_ALIGN), minor);
   }
-  return zret;
+  return (2 * INK_MIN_ALIGN);
 }
 
-/*-------------------------------------------------------------------------
-  LogAccess::unmarshal_ip_to_hex
+int
+LogAccess::marshal_client_retry_after_time(char *buf)
+{
+  if (buf) {
+    int64_t crat = m_http_sm->t_state.congestion_control_crat;
+    marshal_int(buf, crat);
+  }
+  return INK_MIN_ALIGN;
+}
 
-  Retrieve the int pointed at by the buffer and treat as an IP
-  address.  Convert to a string in byte oriented hexadeciaml and
-  return the string.  Advance the buffer pointer.
-  -------------------------------------------------------------------------*/
+static LogCacheWriteCodeType
+convert_cache_write_code(HttpTransact::CacheWriteStatus_t t)
+{
+  LogCacheWriteCodeType code;
+  switch (t) {
+  case HttpTransact::NO_CACHE_WRITE:
+    code = LOG_CACHE_WRITE_NONE;
+    break;
+  case HttpTransact::CACHE_WRITE_LOCK_MISS:
+    code = LOG_CACHE_WRITE_LOCK_MISSED;
+    break;
+  case HttpTransact::CACHE_WRITE_IN_PROGRESS:
+    // Hack - the HttpSM doesn't record
+    //   cache write aborts currently so
+    //   if it's not complete declare it
+    //   aborted
+    code = LOG_CACHE_WRITE_LOCK_ABORTED;
+    break;
+  case HttpTransact::CACHE_WRITE_ERROR:
+    code = LOG_CACHE_WRITE_ERROR;
+    break;
+  case HttpTransact::CACHE_WRITE_COMPLETE:
+    code = LOG_CACHE_WRITE_COMPLETE;
+    break;
+  default:
+    ink_assert(!"bad cache write code");
+    code = LOG_CACHE_WRITE_NONE;
+    break;
+  }
+
+  return code;
+}
 
 int
-LogAccess::unmarshal_ip_to_hex(char **buf, char *dest, int len)
+LogAccess::marshal_cache_write_code(char *buf)
 {
-  int zret = -1;
-  IpEndpoint ip;
+  if (buf) {
+    int code = convert_cache_write_code(m_http_sm->t_state.cache_info.write_status);
+    marshal_int(buf, code);
+  }
 
-  if (len > 0) {
-    unmarshal_ip(buf, &ip);
-    if (!ats_is_ip(&ip)) {
-      *dest = '0';
-      zret  = 1;
-    } else {
-      zret = ats_ip_to_hex(&ip.sa, dest, len);
-    }
+  return INK_MIN_ALIGN;
+}
+
+int
+LogAccess::marshal_cache_write_transform_code(char *buf)
+{
+  if (buf) {
+    int code = convert_cache_write_code(m_http_sm->t_state.cache_info.transform_write_status);
+    marshal_int(buf, code);
   }
-  return zret;
+
+  return INK_MIN_ALIGN;
 }
 
 /*-------------------------------------------------------------------------
-  LogAccess::unmarshal_hierarchy
-
-  Retrieve the int pointed at by the buffer and treat as a
-  SquidHierarchyCode.  Use this as an index into the local string
-  conversion tables and return the string equivalent to the enum.
-  Advance the buffer pointer.
   -------------------------------------------------------------------------*/
 
 int
-LogAccess::unmarshal_hierarchy(char **buf, char *dest, int len, Ptr<LogFieldAliasMap> map)
+LogAccess::marshal_transfer_time_ms(char *buf)
 {
-  ink_assert(buf != nullptr);
-  ink_assert(*buf != nullptr);
-  ink_assert(dest != nullptr);
+  if (buf) {
+    ink_hrtime elapsed = m_http_sm->milestones[TS_MILESTONE_SM_FINISH] - m_http_sm->milestones[TS_MILESTONE_SM_START];
+    int64_t val        = (int64_t)ink_hrtime_to_msec(elapsed);
+    marshal_int(buf, val);
+  }
+  return INK_MIN_ALIGN;
+}
 
-  return (LogAccess::unmarshal_with_map(unmarshal_int(buf), dest, len, map, "INVALID_CODE"));
+int
+LogAccess::marshal_transfer_time_s(char *buf)
+{
+  if (buf) {
+    ink_hrtime elapsed = m_http_sm->milestones[TS_MILESTONE_SM_FINISH] - m_http_sm->milestones[TS_MILESTONE_SM_START];
+    int64_t val        = (int64_t)ink_hrtime_to_sec(elapsed);
+    marshal_int(buf, val);
+  }
+  return INK_MIN_ALIGN;
 }
 
 /*-------------------------------------------------------------------------
-  LogAccess::unmarshal_finish_status
-
-  Retrieve the int pointed at by the buffer and treat as a finish code.
-  Use the enum as an index into a string table and return the string equiv
-  of the enum.  Advance the pointer.
+  Figure out the size of the object *on origin*. This is somewhat tricky
+  since there are many variations on how this can be calculated.
   -------------------------------------------------------------------------*/
-
 int
-LogAccess::unmarshal_finish_status(char **buf, char *dest, int len, Ptr<LogFieldAliasMap> map)
+LogAccess::marshal_file_size(char *buf)
 {
-  ink_assert(buf != nullptr);
-  ink_assert(*buf != nullptr);
-  ink_assert(dest != nullptr);
+  if (buf) {
+    MIMEField *fld;
+    HTTPHdr *hdr = m_server_response ? m_server_response : m_cache_response;
 
-  return (LogAccess::unmarshal_with_map(unmarshal_int(buf), dest, len, map, "UNKNOWN_FINISH_CODE"));
+    if (hdr && (fld = hdr->field_find(MIME_FIELD_CONTENT_RANGE, MIME_LEN_CONTENT_RANGE))) {
+      int len;
+      char *str = (char *)fld->value_get(&len);
+      char *pos = (char *)memchr(str, '/', len); // Find the /
+
+      // If the size is not /* (which means unknown) use it as the file_size.
+      if (pos && !memchr(pos + 1, '*', len - (pos + 1 - str))) {
+        marshal_int(buf, ink_atoi64(pos + 1, len - (pos + 1 - str)));
+      }
+    } else {
+      // This is semi-broken when we serveq zero length objects. See TS-2213
+      if (m_http_sm->server_response_body_bytes > 0) {
+        marshal_int(buf, m_http_sm->server_response_body_bytes);
+      } else if (m_http_sm->cache_response_body_bytes > 0) {
+        marshal_int(buf, m_http_sm->cache_response_body_bytes);
+      }
+    }
+  }
+  // Else, we don't set the value at all (so, -)
+
+  return INK_MIN_ALIGN;
 }
 
 /*-------------------------------------------------------------------------
-  LogAccess::unmarshal_cache_code
-
-  Retrieve the int pointed at by the buffer and treat as a SquidLogCode.
-  Use this to index into the local string tables and return the string
-  equiv of the enum.  Advance the pointer.
   -------------------------------------------------------------------------*/
 
 int
-LogAccess::unmarshal_cache_code(char **buf, char *dest, int len, Ptr<LogFieldAliasMap> map)
+LogAccess::marshal_client_http_connection_id(char *buf)
 {
-  ink_assert(buf != nullptr);
-  ink_assert(*buf != nullptr);
-  ink_assert(dest != nullptr);
-
-  return (LogAccess::unmarshal_with_map(unmarshal_int(buf), dest, len, map, "ERROR_UNKNOWN"));
+  if (buf) {
+    int64_t id = 0;
+    if (m_http_sm) {
+      id = m_http_sm->client_connection_id();
+    }
+    marshal_int(buf, id);
+  }
+  return INK_MIN_ALIGN;
 }
 
 /*-------------------------------------------------------------------------
-  LogAccess::unmarshal_cache_hit_miss
-
-  Retrieve the int pointed at by the buffer and treat as a SquidHitMissCode.
-  Use this to index into the local string tables and return the string
-  equiv of the enum.  Advance the pointer.
   -------------------------------------------------------------------------*/
 
 int
-LogAccess::unmarshal_cache_hit_miss(char **buf, char *dest, int len, Ptr<LogFieldAliasMap> map)
+LogAccess::marshal_client_http_transaction_id(char *buf)
 {
-  ink_assert(buf != nullptr);
-  ink_assert(*buf != nullptr);
-  ink_assert(dest != nullptr);
-
-  return (LogAccess::unmarshal_with_map(unmarshal_int(buf), dest, len, map, "HIT_MISS_UNKNOWN"));
+  if (buf) {
+    int64_t id = 0;
+    if (m_http_sm) {
+      id = m_http_sm->client_transaction_id();
+    }
+    marshal_int(buf, id);
+  }
+  return INK_MIN_ALIGN;
 }
 
 /*-------------------------------------------------------------------------
-  LogAccess::unmarshal_entry_type
   -------------------------------------------------------------------------*/
 
 int
-LogAccess::unmarshal_entry_type(char **buf, char *dest, int len, Ptr<LogFieldAliasMap> map)
+LogAccess::marshal_http_header_field(LogField::Container container, char *field, char *buf)
 {
-  ink_assert(buf != nullptr);
-  ink_assert(*buf != nullptr);
-  ink_assert(dest != nullptr);
+  char *str        = nullptr;
+  int padded_len   = INK_MIN_ALIGN;
+  int actual_len   = 0;
+  bool valid_field = false;
+  HTTPHdr *header;
+
+  switch (container) {
+  case LogField::CQH:
+    header = m_client_request;
+    break;
 
-  return (LogAccess::unmarshal_with_map(unmarshal_int(buf), dest, len, map, "UNKNOWN_ENTRY_TYPE"));
-}
+  case LogField::PSH:
+    header = m_proxy_response;
+    break;
 
-int
-LogAccess::unmarshal_cache_write_code(char **buf, char *dest, int len, Ptr<LogFieldAliasMap> map)
-{
-  ink_assert(buf != nullptr);
-  ink_assert(*buf != nullptr);
-  ink_assert(dest != nullptr);
+  case LogField::PQH:
+    header = m_proxy_request;
+    break;
 
-  return (LogAccess::unmarshal_with_map(unmarshal_int(buf), dest, len, map, "UNKNOWN_CACHE_WRITE_CODE"));
-}
+  case LogField::SSH:
+    header = m_server_response;
+    break;
 
-int
-LogAccess::unmarshal_record(char **buf, char *dest, int len)
-{
-  ink_assert(buf != nullptr);
-  ink_assert(*buf != nullptr);
-  ink_assert(dest != nullptr);
+  case LogField::CSSH:
+    header = m_cache_response;
+    break;
 
-  char *val_buf = *buf;
-  int val_len   = (int)::strlen(val_buf);
-  *buf += MARSHAL_RECORD_LENGTH; // this is how it was stored
-  if (val_len < len) {
-    memcpy(dest, val_buf, val_len);
-    return val_len;
+  default:
+    header = nullptr;
+    break;
   }
-  return -1;
-}
 
-/*-------------------------------------------------------------------------
-  resolve_logfield_string
+  if (header) {
+    MIMEField *fld = header->field_find(field, (int)::strlen(field));
+    if (fld) {
+      valid_field = true;
 
-  This function resolves the given custom log format string using the given
-  LogAccess context and returns the resulting string, which is ats_malloc'd.
-  The caller is responsible for ats_free'ing the return result.  If there are
-  any problems, NULL is returned.
-  -------------------------------------------------------------------------*/
-char *
-resolve_logfield_string(LogAccess *context, const char *format_str)
-{
-  if (!context) {
-    Debug("log-resolve", "No context to resolve?");
-    return nullptr;
+      // Loop over dups, marshalling each one into the buffer and
+      // summing up their length
+      //
+      int running_len = 0;
+      while (fld) {
+        str = (char *)fld->value_get(&actual_len);
+        if (buf) {
+          memcpy(buf, str, actual_len);
+          buf += actual_len;
+        }
+        running_len += actual_len;
+        fld = fld->m_next_dup;
+
+        // Dups need to be comma separated.  So if there's another
+        // dup, then add a comma and a space ...
+        //
+        if (fld != nullptr) {
+          if (buf) {
+            memcpy(buf, ", ", 2);
+            buf += 2;
+          }
+          running_len += 2;
+        }
+      }
+
+      // Done with all dups.  Ensure that the string is terminated
+      // and that the running_len is padded.
+      //
+      if (buf) {
+        *buf = '\0';
+        buf++;
+      }
+      running_len += 1;
+      padded_len = round_strlen(running_len);
+
+// Note: marshal_string fills the padding to
+//  prevent purify UMRs so we do it here too
+//  since we always pass the unpadded length on
+//  our calls to marshal string
+#ifdef DEBUG
+      if (buf) {
+        int pad_len = padded_len - running_len;
+        for (int i = 0; i < pad_len; i++) {
+          *buf = '$';
+          buf++;
+        }
+      }
+#endif
+    }
   }
 
-  if (!format_str) {
-    Debug("log-resolve", "No format to resolve?");
-    return nullptr;
+  if (valid_field == false) {
+    padded_len = INK_MIN_ALIGN;
+    if (buf) {
+      marshal_str(buf, nullptr, padded_len);
+    }
   }
 
-  Debug("log-resolve", "Resolving: %s", format_str);
+  return (padded_len);
+}
 
-  //
-  // Divide the format string into two parts: one for the printf-style
-  // string and one for the symbols.
-  //
-  char *printf_str = nullptr;
-  char *fields_str = nullptr;
-  int n_fields     = LogFormat::parse_format_string(format_str, &printf_str, &fields_str);
+int
+LogAccess::marshal_http_header_field_escapify(LogField::Container container, char *field, char *buf)
+{
+  char *str = nullptr, *new_str = nullptr;
+  int padded_len = INK_MIN_ALIGN;
+  int actual_len = 0, new_len = 0;
+  bool valid_field = false;
+  HTTPHdr *header;
+
+  switch (container) {
+  case LogField::ECQH:
+    header = m_client_request;
+    break;
 
-  //
-  // Perhaps there were no fields to resolve?  Then just return the
-  // format_str. Nothing to free here either.
-  //
-  if (!n_fields) {
-    Debug("log-resolve", "No fields found; returning copy of format_str");
-    ats_free(printf_str);
-    ats_free(fields_str);
-    return ats_strdup(format_str);
+  case LogField::EPSH:
+    header = m_proxy_response;
+    break;
+
+  case LogField::EPQH:
+    header = m_proxy_request;
+    break;
+
+  case LogField::ESSH:
+    header = m_server_response;
+    break;
+
+  case LogField::ECSSH:
+    header = m_cache_response;
+    break;
+
+  default:
+    header = nullptr;
+    break;
   }
 
-  Debug("log-resolve", "%d fields: %s", n_fields, fields_str);
-  Debug("log-resolve", "printf string: %s", printf_str);
+  if (header) {
+    MIMEField *fld = header->field_find(field, (int)::strlen(field));
+    if (fld) {
+      valid_field = true;
 
-  LogFieldList fields;
-  bool contains_aggregates;
-  int field_count = LogFormat::parse_symbol_string(fields_str, &fields, &contains_aggregates);
+      // Loop over dups, marshalling each one into the buffer and
+      // summing up their length
+      //
+      int running_len = 0;
+      while (fld) {
+        str     = (char *)fld->value_get(&actual_len);
+        new_str = LogUtils::escapify_url(&m_arena, str, actual_len, &new_len);
+        if (buf) {
+          memcpy(buf, new_str, new_len);
+          buf += new_len;
+        }
+        running_len += new_len;
+        fld = fld->m_next_dup;
+
+        // Dups need to be comma separated.  So if there's another
+        // dup, then add a comma and an escapified space ...
+        constexpr const char SEP[] = ",%20";
+        constexpr size_t SEP_LEN   = sizeof(SEP) - 1;
+        if (fld != nullptr) {
+          if (buf) {
+            memcpy(buf, SEP, SEP_LEN);
+            buf += SEP_LEN;
+          }
+          running_len += SEP_LEN;
+        }
+      }
 
-  if (field_count != n_fields) {
-    Error("format_str contains %d invalid field symbols", n_fields - field_count);
-    ats_free(printf_str);
-    ats_free(fields_str);
-    return nullptr;
+      // Done with all dups.  Ensure that the string is terminated
+      // and that the running_len is padded.
+      //
+      if (buf) {
+        *buf = '\0';
+        buf++;
+      }
+      running_len += 1;
+      padded_len = round_strlen(running_len);
+
+// Note: marshal_string fills the padding to
+//  prevent purify UMRs so we do it here too
+//  since we always pass the unpadded length on
+//  our calls to marshal string
+#ifdef DEBUG
+      if (buf) {
+        int pad_len = padded_len - running_len;
+        for (int i = 0; i < pad_len; i++) {
+          *buf = '$';
+          buf++;
+        }
+      }
+#endif
+    }
   }
-  //
-  // Ok, now marshal the data out of the LogAccess object and into a
-  // temporary storage buffer.  Make sure the LogAccess context is
-  // initialized first.
-  //
-  Debug("log-resolve", "Marshaling data from LogAccess into buffer ...");
-  context->init();
-  unsigned bytes_needed = fields.marshal_len(context);
-  char *buf             = (char *)ats_malloc(bytes_needed);
-  unsigned bytes_used   = fields.marshal(context, buf);
 
-  ink_assert(bytes_needed == bytes_used);
-  Debug("log-resolve", "    %u bytes marshalled", bytes_used);
+  if (valid_field == false) {
+    padded_len = INK_MIN_ALIGN;
+    if (buf) {
+      marshal_str(buf, nullptr, padded_len);
+    }
+  }
 
-  //
-  // Now we can "unmarshal" the data from the buffer into a string,
-  // combining it with the data from the printf string.  The problem is,
-  // we're not sure how much space it will take when it's unmarshalled.
-  // So, we'll just guess.
-  //
-  char *result = (char *)ats_malloc(8192);
-  unsigned bytes_resolved =
-    LogBuffer::resolve_custom_entry(&fields, printf_str, buf, result, 8191, LogUtils::timestamp(), 0, LOG_SEGMENT_VERSION);
-  ink_assert(bytes_resolved < 8192);
+  return (padded_len);
+}
 
-  if (!bytes_resolved) {
-    ats_free(result);
-    result = nullptr;
-  } else {
-    result[bytes_resolved] = 0; // NULL terminate
+int
+LogAccess::marshal_milestone(TSMilestonesType ms, char *buf)
+{
+  if (buf) {
+    int64_t val = ink_hrtime_to_msec(m_http_sm->milestones[ms]);
+    marshal_int(buf, val);
   }
+  return INK_MIN_ALIGN;
+}
 
-  ats_free(printf_str);
-  ats_free(fields_str);
-  ats_free(buf);
+int
+LogAccess::marshal_milestone_fmt_sec(TSMilestonesType type, char *buf)
+{
+  if (buf) {
+    ink_hrtime tsec = ink_hrtime_to_sec(m_http_sm->milestones[type]);
+    marshal_int(buf, tsec);
+  }
+  return INK_MIN_ALIGN;
+}
 
-  return result;
+int
+LogAccess::marshal_milestone_fmt_ms(TSMilestonesType type, char *buf)
+{
+  if (buf) {
+    ink_hrtime tmsec = ink_hrtime_to_msec(m_http_sm->milestones[type]);
+    marshal_int(buf, tmsec);
+  }
+  return INK_MIN_ALIGN;
+}
+
+int
+LogAccess::marshal_milestone_diff(TSMilestonesType ms1, TSMilestonesType ms2, char *buf)
+{
+  if (buf) {
+    ink_hrtime elapsed = m_http_sm->milestones.elapsed(ms2, ms1);
+    int64_t val        = (int64_t)ink_hrtime_to_msec(elapsed);
+    marshal_int(buf, val);
+  }
+  return INK_MIN_ALIGN;
 }
diff --git a/proxy/logging/LogAccess.h b/proxy/logging/LogAccess.h
index bfcefb4..20e4b9e 100644
--- a/proxy/logging/LogAccess.h
+++ b/proxy/logging/LogAccess.h
@@ -1,6 +1,7 @@
 /** @file
 
-  A brief file description
+  This class extends the logging system interface as implemented by the
+  HttpStateMachineGet class.
 
   @section license License
 
@@ -21,31 +22,24 @@
   limitations under the License.
  */
 
-/***************************************************************************
- Logging - LogAccess.h
-
-
- ***************************************************************************/
 #pragma once
-#include "ts/ink_platform.h"
-#include "ts/ink_inet.h"
+
 #include "ts/ink_align.h"
 #include "LogField.h"
 
+class HTTPHdr;
+class HttpSM;
+class IpClass;
+union IpEndpoint;
+
 /*-------------------------------------------------------------------------
   LogAccess
 
   This class defines the logging system interface for extracting
   information required to process a log entry.  This accessor is
-  implemented as an abstract base class with virtual functions for
+  implemented as an abstract base class with functions for
   accessing the data based on the derived class.
 
-  NOTE that some accessors are declared non-virtual, meaning that they
-  provide an implementation in this base class that is NOT TO BE
-  OVERRIDDEN.  This is used for fields that are already part of the
-  LogEntryHeader, and thus do not need to be marshalled.  So, these
-  functions do nothing and return 0.
-
   Each function has the ability to marshal its data into a buffer that is
   provided, and return the number of bytes that were marshalled.  In the
   absence of a marshalling buffer, the routines will simply return the
@@ -95,41 +89,6 @@
 
 extern char INVALID_STR[];
 
-#define DEFAULT_INT_FIELD  \
-  {                        \
-    if (buf) {             \
-      int64_t i = 0;       \
-      marshal_int(buf, i); \
-    }                      \
-    return INK_MIN_ALIGN;  \
-  }
-
-#define DEFAULT_STR_FIELD         \
-  {                               \
-    char *str = NULL;             \
-    int len   = INK_MIN_ALIGN;    \
-    if (buf) {                    \
-      marshal_str(buf, str, len); \
-    }                             \
-    return len;                   \
-  }
-
-#define DEFAULT_IP_FIELD           \
-  {                                \
-    int len = sizeof(LogFieldIp);  \
-    if (buf) {                     \
-      len = marshal_ip(buf, NULL); \
-    }                              \
-    return len;                    \
-  }
-
-// should be at least 22 bytes to always accommodate a converted
-// MgmtInt, MgmtIntCounter or MgmtFloat. 22 bytes is enough for 64 bit
-// ints + sign + eos, and enough for %e floating point representation
-// + eos
-//
-#define MARSHAL_RECORD_LENGTH 32
-
 enum LogEntryType {
   LOG_ENTRY_HTTP = 0,
   N_LOG_ENTRY_TYPES,
@@ -152,144 +111,140 @@ enum LogCacheWriteCodeType {
 };
 
 class LogAccess
-{ // Abstract Base Class
+{
 public:
   inkcoreapi
   LogAccess()
-    : initialized(false)
   {
   }
 
-  inkcoreapi virtual ~LogAccess() {}
-  inkcoreapi virtual void init();
+  LogAccess(HttpSM *sm);
 
-  virtual LogEntryType entry_type() const = 0;
+  inkcoreapi ~LogAccess() {}
+  inkcoreapi void init();
 
   //
   // client -> proxy fields
   //
-  inkcoreapi virtual int marshal_client_host_ip(char *);                // STR
-  inkcoreapi virtual int marshal_host_interface_ip(char *);             // STR
-  inkcoreapi virtual int marshal_client_host_port(char *);              // INT
-  inkcoreapi virtual int marshal_client_auth_user_name(char *);         // STR
-  inkcoreapi virtual int marshal_client_req_timestamp_sec(char *);      // INT
-  inkcoreapi virtual int marshal_client_req_timestamp_ms(char *);       // INT
-  inkcoreapi virtual int marshal_client_req_text(char *);               // STR
-  inkcoreapi virtual int marshal_client_req_http_method(char *);        // STR
-  inkcoreapi virtual int marshal_client_req_url(char *);                // STR
-  inkcoreapi virtual int marshal_client_req_url_canon(char *);          // STR
-  inkcoreapi virtual int marshal_client_req_unmapped_url_canon(char *); // STR
-  inkcoreapi virtual int marshal_client_req_unmapped_url_path(char *);  // STR
-  inkcoreapi virtual int marshal_client_req_unmapped_url_host(char *);  // STR
-  inkcoreapi virtual int marshal_client_req_url_path(char *);           // STR
-  inkcoreapi virtual int marshal_client_req_url_scheme(char *);         // STR
-  inkcoreapi virtual int marshal_client_req_http_version(char *);       // INT
-  inkcoreapi virtual int marshal_client_req_protocol_version(char *);   // STR
-  inkcoreapi virtual int marshal_client_req_squid_len(char *);          // INT
-  inkcoreapi virtual int marshal_client_req_header_len(char *);         // INT
-  inkcoreapi virtual int marshal_client_req_content_len(char *);        // INT
-  inkcoreapi virtual int marshal_client_req_tcp_reused(char *);         // INT
-  inkcoreapi virtual int marshal_client_req_is_ssl(char *);             // INT
-  inkcoreapi virtual int marshal_client_req_ssl_reused(char *);         // INT
-  inkcoreapi virtual int marshal_client_security_protocol(char *);      // STR
-  inkcoreapi virtual int marshal_client_security_cipher_suite(char *);  // STR
-  inkcoreapi virtual int marshal_client_finish_status_code(char *);     // INT
-  inkcoreapi virtual int marshal_client_req_id(char *);                 // INT
-  inkcoreapi virtual int marshal_client_req_uuid(char *);               // STR
-  inkcoreapi virtual int marshal_client_rx_error_code(char *);          // STR
-  inkcoreapi virtual int marshal_client_tx_error_code(char *);          // STR
+  inkcoreapi int marshal_client_host_ip(char *);                // STR
+  inkcoreapi int marshal_host_interface_ip(char *);             // STR
+  inkcoreapi int marshal_client_host_port(char *);              // INT
+  inkcoreapi int marshal_client_auth_user_name(char *);         // STR
+  inkcoreapi int marshal_client_req_timestamp_sec(char *);      // INT
+  inkcoreapi int marshal_client_req_timestamp_ms(char *);       // INT
+  inkcoreapi int marshal_client_req_text(char *);               // STR
+  inkcoreapi int marshal_client_req_http_method(char *);        // STR
+  inkcoreapi int marshal_client_req_url(char *);                // STR
+  inkcoreapi int marshal_client_req_url_canon(char *);          // STR
+  inkcoreapi int marshal_client_req_unmapped_url_canon(char *); // STR
+  inkcoreapi int marshal_client_req_unmapped_url_path(char *);  // STR
+  inkcoreapi int marshal_client_req_unmapped_url_host(char *);  // STR
+  inkcoreapi int marshal_client_req_url_path(char *);           // STR
+  inkcoreapi int marshal_client_req_url_scheme(char *);         // STR
+  inkcoreapi int marshal_client_req_http_version(char *);       // INT
+  inkcoreapi int marshal_client_req_protocol_version(char *);   // STR
+  inkcoreapi int marshal_client_req_squid_len(char *);          // INT
+  inkcoreapi int marshal_client_req_header_len(char *);         // INT
+  inkcoreapi int marshal_client_req_content_len(char *);        // INT
+  inkcoreapi int marshal_client_req_tcp_reused(char *);         // INT
+  inkcoreapi int marshal_client_req_is_ssl(char *);             // INT
+  inkcoreapi int marshal_client_req_ssl_reused(char *);         // INT
+  inkcoreapi int marshal_client_security_protocol(char *);      // STR
+  inkcoreapi int marshal_client_security_cipher_suite(char *);  // STR
+  inkcoreapi int marshal_client_finish_status_code(char *);     // INT
+  inkcoreapi int marshal_client_req_id(char *);                 // INT
+  inkcoreapi int marshal_client_req_uuid(char *);               // STR
+  inkcoreapi int marshal_client_rx_error_code(char *);          // STR
+  inkcoreapi int marshal_client_tx_error_code(char *);          // STR
 
   //
   // proxy -> client fields
   //
-  inkcoreapi virtual int marshal_proxy_resp_content_type(char *);  // STR
-  inkcoreapi virtual int marshal_proxy_resp_reason_phrase(char *); // STR
-  inkcoreapi virtual int marshal_proxy_resp_squid_len(char *);     // INT
-  inkcoreapi virtual int marshal_proxy_resp_content_len(char *);   // INT
-  inkcoreapi virtual int marshal_proxy_resp_status_code(char *);   // INT
-  inkcoreapi virtual int marshal_proxy_resp_header_len(char *);    // INT
-  inkcoreapi virtual int marshal_proxy_finish_status_code(char *); // INT
-  inkcoreapi virtual int marshal_cache_result_code(char *);        // INT
-  inkcoreapi virtual int marshal_cache_result_subcode(char *);     // INT
-  inkcoreapi virtual int marshal_proxy_host_port(char *);          // INT
-  inkcoreapi virtual int marshal_cache_hit_miss(char *);           // INT
+  inkcoreapi int marshal_proxy_resp_content_type(char *);  // STR
+  inkcoreapi int marshal_proxy_resp_reason_phrase(char *); // STR
+  inkcoreapi int marshal_proxy_resp_squid_len(char *);     // INT
+  inkcoreapi int marshal_proxy_resp_content_len(char *);   // INT
+  inkcoreapi int marshal_proxy_resp_status_code(char *);   // INT
+  inkcoreapi int marshal_proxy_resp_header_len(char *);    // INT
+  inkcoreapi int marshal_proxy_finish_status_code(char *); // INT
+  inkcoreapi int marshal_cache_result_code(char *);        // INT
+  inkcoreapi int marshal_cache_result_subcode(char *);     // INT
+  inkcoreapi int marshal_proxy_host_port(char *);          // INT
+  inkcoreapi int marshal_cache_hit_miss(char *);           // INT
 
   //
   // proxy -> server fields
   //
-  inkcoreapi virtual int marshal_proxy_req_header_len(char *);  // INT
-  inkcoreapi virtual int marshal_proxy_req_squid_len(char *);   // INT
-  inkcoreapi virtual int marshal_proxy_req_content_len(char *); // INT
-  inkcoreapi virtual int marshal_proxy_req_server_ip(char *);   // INT
-  inkcoreapi virtual int marshal_proxy_req_server_port(char *); // INT
-  inkcoreapi virtual int marshal_proxy_hierarchy_route(char *); // INT
-  inkcoreapi virtual int marshal_next_hop_ip(char *);           // STR
-  inkcoreapi virtual int marshal_next_hop_port(char *);         // INT
-  inkcoreapi virtual int marshal_proxy_host_name(char *);       // STR
-  inkcoreapi virtual int marshal_proxy_host_ip(char *);         // STR
-  inkcoreapi virtual int marshal_proxy_req_is_ssl(char *);      // INT
+  inkcoreapi int marshal_proxy_req_header_len(char *);  // INT
+  inkcoreapi int marshal_proxy_req_squid_len(char *);   // INT
+  inkcoreapi int marshal_proxy_req_content_len(char *); // INT
+  inkcoreapi int marshal_proxy_req_server_ip(char *);   // INT
+  inkcoreapi int marshal_proxy_req_server_port(char *); // INT
+  inkcoreapi int marshal_proxy_hierarchy_route(char *); // INT
+  inkcoreapi int marshal_next_hop_ip(char *);           // STR
+  inkcoreapi int marshal_next_hop_port(char *);         // INT
+  inkcoreapi int marshal_proxy_host_name(char *);       // STR
+  inkcoreapi int marshal_proxy_host_ip(char *);         // STR
+  inkcoreapi int marshal_proxy_req_is_ssl(char *);      // INT
 
   //
   // server -> proxy fields
   //
-  inkcoreapi virtual int marshal_server_host_ip(char *);           // INT
-  inkcoreapi virtual int marshal_server_host_name(char *);         // STR
-  inkcoreapi virtual int marshal_server_resp_status_code(char *);  // INT
-  inkcoreapi virtual int marshal_server_resp_squid_len(char *);    // INT
-  inkcoreapi virtual int marshal_server_resp_content_len(char *);  // INT
-  inkcoreapi virtual int marshal_server_resp_header_len(char *);   // INT
-  inkcoreapi virtual int marshal_server_resp_http_version(char *); // INT
-  inkcoreapi virtual int marshal_server_resp_time_ms(char *);      // INT
-  inkcoreapi virtual int marshal_server_resp_time_s(char *);       // INT
-  inkcoreapi virtual int marshal_server_transact_count(char *);    // INT
-  inkcoreapi virtual int marshal_server_connect_attempts(char *);  // INT
+  inkcoreapi int marshal_server_host_ip(char *);           // INT
+  inkcoreapi int marshal_server_host_name(char *);         // STR
+  inkcoreapi int marshal_server_resp_status_code(char *);  // INT
+  inkcoreapi int marshal_server_resp_squid_len(char *);    // INT
+  inkcoreapi int marshal_server_resp_content_len(char *);  // INT
+  inkcoreapi int marshal_server_resp_header_len(char *);   // INT
+  inkcoreapi int marshal_server_resp_http_version(char *); // INT
+  inkcoreapi int marshal_server_resp_time_ms(char *);      // INT
+  inkcoreapi int marshal_server_resp_time_s(char *);       // INT
+  inkcoreapi int marshal_server_transact_count(char *);    // INT
+  inkcoreapi int marshal_server_connect_attempts(char *);  // INT
 
   //
   // cache -> client fields
   //
-  inkcoreapi virtual int marshal_cache_resp_status_code(char *);  // INT
-  inkcoreapi virtual int marshal_cache_resp_squid_len(char *);    // INT
-  inkcoreapi virtual int marshal_cache_resp_content_len(char *);  // INT
-  inkcoreapi virtual int marshal_cache_resp_header_len(char *);   // INT
-  inkcoreapi virtual int marshal_cache_resp_http_version(char *); // INT
-
-  inkcoreapi virtual void set_client_req_url(char *, int){};                // STR
-  inkcoreapi virtual void set_client_req_url_canon(char *, int){};          // STR
-  inkcoreapi virtual void set_client_req_unmapped_url_canon(char *, int){}; // STR
-  inkcoreapi virtual void set_client_req_unmapped_url_path(char *, int){};  // STR
-  inkcoreapi virtual void set_client_req_unmapped_url_host(char *, int){};  // STR
-  inkcoreapi virtual void set_client_req_url_path(char *, int){};           // STR
+  inkcoreapi int marshal_cache_resp_status_code(char *);  // INT
+  inkcoreapi int marshal_cache_resp_squid_len(char *);    // INT
+  inkcoreapi int marshal_cache_resp_content_len(char *);  // INT
+  inkcoreapi int marshal_cache_resp_header_len(char *);   // INT
+  inkcoreapi int marshal_cache_resp_http_version(char *); // INT
+
+  inkcoreapi void set_client_req_url(char *, int);                // STR
+  inkcoreapi void set_client_req_url_canon(char *, int);          // STR
+  inkcoreapi void set_client_req_unmapped_url_canon(char *, int); // STR
+  inkcoreapi void set_client_req_unmapped_url_path(char *, int);  // STR
+  inkcoreapi void set_client_req_unmapped_url_host(char *, int);  // STR
+  inkcoreapi void set_client_req_url_path(char *, int);           // STR
 
   //
   // congestion control -- client_retry_after_time
   //
-  inkcoreapi virtual int marshal_client_retry_after_time(char *); // INT
+  inkcoreapi int marshal_client_retry_after_time(char *); // INT
 
   //
   // cache write fields
   //
-  inkcoreapi virtual int marshal_cache_write_code(char *);           // INT
-  inkcoreapi virtual int marshal_cache_write_transform_code(char *); // INT
+  inkcoreapi int marshal_cache_write_code(char *);           // INT
+  inkcoreapi int marshal_cache_write_transform_code(char *); // INT
 
   // other fields
   //
-  inkcoreapi virtual int marshal_transfer_time_ms(char *);           // INT
-  inkcoreapi virtual int marshal_transfer_time_s(char *);            // INT
-  inkcoreapi virtual int marshal_file_size(char *);                  // INT
-  inkcoreapi virtual int marshal_plugin_identity_id(char *);         // INT
-  inkcoreapi virtual int marshal_plugin_identity_tag(char *);        // STR
-  inkcoreapi virtual int marshal_process_uuid(char *);               // STR
-  inkcoreapi virtual int marshal_client_http_connection_id(char *);  // INT
-  inkcoreapi virtual int marshal_client_http_transaction_id(char *); // INT
-
-  // These two are special, in that they are shared for all log types / implementations
-  inkcoreapi int marshal_entry_type(char *);                     // INT
-  inkcoreapi virtual int marshal_cache_lookup_url_canon(char *); // STR
+  inkcoreapi int marshal_transfer_time_ms(char *);           // INT
+  inkcoreapi int marshal_transfer_time_s(char *);            // INT
+  inkcoreapi int marshal_file_size(char *);                  // INT
+  inkcoreapi int marshal_plugin_identity_id(char *);         // INT
+  inkcoreapi int marshal_plugin_identity_tag(char *);        // STR
+  inkcoreapi int marshal_process_uuid(char *);               // STR
+  inkcoreapi int marshal_client_http_connection_id(char *);  // INT
+  inkcoreapi int marshal_client_http_transaction_id(char *); // INT
+  inkcoreapi int marshal_cache_lookup_url_canon(char *);     // STR
 
   // named fields from within a http header
   //
-  inkcoreapi virtual int marshal_http_header_field(LogField::Container container, char *field, char *buf);
-  inkcoreapi virtual int marshal_http_header_field_escapify(LogField::Container container, char *field, char *buf);
+  inkcoreapi int marshal_http_header_field(LogField::Container container, char *field, char *buf);
+  inkcoreapi int marshal_http_header_field_escapify(LogField::Container container, char *field, char *buf);
 
   //
   // named records.config int variables
@@ -309,14 +264,14 @@ public:
   //
   // milestones access
   //
-  inkcoreapi virtual int marshal_milestone(TSMilestonesType ms, char *buf);
-  inkcoreapi virtual int marshal_milestone_fmt_sec(TSMilestonesType ms, char *buf);
-  inkcoreapi virtual int marshal_milestone_fmt_squid(TSMilestonesType ms, char *buf);
-  inkcoreapi virtual int marshal_milestone_fmt_netscape(TSMilestonesType ms, char *buf);
-  inkcoreapi virtual int marshal_milestone_fmt_date(TSMilestonesType ms, char *buf);
-  inkcoreapi virtual int marshal_milestone_fmt_time(TSMilestonesType ms, char *buf);
-  inkcoreapi virtual int marshal_milestone_diff(TSMilestonesType ms1, TSMilestonesType ms2, char *buf);
-
+  inkcoreapi int marshal_milestone(TSMilestonesType ms, char *buf);
+  inkcoreapi int marshal_milestone_fmt_sec(TSMilestonesType ms, char *buf);
+  inkcoreapi int marshal_milestone_fmt_squid(TSMilestonesType ms, char *buf);
+  inkcoreapi int marshal_milestone_fmt_netscape(TSMilestonesType ms, char *buf);
+  inkcoreapi int marshal_milestone_fmt_date(TSMilestonesType ms, char *buf);
+  inkcoreapi int marshal_milestone_fmt_time(TSMilestonesType ms, char *buf);
+  inkcoreapi int marshal_milestone_fmt_ms(TSMilestonesType ms, char *buf);
+  inkcoreapi int marshal_milestone_diff(TSMilestonesType ms1, TSMilestonesType ms2, char *buf);
   //
   // unmarshalling routines
   //
@@ -343,7 +298,6 @@ public:
   static int unmarshal_finish_status(char **buf, char *dest, int len, Ptr<LogFieldAliasMap> map);
   static int unmarshal_cache_code(char **buf, char *dest, int len, Ptr<LogFieldAliasMap> map);
   static int unmarshal_cache_hit_miss(char **buf, char *dest, int len, Ptr<LogFieldAliasMap> map);
-  static int unmarshal_entry_type(char **buf, char *dest, int len, Ptr<LogFieldAliasMap> map);
   static int unmarshal_cache_write_code(char **buf, char *dest, int len, Ptr<LogFieldAliasMap> map);
   static int unmarshal_client_protocol_stack(char **buf, char *dest, int len, Ptr<LogFieldAliasMap> map);
 
@@ -364,14 +318,45 @@ public:
   inkcoreapi static void marshal_mem(char *dest, const char *source, int actual_len, int padded_len);
   inkcoreapi static int marshal_ip(char *dest, sockaddr const *ip);
 
-  bool initialized;
-
   // noncopyable
   // -- member functions that are not allowed --
   LogAccess(const LogAccess &rhs) = delete;      // no copies
   LogAccess &operator=(LogAccess &rhs) = delete; // or assignment
 
 private:
+  HttpSM *m_http_sm;
+
+  Arena m_arena;
+
+  HTTPHdr *m_client_request;
+  HTTPHdr *m_proxy_response;
+  HTTPHdr *m_proxy_request;
+  HTTPHdr *m_server_response;
+  HTTPHdr *m_cache_response;
+
+  char *m_client_req_url_str;
+  int m_client_req_url_len;
+  char *m_client_req_url_canon_str;
+  int m_client_req_url_canon_len;
+  char *m_client_req_unmapped_url_canon_str;
+  int m_client_req_unmapped_url_canon_len;
+  char *m_client_req_unmapped_url_path_str;
+  int m_client_req_unmapped_url_path_len;
+  char *m_client_req_unmapped_url_host_str;
+  int m_client_req_unmapped_url_host_len;
+  char const *m_client_req_url_path_str;
+  int m_client_req_url_path_len;
+  char *m_proxy_resp_content_type_str;
+  int m_proxy_resp_content_type_len;
+  char *m_proxy_resp_reason_phrase_str;
+  int m_proxy_resp_reason_phrase_len;
+  char *m_cache_lookup_url_canon_str;
+  int m_cache_lookup_url_canon_len;
+
+  void validate_unmapped_url(void);
+  void validate_unmapped_url_path(void);
+
+  void validate_lookup_url(void);
 };
 
 inline int
diff --git a/proxy/logging/LogAccessHttp.cc b/proxy/logging/LogAccessHttp.cc
deleted file mode 100644
index 1234c32..0000000
--- a/proxy/logging/LogAccessHttp.cc
+++ /dev/null
@@ -1,1801 +0,0 @@
-/** @file
-
-  A brief file description
-
-  @section license License
-
-  Licensed to the Apache Software Foundation (ASF) under one
-  or more contributor license agreements.  See the NOTICE file
-  distributed with this work for additional information
-  regarding copyright ownership.  The ASF licenses this file
-  to you 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
-
-      http://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.
- */
-
-/***************************************************************************
- LogAccessHttp.cc
-
- This file defines the Http implementation of a LogAccess object, and
- implements the accessor functions using information about an Http state
- machine.
-
-
- ***************************************************************************/
-#include "ts/ink_platform.h"
-#include "LogAccessHttp.h"
-#include "http/HttpSM.h"
-#include "MIME.h"
-#include "HTTP.h"
-#include "LogUtils.h"
-#include "LogObject.h"
-#include "LogConfig.h"
-#include "Log.h"
-#include "I_Machine.h"
-
-/*-------------------------------------------------------------------------
-  LogAccessHttp
-
-  Initialize the private data members and assert that we got a valid state
-  machine pointer.
-  -------------------------------------------------------------------------*/
-
-LogAccessHttp::LogAccessHttp(HttpSM *sm)
-  : m_http_sm(sm),
-    m_arena(),
-    m_client_request(nullptr),
-    m_proxy_response(nullptr),
-    m_proxy_request(nullptr),
-    m_server_response(nullptr),
-    m_cache_response(nullptr),
-    m_client_req_url_str(nullptr),
-    m_client_req_url_len(0),
-    m_client_req_url_canon_str(nullptr),
-    m_client_req_url_canon_len(0),
-    m_client_req_unmapped_url_canon_str(nullptr),
-    m_client_req_unmapped_url_canon_len(0),
-    m_client_req_unmapped_url_path_str(nullptr),
-    m_client_req_unmapped_url_path_len(0),
-    m_client_req_unmapped_url_host_str(nullptr),
-    m_client_req_unmapped_url_host_len(0),
-    m_client_req_url_path_str(nullptr),
-    m_client_req_url_path_len(0),
-    m_proxy_resp_content_type_str(nullptr),
-    m_proxy_resp_content_type_len(0),
-    m_proxy_resp_reason_phrase_str(nullptr),
-    m_proxy_resp_reason_phrase_len(0),
-    m_cache_lookup_url_canon_str(nullptr),
-    m_cache_lookup_url_canon_len(0)
-{
-  ink_assert(m_http_sm != nullptr);
-}
-
-/*-------------------------------------------------------------------------
-  LogAccessHttp::~LogAccessHttp
-
-  Deallocate space for any strings allocated in the init routine.
-  -------------------------------------------------------------------------*/
-
-LogAccessHttp::~LogAccessHttp() {}
-
-/*-------------------------------------------------------------------------
-  LogAccessHttp::init
-
-  Build some strings that will come in handy for processing later, such as
-  URL.  This saves us from having to build the strings twice: once to
-  compute their length and a second time to actually marshal them.  We also
-  initialize local pointers to each of the 4 http headers.  However, there
-  is no guarantee that these headers will all be valid, so we must always
-  check the validity of these pointers before using them.
-  -------------------------------------------------------------------------*/
-
-#define HIDDEN_CONTENT_TYPE "@Content-Type"
-#define HIDDEN_CONTENT_TYPE_LEN 13
-
-void
-LogAccessHttp::init()
-{
-  HttpTransact::HeaderInfo *hdr = &(m_http_sm->t_state.hdr_info);
-
-  if (hdr->client_request.valid()) {
-    m_client_request = &(hdr->client_request);
-
-    // make a copy of the incoming url into the arena
-    const char *url_string_ref = m_client_request->url_string_get_ref(&m_client_req_url_len);
-    m_client_req_url_str       = m_arena.str_alloc(m_client_req_url_len + 1);
-    memcpy(m_client_req_url_str, url_string_ref, m_client_req_url_len);
-    m_client_req_url_str[m_client_req_url_len] = '\0';
-
-    m_client_req_url_canon_str =
-      LogUtils::escapify_url(&m_arena, m_client_req_url_str, m_client_req_url_len, &m_client_req_url_canon_len);
-    m_client_req_url_path_str = m_client_request->path_get(&m_client_req_url_path_len);
-  }
-
-  if (hdr->client_response.valid()) {
-    m_proxy_response = &(hdr->client_response);
-    MIMEField *field = m_proxy_response->field_find(MIME_FIELD_CONTENT_TYPE, MIME_LEN_CONTENT_TYPE);
-    if (field) {
-      m_proxy_resp_content_type_str = (char *)field->value_get(&m_proxy_resp_content_type_len);
-      //
-      // here is the assert
-      //
-      // assert (m_proxy_resp_content_type_str[0] >= 'A' && m_proxy_resp_content_type_str[0] <= 'z');
-      LogUtils::remove_content_type_attributes(m_proxy_resp_content_type_str, &m_proxy_resp_content_type_len);
-    } else {
-      // If Content-Type field is missing, check for @Content-Type
-      field = m_proxy_response->field_find(HIDDEN_CONTENT_TYPE, HIDDEN_CONTENT_TYPE_LEN);
-      if (field) {
-        m_proxy_resp_content_type_str = (char *)field->value_get(&m_proxy_resp_content_type_len);
-        LogUtils::remove_content_type_attributes(m_proxy_resp_content_type_str, &m_proxy_resp_content_type_len);
-      }
-    }
-    m_proxy_resp_reason_phrase_str = (char *)m_proxy_response->reason_get(&m_proxy_resp_reason_phrase_len);
-  }
-  if (hdr->server_request.valid()) {
-    m_proxy_request = &(hdr->server_request);
-  }
-  if (hdr->server_response.valid()) {
-    m_server_response = &(hdr->server_response);
-  }
-  if (hdr->cache_response.valid()) {
-    m_cache_response = &(hdr->cache_response);
-  }
-}
-
-/*-------------------------------------------------------------------------
-  The set routines ...
-
-  These routines are used by the WIPE_FIELD_VALUE filter to replace the original req url
-  strings with the WIPED req strings.
-  -------------------------------------------------------------------------*/
-
-void
-LogAccessHttp::set_client_req_url(char *buf, int len)
-{
-  if (buf) {
-    m_client_req_url_len = len;
-    ink_strlcpy(m_client_req_url_str, buf, m_client_req_url_len + 1);
-  }
-}
-
-void
-LogAccessHttp::set_client_req_url_canon(char *buf, int len)
-{
-  if (buf) {
-    m_client_req_url_canon_len = len;
-    ink_strlcpy(m_client_req_url_canon_str, buf, m_client_req_url_canon_len + 1);
-  }
-}
-
-void
-LogAccessHttp::set_client_req_unmapped_url_canon(char *buf, int len)
-{
-  if (buf) {
-    m_client_req_unmapped_url_canon_len = len;
-    ink_strlcpy(m_client_req_unmapped_url_canon_str, buf, m_client_req_unmapped_url_canon_len + 1);
-  }
-}
-
-void
-LogAccessHttp::set_client_req_unmapped_url_path(char *buf, int len)
-{
-  if (buf) {
-    m_client_req_unmapped_url_path_len = len;
-    ink_strlcpy(m_client_req_unmapped_url_path_str, buf, m_client_req_unmapped_url_path_len + 1);
-  }
-}
-
-void
-LogAccessHttp::set_client_req_unmapped_url_host(char *buf, int len)
-{
-  if (buf) {
-    m_client_req_unmapped_url_host_len = len;
-    ink_strlcpy(m_client_req_unmapped_url_host_str, buf, m_client_req_unmapped_url_host_len + 1);
-  }
-}
-
-void
-LogAccessHttp::set_client_req_url_path(char *buf, int len)
-{
-  //?? use m_client_req_unmapped_url_path_str for now..may need to enhance later..
-  if (buf) {
-    m_client_req_url_path_len = len;
-    ink_strlcpy(m_client_req_unmapped_url_path_str, buf, m_client_req_url_path_len + 1);
-  }
-}
-
-/*-------------------------------------------------------------------------
-  The marshalling routines ...
-
-  We know that m_http_sm is a valid pointer (we assert so in the ctor), but
-  we still need to check the other header pointers before using them in the
-  routines.
-  -------------------------------------------------------------------------*/
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-int
-LogAccessHttp::marshal_plugin_identity_id(char *buf)
-{
-  if (buf) {
-    marshal_int(buf, m_http_sm->plugin_id);
-  }
-  return INK_MIN_ALIGN;
-}
-
-int
-LogAccessHttp::marshal_plugin_identity_tag(char *buf)
-{
-  int len         = INK_MIN_ALIGN;
-  const char *tag = m_http_sm->plugin_tag;
-
-  if (!tag) {
-    tag = "*";
-  } else {
-    len = LogAccess::strlen(tag);
-  }
-
-  if (buf) {
-    marshal_str(buf, tag, len);
-  }
-
-  return len;
-}
-
-int
-LogAccessHttp::marshal_client_host_ip(char *buf)
-{
-  return marshal_ip(buf, &m_http_sm->t_state.client_info.src_addr.sa);
-}
-
-int
-LogAccessHttp::marshal_host_interface_ip(char *buf)
-{
-  return marshal_ip(buf, &m_http_sm->t_state.client_info.dst_addr.sa);
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-int
-LogAccessHttp::marshal_cache_lookup_url_canon(char *buf)
-{
-  int len = INK_MIN_ALIGN;
-
-  validate_lookup_url();
-  if (m_cache_lookup_url_canon_str == INVALID_STR) {
-    // If the lookup URL isn't populated, we'll fall back to the request URL.
-    len = marshal_client_req_url_canon(buf);
-  } else {
-    len = round_strlen(m_cache_lookup_url_canon_len + 1); // +1 for eos
-    if (buf) {
-      marshal_mem(buf, m_cache_lookup_url_canon_str, m_cache_lookup_url_canon_len, len);
-    }
-  }
-
-  return len;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_client_host_port(char *buf)
-{
-  if (buf) {
-    uint16_t port = ntohs(m_http_sm->t_state.client_info.src_addr.port());
-    marshal_int(buf, port);
-  }
-  return INK_MIN_ALIGN;
-}
-
-/*-------------------------------------------------------------------------
-  user authenticated to the proxy (RFC931)
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_client_auth_user_name(char *buf)
-{
-  char *str = nullptr;
-  int len   = INK_MIN_ALIGN;
-
-  // Jira TS-40:
-  // NOTE: Authentication related code and modules were removed/disabled.
-  //       Uncomment code path below when re-added/enabled.
-  /*if (m_http_sm->t_state.auth_params.user_name) {
-    str = m_http_sm->t_state.auth_params.user_name;
-    len = LogAccess::strlen(str);
-    } */
-  if (buf) {
-    marshal_str(buf, str, len);
-  }
-  return len;
-}
-
-/*-------------------------------------------------------------------------
-  Private utility function to validate m_client_req_unmapped_url_canon_str &
-  m_client_req_unmapped_url_canon_len fields.
-  -------------------------------------------------------------------------*/
-
-void
-LogAccessHttp::validate_unmapped_url()
-{
-  if (m_client_req_unmapped_url_canon_str == nullptr) {
-    // prevent multiple validations
-    m_client_req_unmapped_url_canon_str = INVALID_STR;
-
-    if (m_http_sm->t_state.unmapped_url.valid()) {
-      int unmapped_url_len;
-      char *unmapped_url = m_http_sm->t_state.unmapped_url.string_get_ref(&unmapped_url_len);
-
-      if (unmapped_url && unmapped_url[0] != 0) {
-        m_client_req_unmapped_url_canon_str =
-          LogUtils::escapify_url(&m_arena, unmapped_url, unmapped_url_len, &m_client_req_unmapped_url_canon_len);
-      }
-    }
-  }
-}
-
-/*-------------------------------------------------------------------------
-  Private utility function to validate m_client_req_unmapped_url_path_str &
-  m_client_req_unmapped_url_path_len fields.
-  -------------------------------------------------------------------------*/
-
-void
-LogAccessHttp::validate_unmapped_url_path()
-{
-  int len;
-  char *c;
-
-  if (m_client_req_unmapped_url_path_str == nullptr && m_client_req_unmapped_url_host_str == nullptr) {
-    // Use unmapped canonical URL as default
-    m_client_req_unmapped_url_path_str = m_client_req_unmapped_url_canon_str;
-    m_client_req_unmapped_url_path_len = m_client_req_unmapped_url_canon_len;
-    // Incase the code below fails, we prevent it from being used.
-    m_client_req_unmapped_url_host_str = INVALID_STR;
-
-    if (m_client_req_unmapped_url_path_len >= 6) { // xxx:// - minimum schema size
-      c = (char *)memchr((void *)m_client_req_unmapped_url_path_str, ':', m_client_req_unmapped_url_path_len - 1);
-      if (c && (len = (int)(c - m_client_req_unmapped_url_path_str)) <= 5) { // 5 - max schema size
-        if (len + 2 <= m_client_req_unmapped_url_canon_len && c[1] == '/' && c[2] == '/') {
-          len += 3; // Skip "://"
-          m_client_req_unmapped_url_host_str = &m_client_req_unmapped_url_canon_str[len];
-          m_client_req_unmapped_url_host_len = m_client_req_unmapped_url_path_len - len;
-          // Attempt to find first '/' in the path
-          if (m_client_req_unmapped_url_host_len > 0 && (c = (char *)memchr((void *)m_client_req_unmapped_url_host_str, '/',
-                                                                            m_client_req_unmapped_url_path_len)) != nullptr) {
-            m_client_req_unmapped_url_host_len = (int)(c - m_client_req_unmapped_url_host_str);
-            m_client_req_unmapped_url_path_str = &m_client_req_unmapped_url_host_str[m_client_req_unmapped_url_host_len];
-            m_client_req_unmapped_url_path_len = m_client_req_unmapped_url_path_len - len - m_client_req_unmapped_url_host_len;
-          }
-        }
-      }
-    }
-  }
-}
-
-/*-------------------------------------------------------------------------
-  Private utility function to validate m_cache_lookup_url_canon_str &
-  m_cache_lookup__url_canon_len fields.
-  -------------------------------------------------------------------------*/
-void
-LogAccessHttp::validate_lookup_url()
-{
-  if (m_cache_lookup_url_canon_str == nullptr) {
-    // prevent multiple validations
-    m_cache_lookup_url_canon_str = INVALID_STR;
-
-    if (m_http_sm->t_state.cache_info.lookup_url_storage.valid()) {
-      int lookup_url_len;
-      char *lookup_url = m_http_sm->t_state.cache_info.lookup_url_storage.string_get_ref(&lookup_url_len);
-
-      if (lookup_url && lookup_url[0] != 0) {
-        m_cache_lookup_url_canon_str = LogUtils::escapify_url(&m_arena, lookup_url, lookup_url_len, &m_cache_lookup_url_canon_len);
-      }
-    }
-  }
-}
-
-/*-------------------------------------------------------------------------
-  This is the method, url, and version all rolled into one.  Use the
-  respective marshalling routines to do the job.
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_client_req_text(char *buf)
-{
-  int len = marshal_client_req_http_method(nullptr) + marshal_client_req_url(nullptr) + marshal_client_req_http_version(nullptr);
-
-  if (buf) {
-    int offset = 0;
-    offset += marshal_client_req_http_method(&buf[offset]);
-    offset += marshal_client_req_url(&buf[offset]);
-    offset += marshal_client_req_http_version(&buf[offset]);
-    len = offset;
-  }
-  return len;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_client_req_timestamp_sec(char *buf)
-{
-  return marshal_milestone_fmt_sec(TS_MILESTONE_UA_BEGIN, buf);
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_client_req_timestamp_ms(char *buf)
-{
-  return marshal_milestone_fmt_ms(TS_MILESTONE_UA_BEGIN, buf);
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_client_req_http_method(char *buf)
-{
-  char *str = nullptr;
-  int alen  = 0;
-  int plen  = INK_MIN_ALIGN;
-
-  if (m_client_request) {
-    str = (char *)m_client_request->method_get(&alen);
-
-    // calculate the the padded length only if the actual length
-    // is not zero. We don't want the padded length to be zero
-    // because marshal_mem should write the DEFAULT_STR to the
-    // buffer if str is nil, and we need room for this.
-    //
-    if (alen) {
-      plen = round_strlen(alen + 1); // +1 for trailing 0
-    }
-  }
-
-  if (buf) {
-    marshal_mem(buf, str, alen, plen);
-  }
-  return plen;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_client_req_url(char *buf)
-{
-  int len = round_strlen(m_client_req_url_len + 1); // +1 for trailing 0
-
-  if (buf) {
-    marshal_mem(buf, m_client_req_url_str, m_client_req_url_len, len);
-  }
-  return len;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_client_req_url_canon(char *buf)
-{
-  int len = round_strlen(m_client_req_url_canon_len + 1);
-
-  if (buf) {
-    marshal_mem(buf, m_client_req_url_canon_str, m_client_req_url_canon_len, len);
-  }
-  return len;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_client_req_unmapped_url_canon(char *buf)
-{
-  int len = INK_MIN_ALIGN;
-
-  validate_unmapped_url();
-  if (m_client_req_unmapped_url_canon_str == INVALID_STR) {
-    // If the unmapped URL isn't populated, we'll fall back to the original
-    // client URL. This helps for example server intercepts to continue to
-    // log the requests, even when there is no remap rule for it.
-    len = marshal_client_req_url_canon(buf);
-  } else {
-    len = round_strlen(m_client_req_unmapped_url_canon_len + 1); // +1 for eos
-    if (buf) {
-      marshal_mem(buf, m_client_req_unmapped_url_canon_str, m_client_req_unmapped_url_canon_len, len);
-    }
-  }
-
-  return len;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_client_req_unmapped_url_path(char *buf)
-{
-  int len = INK_MIN_ALIGN;
-
-  validate_unmapped_url();
-  validate_unmapped_url_path();
-
-  if (m_client_req_unmapped_url_path_str == INVALID_STR) {
-    len = marshal_client_req_url_path(buf);
-  } else {
-    len = round_strlen(m_client_req_unmapped_url_path_len + 1); // +1 for eos
-    if (buf) {
-      marshal_mem(buf, m_client_req_unmapped_url_path_str, m_client_req_unmapped_url_path_len, len);
-    }
-  }
-  return len;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_client_req_unmapped_url_host(char *buf)
-{
-  validate_unmapped_url();
-  validate_unmapped_url_path();
-
-  int len = round_strlen(m_client_req_unmapped_url_host_len + 1); // +1 for eos
-  if (buf) {
-    marshal_mem(buf, m_client_req_unmapped_url_host_str, m_client_req_unmapped_url_host_len, len);
-  }
-
-  return len;
-}
-
-int
-LogAccessHttp::marshal_client_req_url_path(char *buf)
-{
-  int len = round_strlen(m_client_req_url_path_len + 1);
-  if (buf) {
-    marshal_mem(buf, m_client_req_url_path_str, m_client_req_url_path_len, len);
-  }
-  return len;
-}
-
-int
-LogAccessHttp::marshal_client_req_url_scheme(char *buf)
-{
-  int scheme      = m_http_sm->t_state.orig_scheme;
-  const char *str = nullptr;
-  int alen;
-  int plen = INK_MIN_ALIGN;
-
-  // If the transaction aborts very early, the scheme may not be set, or so ASAN reports.
-  if (scheme >= 0) {
-    str  = hdrtoken_index_to_wks(scheme);
-    alen = hdrtoken_index_to_length(scheme);
-  } else {
-    str  = "UNKNOWN";
-    alen = strlen(str);
-  }
-
-  // calculate the the padded length only if the actual length
-  // is not zero. We don't want the padded length to be zero
-  // because marshal_mem should write the DEFAULT_STR to the
-  // buffer if str is nil, and we need room for this.
-  //
-  if (alen) {
-    plen = round_strlen(alen + 1); // +1 for trailing 0
-  }
-
-  if (buf) {
-    marshal_mem(buf, str, alen, plen);
-  }
-
-  return plen;
-}
-
-/*-------------------------------------------------------------------------
-  For this one we're going to marshal two INTs, one the first representing
-  the major number and the second representing the minor.
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_client_req_http_version(char *buf)
-{
-  if (buf) {
-    int64_t major = 0;
-    int64_t minor = 0;
-    if (m_client_request) {
-      HTTPVersion versionObject = m_client_request->version_get();
-      major                     = HTTP_MAJOR(versionObject.m_version);
-      minor                     = HTTP_MINOR(versionObject.m_version);
-    }
-    marshal_int(buf, major);
-    marshal_int((buf + INK_MIN_ALIGN), minor);
-  }
-  return (2 * INK_MIN_ALIGN);
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_client_req_protocol_version(char *buf)
-{
-  const char *protocol_str = m_http_sm->client_protocol;
-  int len                  = LogAccess::strlen(protocol_str);
-
-  // Set major & minor versions when protocol_str is not "http/2".
-  if (::strlen(protocol_str) == 4 && strncmp("http", protocol_str, 4) == 0) {
-    if (m_client_request) {
-      HTTPVersion versionObject = m_client_request->version_get();
-      int64_t major             = HTTP_MAJOR(versionObject.m_version);
-      int64_t minor             = HTTP_MINOR(versionObject.m_version);
-      if (major == 1 && minor == 1) {
-        protocol_str = "http/1.1";
-      } else if (major == 1 && minor == 0) {
-        protocol_str = "http/1.0";
-      } // else invalid http version
-    } else {
-      protocol_str = "*";
-    }
-
-    len = LogAccess::strlen(protocol_str);
-  }
-
-  if (buf) {
-    marshal_str(buf, protocol_str, len);
-  }
-
-  return len;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_client_req_header_len(char *buf)
-{
-  if (buf) {
-    int64_t len = 0;
-    if (m_client_request) {
-      len = m_client_request->length_get();
-    }
-    marshal_int(buf, len);
-  }
-  return INK_MIN_ALIGN;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_client_req_content_len(char *buf)
-{
-  if (buf) {
-    int64_t len = 0;
-    if (m_client_request) {
-      len = m_http_sm->client_request_body_bytes;
-    }
-    marshal_int(buf, len);
-  }
-  return INK_MIN_ALIGN;
-}
-
-int
-LogAccessHttp::marshal_client_req_squid_len(char *buf)
-{
-  if (buf) {
-    int64_t val = 0;
-    if (m_client_request) {
-      val = m_client_request->length_get() + m_http_sm->client_request_body_bytes;
-    }
-    marshal_int(buf, val);
-  }
-  return INK_MIN_ALIGN;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_client_req_tcp_reused(char *buf)
-{
-  if (buf) {
-    int64_t tcp_reused;
-    tcp_reused = m_http_sm->client_tcp_reused;
-    marshal_int(buf, tcp_reused);
-  }
-  return INK_MIN_ALIGN;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_client_req_is_ssl(char *buf)
-{
-  if (buf) {
-    int64_t is_ssl;
-    is_ssl = m_http_sm->client_connection_is_ssl;
-    marshal_int(buf, is_ssl);
-  }
-  return INK_MIN_ALIGN;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_client_req_ssl_reused(char *buf)
-{
-  if (buf) {
-    int64_t ssl_session_reused;
-    ssl_session_reused = m_http_sm->client_ssl_reused;
-    marshal_int(buf, ssl_session_reused);
-  }
-  return INK_MIN_ALIGN;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_client_finish_status_code(char *buf)
-{
-  if (buf) {
-    int code                                  = LOG_FINISH_FIN;
-    HttpTransact::AbortState_t cl_abort_state = m_http_sm->t_state.client_info.abort;
-    if (cl_abort_state == HttpTransact::ABORTED) {
-      // Check to see if the abort is due to a timeout
-      if (m_http_sm->t_state.client_info.state == HttpTransact::ACTIVE_TIMEOUT ||
-          m_http_sm->t_state.client_info.state == HttpTransact::INACTIVE_TIMEOUT) {
-        code = LOG_FINISH_TIMEOUT;
-      } else {
-        code = LOG_FINISH_INTR;
-      }
-    }
-    marshal_int(buf, code);
-  }
-  return INK_MIN_ALIGN;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_client_req_id(char *buf)
-{
-  if (buf) {
-    marshal_int(buf, m_http_sm->sm_id);
-  }
-  return INK_MIN_ALIGN;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_client_req_uuid(char *buf)
-{
-  char str[TS_CRUUID_STRING_LEN + 1];
-  const char *uuid = Machine::instance()->uuid.getString();
-  int len          = snprintf(str, sizeof(str), "%s-%" PRId64 "", uuid, m_http_sm->sm_id);
-
-  ink_assert(len <= TS_CRUUID_STRING_LEN);
-  len = round_strlen(len + 1);
-
-  if (buf) {
-    marshal_str(buf, str, len); // This will pad the remaning bytes properly ...
-  }
-
-  return len;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-// 1 ('S'/'T' flag) + 8 (Error Code) + 1 ('\0')
-static constexpr size_t MAX_PROXY_ERROR_CODE_SIZE = 10;
-
-int
-LogAccessHttp::marshal_client_rx_error_code(char *buf)
-{
-  char error_code[MAX_PROXY_ERROR_CODE_SIZE] = {0};
-  m_http_sm->t_state.client_info.rx_error_code.str(error_code, sizeof(error_code));
-  int round_len = LogAccess::strlen(error_code);
-
-  if (buf) {
-    marshal_str(buf, error_code, round_len);
-  }
-
-  return round_len;
-}
-
-int
-LogAccessHttp::marshal_client_tx_error_code(char *buf)
-{
-  char error_code[MAX_PROXY_ERROR_CODE_SIZE] = {0};
-  m_http_sm->t_state.client_info.tx_error_code.str(error_code, sizeof(error_code));
-  int round_len = LogAccess::strlen(error_code);
-
-  if (buf) {
-    marshal_str(buf, error_code, round_len);
-  }
-
-  return round_len;
-}
-
-/*-------------------------------------------------------------------------
--------------------------------------------------------------------------*/
-int
-LogAccessHttp::marshal_client_security_protocol(char *buf)
-{
-  const char *proto = m_http_sm->client_sec_protocol;
-  int round_len     = LogAccess::strlen(proto);
-
-  if (buf) {
-    marshal_str(buf, proto, round_len);
-  }
-
-  return round_len;
-}
-
-int
-LogAccessHttp::marshal_client_security_cipher_suite(char *buf)
-{
-  const char *cipher = m_http_sm->client_cipher_suite;
-  int round_len      = LogAccess::strlen(cipher);
-
-  if (buf) {
-    marshal_str(buf, cipher, round_len);
-  }
-
-  return round_len;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_proxy_resp_content_type(char *buf)
-{
-  int len = round_strlen(m_proxy_resp_content_type_len + 1);
-  if (buf) {
-    marshal_mem(buf, m_proxy_resp_content_type_str, m_proxy_resp_content_type_len, len);
-  }
-  return len;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_proxy_resp_reason_phrase(char *buf)
-{
-  int len = round_strlen(m_proxy_resp_reason_phrase_len + 1);
-  if (buf) {
-    marshal_mem(buf, m_proxy_resp_reason_phrase_str, m_proxy_resp_reason_phrase_len, len);
-  }
-  return len;
-}
-
-/*-------------------------------------------------------------------------
-  Squid returns the content-length + header length as the total length.
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_proxy_resp_squid_len(char *buf)
-{
-  if (buf) {
-    int64_t val = m_http_sm->client_response_hdr_bytes + m_http_sm->client_response_body_bytes;
-    marshal_int(buf, val);
-  }
-  return INK_MIN_ALIGN;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_proxy_resp_content_len(char *buf)
-{
-  if (buf) {
-    int64_t val = m_http_sm->client_response_body_bytes;
-    marshal_int(buf, val);
-  }
-  return INK_MIN_ALIGN;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_proxy_resp_status_code(char *buf)
-{
-  if (buf) {
-    HTTPStatus status;
-    if (m_proxy_response && m_client_request) {
-      if (m_client_request->version_get() >= HTTPVersion(1, 0)) {
-        status = m_proxy_response->status_get();
-      }
-      // INKqa10788
-      // For bad/incomplete request, the request version may be 0.9.
-      // However, we can still log the status code if there is one.
-      else if (m_proxy_response->valid()) {
-        status = m_proxy_response->status_get();
-      } else {
-        status = HTTP_STATUS_OK;
-      }
-    } else {
-      status = HTTP_STATUS_NONE;
-    }
-    marshal_int(buf, (int64_t)status);
-  }
-  return INK_MIN_ALIGN;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_proxy_resp_header_len(char *buf)
-{
-  if (buf) {
-    int64_t val = m_http_sm->client_response_hdr_bytes;
-    marshal_int(buf, val);
-  }
-  return INK_MIN_ALIGN;
-}
-
-int
-LogAccessHttp::marshal_proxy_finish_status_code(char *buf)
-{
-  /* FIXME: Should there be no server transaction code if
-     the result comes out of the cache.  Right now we default
-     to FIN */
-  if (buf) {
-    int code = LOG_FINISH_FIN;
-    if (m_http_sm->t_state.current.server) {
-      switch (m_http_sm->t_state.current.server->state) {
-      case HttpTransact::ACTIVE_TIMEOUT:
-      case HttpTransact::INACTIVE_TIMEOUT:
-        code = LOG_FINISH_TIMEOUT;
-        break;
-      case HttpTransact::CONNECTION_ERROR:
-        code = LOG_FINISH_INTR;
-        break;
-      default:
-        if (m_http_sm->t_state.current.server->abort == HttpTransact::ABORTED) {
-          code = LOG_FINISH_INTR;
-        }
-        break;
-      }
-    }
-
-    marshal_int(buf, code);
-  }
-
-  return INK_MIN_ALIGN;
-}
-
-/*-------------------------------------------------------------------------
--------------------------------------------------------------------------*/
-int
-LogAccessHttp::marshal_proxy_host_port(char *buf)
-{
-  if (buf) {
-    uint16_t port = m_http_sm->t_state.request_data.incoming_port;
-    marshal_int(buf, port);
-  }
-  return INK_MIN_ALIGN;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_cache_result_code(char *buf)
-{
-  if (buf) {
-    SquidLogCode code = m_http_sm->t_state.squid_codes.log_code;
-    marshal_int(buf, (int64_t)code);
-  }
-  return INK_MIN_ALIGN;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_cache_result_subcode(char *buf)
-{
-  if (buf) {
-    SquidSubcode code = m_http_sm->t_state.squid_codes.subcode;
-    marshal_int(buf, (int64_t)code);
-  }
-  return INK_MIN_ALIGN;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_cache_hit_miss(char *buf)
-{
-  if (buf) {
-    SquidHitMissCode code = m_http_sm->t_state.squid_codes.hit_miss_code;
-    marshal_int(buf, (int64_t)code);
-  }
-  return INK_MIN_ALIGN;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_proxy_req_header_len(char *buf)
-{
-  if (buf) {
-    int64_t val = 0;
-    if (m_proxy_request) {
-      val = m_proxy_request->length_get();
-    }
-    marshal_int(buf, val);
-  }
-  return INK_MIN_ALIGN;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_proxy_req_content_len(char *buf)
-{
-  if (buf) {
-    int64_t val = 0;
-    if (m_proxy_request) {
-      val = m_http_sm->server_request_body_bytes;
-    }
-    marshal_int(buf, val);
-  }
-  return INK_MIN_ALIGN;
-}
-
-int
-LogAccessHttp::marshal_proxy_req_squid_len(char *buf)
-{
-  if (buf) {
-    int64_t val = 0;
-    if (m_proxy_request) {
-      val = m_proxy_request->length_get() + m_http_sm->server_request_body_bytes;
-    }
-    marshal_int(buf, val);
-  }
-  return INK_MIN_ALIGN;
-}
-
-// TODO: Change marshalling code to support both IPv4 and IPv6 addresses.
-int
-LogAccessHttp::marshal_proxy_req_server_ip(char *buf)
-{
-  return marshal_ip(buf, m_http_sm->t_state.current.server != nullptr ? &m_http_sm->t_state.current.server->src_addr.sa : nullptr);
-}
-
-int
-LogAccessHttp::marshal_proxy_req_server_port(char *buf)
-{
-  if (buf) {
-    uint16_t port = ntohs(m_http_sm->t_state.current.server != nullptr ? m_http_sm->t_state.current.server->src_addr.port() : 0);
-    marshal_int(buf, port);
-  }
-  return INK_MIN_ALIGN;
-}
-
-int
-LogAccessHttp::marshal_next_hop_ip(char *buf)
-{
-  return marshal_ip(buf, m_http_sm->t_state.current.server != nullptr ? &m_http_sm->t_state.current.server->dst_addr.sa : nullptr);
-}
-
-int
-LogAccessHttp::marshal_next_hop_port(char *buf)
-{
-  if (buf) {
-    uint16_t port = ntohs(m_http_sm->t_state.current.server != nullptr ? m_http_sm->t_state.current.server->dst_addr.port() : 0);
-    marshal_int(buf, port);
-  }
-  return INK_MIN_ALIGN;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_proxy_req_is_ssl(char *buf)
-{
-  if (buf) {
-    int64_t is_ssl;
-    is_ssl = m_http_sm->server_connection_is_ssl;
-    marshal_int(buf, is_ssl);
-  }
-  return INK_MIN_ALIGN;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_proxy_hierarchy_route(char *buf)
-{
-  if (buf) {
-    SquidHierarchyCode code = m_http_sm->t_state.squid_codes.hier_code;
-    marshal_int(buf, (int64_t)code);
-  }
-  return INK_MIN_ALIGN;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-// TODO: Change marshalling code to support both IPv4 and IPv6 addresses.
-int
-LogAccessHttp::marshal_server_host_ip(char *buf)
-{
-  sockaddr const *ip = nullptr;
-  ip                 = &m_http_sm->t_state.server_info.dst_addr.sa;
-  if (!ats_is_ip(ip)) {
-    if (m_http_sm->t_state.current.server) {
-      ip = &m_http_sm->t_state.current.server->dst_addr.sa;
-      if (!ats_is_ip(ip)) {
-        ip = nullptr;
-      }
-    } else {
-      ip = nullptr;
-    }
-  }
-  return marshal_ip(buf, ip);
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_server_host_name(char *buf)
-{
-  char *str = nullptr;
-  int len   = INK_MIN_ALIGN;
-
-  if (m_http_sm->t_state.current.server) {
-    str = m_http_sm->t_state.current.server->name;
-    len = LogAccess::strlen(str);
-  }
-
-  if (buf) {
-    marshal_str(buf, str, len);
-  }
-  return len;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_server_resp_status_code(char *buf)
-{
-  if (buf) {
-    HTTPStatus status;
-    if (m_server_response) {
-      status = m_server_response->status_get();
-    } else {
-      status = HTTP_STATUS_NONE;
-    }
-    marshal_int(buf, (int64_t)status);
-  }
-  return INK_MIN_ALIGN;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_server_resp_content_len(char *buf)
-{
-  if (buf) {
-    int64_t val = 0;
-    if (m_server_response) {
-      val = m_http_sm->server_response_body_bytes;
-    }
-    marshal_int(buf, val);
-  }
-  return INK_MIN_ALIGN;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_server_resp_header_len(char *buf)
-{
-  if (buf) {
-    int64_t val = 0;
-    if (m_server_response) {
-      val = m_server_response->length_get();
-    }
-    marshal_int(buf, val);
-  }
-  return INK_MIN_ALIGN;
-}
-
-int
-LogAccessHttp::marshal_server_resp_squid_len(char *buf)
-{
-  if (buf) {
-    int64_t val = 0;
-    if (m_server_response) {
-      val = m_server_response->length_get() + m_http_sm->server_response_body_bytes;
-    }
-    marshal_int(buf, val);
-  }
-  return INK_MIN_ALIGN;
-}
-
-int
-LogAccessHttp::marshal_server_resp_http_version(char *buf)
-{
-  if (buf) {
-    int64_t major = 0;
-    int64_t minor = 0;
-    if (m_server_response) {
-      major = HTTP_MAJOR(m_server_response->version_get().m_version);
-      minor = HTTP_MINOR(m_server_response->version_get().m_version);
-    }
-    marshal_int(buf, major);
-    marshal_int((buf + INK_MIN_ALIGN), minor);
-  }
-  return (2 * INK_MIN_ALIGN);
-}
-
-/*-------------------------------------------------------------------------
--------------------------------------------------------------------------*/
-int
-LogAccessHttp::marshal_server_resp_time_ms(char *buf)
-{
-  if (buf) {
-    ink_hrtime elapsed = m_http_sm->milestones[TS_MILESTONE_SERVER_CLOSE] - m_http_sm->milestones[TS_MILESTONE_SERVER_CONNECT];
-    int64_t val        = (int64_t)ink_hrtime_to_msec(elapsed);
-    marshal_int(buf, val);
-  }
-  return INK_MIN_ALIGN;
-}
-
-int
-LogAccessHttp::marshal_server_resp_time_s(char *buf)
-{
-  if (buf) {
-    ink_hrtime elapsed = m_http_sm->milestones[TS_MILESTONE_SERVER_CLOSE] - m_http_sm->milestones[TS_MILESTONE_SERVER_CONNECT];
-    int64_t val        = (int64_t)ink_hrtime_to_sec(elapsed);
-    marshal_int(buf, val);
-  }
-  return INK_MIN_ALIGN;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_server_transact_count(char *buf)
-{
-  if (buf) {
-    int64_t count;
-    count = m_http_sm->server_transact_count;
-    marshal_int(buf, count);
-  }
-  return INK_MIN_ALIGN;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_server_connect_attempts(char *buf)
-{
-  if (buf) {
-    int64_t attempts = m_http_sm->t_state.current.attempts;
-    marshal_int(buf, attempts);
-  }
-  return INK_MIN_ALIGN;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_cache_resp_status_code(char *buf)
-{
-  if (buf) {
-    HTTPStatus status;
-    if (m_cache_response) {
-      status = m_cache_response->status_get();
-    } else {
-      status = HTTP_STATUS_NONE;
-    }
-    marshal_int(buf, (int64_t)status);
-  }
-  return INK_MIN_ALIGN;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_cache_resp_content_len(char *buf)
-{
-  if (buf) {
-    int64_t val = 0;
-    if (m_cache_response) {
-      val = m_http_sm->cache_response_body_bytes;
-    }
-    marshal_int(buf, val);
-  }
-  return INK_MIN_ALIGN;
-}
-
-int
-LogAccessHttp::marshal_cache_resp_squid_len(char *buf)
-{
-  if (buf) {
-    int64_t val = 0;
-    if (m_cache_response) {
-      val = m_cache_response->length_get() + m_http_sm->cache_response_body_bytes;
-    }
-    marshal_int(buf, val);
-  }
-  return INK_MIN_ALIGN;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_cache_resp_header_len(char *buf)
-{
-  if (buf) {
-    int64_t val = 0;
-    if (m_cache_response) {
-      val = m_http_sm->cache_response_hdr_bytes;
-    }
-    marshal_int(buf, val);
-  }
-  return INK_MIN_ALIGN;
-}
-
-int
-LogAccessHttp::marshal_cache_resp_http_version(char *buf)
-{
-  if (buf) {
-    int64_t major = 0;
-    int64_t minor = 0;
-    if (m_cache_response) {
-      major = HTTP_MAJOR(m_cache_response->version_get().m_version);
-      minor = HTTP_MINOR(m_cache_response->version_get().m_version);
-    }
-    marshal_int(buf, major);
-    marshal_int((buf + INK_MIN_ALIGN), minor);
-  }
-  return (2 * INK_MIN_ALIGN);
-}
-
-int
-LogAccessHttp::marshal_client_retry_after_time(char *buf)
-{
-  if (buf) {
-    int64_t crat = m_http_sm->t_state.congestion_control_crat;
-    marshal_int(buf, crat);
-  }
-  return INK_MIN_ALIGN;
-}
-
-static LogCacheWriteCodeType
-convert_cache_write_code(HttpTransact::CacheWriteStatus_t t)
-{
-  LogCacheWriteCodeType code;
-  switch (t) {
-  case HttpTransact::NO_CACHE_WRITE:
-    code = LOG_CACHE_WRITE_NONE;
-    break;
-  case HttpTransact::CACHE_WRITE_LOCK_MISS:
-    code = LOG_CACHE_WRITE_LOCK_MISSED;
-    break;
-  case HttpTransact::CACHE_WRITE_IN_PROGRESS:
-    // Hack - the HttpSM doesn't record
-    //   cache write aborts currently so
-    //   if it's not complete declare it
-    //   aborted
-    code = LOG_CACHE_WRITE_LOCK_ABORTED;
-    break;
-  case HttpTransact::CACHE_WRITE_ERROR:
-    code = LOG_CACHE_WRITE_ERROR;
-    break;
-  case HttpTransact::CACHE_WRITE_COMPLETE:
-    code = LOG_CACHE_WRITE_COMPLETE;
-    break;
-  default:
-    ink_assert(!"bad cache write code");
-    code = LOG_CACHE_WRITE_NONE;
-    break;
-  }
-
-  return code;
-}
-
-int
-LogAccessHttp::marshal_cache_write_code(char *buf)
-{
-  if (buf) {
-    int code = convert_cache_write_code(m_http_sm->t_state.cache_info.write_status);
-    marshal_int(buf, code);
-  }
-
-  return INK_MIN_ALIGN;
-}
-
-int
-LogAccessHttp::marshal_cache_write_transform_code(char *buf)
-{
-  if (buf) {
-    int code = convert_cache_write_code(m_http_sm->t_state.cache_info.transform_write_status);
-    marshal_int(buf, code);
-  }
-
-  return INK_MIN_ALIGN;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_transfer_time_ms(char *buf)
-{
-  if (buf) {
-    ink_hrtime elapsed = m_http_sm->milestones[TS_MILESTONE_SM_FINISH] - m_http_sm->milestones[TS_MILESTONE_SM_START];
-    int64_t val        = (int64_t)ink_hrtime_to_msec(elapsed);
-    marshal_int(buf, val);
-  }
-  return INK_MIN_ALIGN;
-}
-
-int
-LogAccessHttp::marshal_transfer_time_s(char *buf)
-{
-  if (buf) {
-    ink_hrtime elapsed = m_http_sm->milestones[TS_MILESTONE_SM_FINISH] - m_http_sm->milestones[TS_MILESTONE_SM_START];
-    int64_t val        = (int64_t)ink_hrtime_to_sec(elapsed);
-    marshal_int(buf, val);
-  }
-  return INK_MIN_ALIGN;
-}
-
-/*-------------------------------------------------------------------------
-  Figure out the size of the object *on origin*. This is somewhat tricky
-  since there are many variations on how this can be calculated.
-  -------------------------------------------------------------------------*/
-int
-LogAccessHttp::marshal_file_size(char *buf)
-{
-  if (buf) {
-    MIMEField *fld;
-    HTTPHdr *hdr = m_server_response ? m_server_response : m_cache_response;
-
-    if (hdr && (fld = hdr->field_find(MIME_FIELD_CONTENT_RANGE, MIME_LEN_CONTENT_RANGE))) {
-      int len;
-      char *str = (char *)fld->value_get(&len);
-      char *pos = (char *)memchr(str, '/', len); // Find the /
-
-      // If the size is not /* (which means unknown) use it as the file_size.
-      if (pos && !memchr(pos + 1, '*', len - (pos + 1 - str))) {
-        marshal_int(buf, ink_atoi64(pos + 1, len - (pos + 1 - str)));
-      }
-    } else {
-      // This is semi-broken when we serveq zero length objects. See TS-2213
-      if (m_http_sm->server_response_body_bytes > 0) {
-        marshal_int(buf, m_http_sm->server_response_body_bytes);
-      } else if (m_http_sm->cache_response_body_bytes > 0) {
-        marshal_int(buf, m_http_sm->cache_response_body_bytes);
-      }
-    }
-  }
-  // Else, we don't set the value at all (so, -)
-
-  return INK_MIN_ALIGN;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_client_http_connection_id(char *buf)
-{
-  if (buf) {
-    int64_t id = 0;
-    if (m_http_sm) {
-      id = m_http_sm->client_connection_id();
-    }
-    marshal_int(buf, id);
-  }
-  return INK_MIN_ALIGN;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_client_http_transaction_id(char *buf)
-{
-  if (buf) {
-    int64_t id = 0;
-    if (m_http_sm) {
-      id = m_http_sm->client_transaction_id();
-    }
-    marshal_int(buf, id);
-  }
-  return INK_MIN_ALIGN;
-}
-
-/*-------------------------------------------------------------------------
-  -------------------------------------------------------------------------*/
-
-int
-LogAccessHttp::marshal_http_header_field(LogField::Container container, char *field, char *buf)
-{
-  char *str        = nullptr;
-  int padded_len   = INK_MIN_ALIGN;
-  int actual_len   = 0;
-  bool valid_field = false;
-  HTTPHdr *header;
-
-  switch (container) {
-  case LogField::CQH:
-    header = m_client_request;
-    break;
-
-  case LogField::PSH:
-    header = m_proxy_response;
-    break;
-
-  case LogField::PQH:
-    header = m_proxy_request;
-    break;
-
-  case LogField::SSH:
-    header = m_server_response;
-    break;
-
-  case LogField::CSSH:
-    header = m_cache_response;
-    break;
-
-  default:
-    header = nullptr;
-    break;
-  }
-
-  if (header) {
-    MIMEField *fld = header->field_find(field, (int)::strlen(field));
-    if (fld) {
-      valid_field = true;
-
-      // Loop over dups, marshalling each one into the buffer and
-      // summing up their length
-      //
-      int running_len = 0;
-      while (fld) {
-        str = (char *)fld->value_get(&actual_len);
-        if (buf) {
-          memcpy(buf, str, actual_len);
-          buf += actual_len;
-        }
-        running_len += actual_len;
-        fld = fld->m_next_dup;
-
-        // Dups need to be comma separated.  So if there's another
-        // dup, then add a comma and a space ...
-        //
-        if (fld != nullptr) {
-          if (buf) {
-            memcpy(buf, ", ", 2);
-            buf += 2;
-          }
-          running_len += 2;
-        }
-      }
-
-      // Done with all dups.  Ensure that the string is terminated
-      // and that the running_len is padded.
-      //
-      if (buf) {
-        *buf = '\0';
-        buf++;
-      }
-      running_len += 1;
-      padded_len = round_strlen(running_len);
-
-// Note: marshal_string fills the padding to
-//  prevent purify UMRs so we do it here too
-//  since we always pass the unpadded length on
-//  our calls to marshal string
-#ifdef DEBUG
-      if (buf) {
-        int pad_len = padded_len - running_len;
-        for (int i = 0; i < pad_len; i++) {
-          *buf = '$';
-          buf++;
-        }
-      }
-#endif
-    }
-  }
-
-  if (valid_field == false) {
-    padded_len = INK_MIN_ALIGN;
-    if (buf) {
-      marshal_str(buf, nullptr, padded_len);
-    }
-  }
-
-  return (padded_len);
-}
-
-int
-LogAccessHttp::marshal_http_header_field_escapify(LogField::Container container, char *field, char *buf)
-{
-  char *str = nullptr, *new_str = nullptr;
-  int padded_len = INK_MIN_ALIGN;
-  int actual_len = 0, new_len = 0;
-  bool valid_field = false;
-  HTTPHdr *header;
-
-  switch (container) {
-  case LogField::ECQH:
-    header = m_client_request;
-    break;
-
-  case LogField::EPSH:
-    header = m_proxy_response;
-    break;
-
-  case LogField::EPQH:
-    header = m_proxy_request;
-    break;
-
-  case LogField::ESSH:
-    header = m_server_response;
-    break;
-
-  case LogField::ECSSH:
-    header = m_cache_response;
-    break;
-
-  default:
-    header = nullptr;
-    break;
-  }
-
-  if (header) {
-    MIMEField *fld = header->field_find(field, (int)::strlen(field));
-    if (fld) {
-      valid_field = true;
-
-      // Loop over dups, marshalling each one into the buffer and
-      // summing up their length
-      //
-      int running_len = 0;
-      while (fld) {
-        str     = (char *)fld->value_get(&actual_len);
-        new_str = LogUtils::escapify_url(&m_arena, str, actual_len, &new_len);
-        if (buf) {
-          memcpy(buf, new_str, new_len);
-          buf += new_len;
-        }
-        running_len += new_len;
-        fld = fld->m_next_dup;
-
-        // Dups need to be comma separated.  So if there's another
-        // dup, then add a comma and an escapified space ...
-        constexpr const char SEP[] = ",%20";
-        constexpr size_t SEP_LEN   = sizeof(SEP) - 1;
-        if (fld != nullptr) {
-          if (buf) {
-            memcpy(buf, SEP, SEP_LEN);
-            buf += SEP_LEN;
-          }
-          running_len += SEP_LEN;
-        }
-      }
-
-      // Done with all dups.  Ensure that the string is terminated
-      // and that the running_len is padded.
-      //
-      if (buf) {
-        *buf = '\0';
-        buf++;
-      }
-      running_len += 1;
-      padded_len = round_strlen(running_len);
-
-// Note: marshal_string fills the padding to
-//  prevent purify UMRs so we do it here too
-//  since we always pass the unpadded length on
-//  our calls to marshal string
-#ifdef DEBUG
-      if (buf) {
-        int pad_len = padded_len - running_len;
-        for (int i = 0; i < pad_len; i++) {
-          *buf = '$';
-          buf++;
-        }
-      }
-#endif
-    }
-  }
-
-  if (valid_field == false) {
-    padded_len = INK_MIN_ALIGN;
-    if (buf) {
-      marshal_str(buf, nullptr, padded_len);
-    }
-  }
-
-  return (padded_len);
-}
-
-int
-LogAccessHttp::marshal_milestone(TSMilestonesType ms, char *buf)
-{
-  if (buf) {
-    int64_t val = ink_hrtime_to_msec(m_http_sm->milestones[ms]);
-    marshal_int(buf, val);
-  }
-  return INK_MIN_ALIGN;
-}
-
-int
-LogAccessHttp::marshal_milestone_fmt_sec(TSMilestonesType type, char *buf)
-{
-  if (buf) {
-    ink_hrtime tsec = ink_hrtime_to_sec(m_http_sm->milestones[type]);
-    marshal_int(buf, tsec);
-  }
-  return INK_MIN_ALIGN;
-}
-
-int
-LogAccessHttp::marshal_milestone_fmt_ms(TSMilestonesType type, char *buf)
-{
-  if (buf) {
-    ink_hrtime tmsec = ink_hrtime_to_msec(m_http_sm->milestones[type]);
-    marshal_int(buf, tmsec);
-  }
-  return INK_MIN_ALIGN;
-}
-
-int
-LogAccessHttp::marshal_milestone_diff(TSMilestonesType ms1, TSMilestonesType ms2, char *buf)
-{
-  if (buf) {
-    ink_hrtime elapsed = m_http_sm->milestones.elapsed(ms2, ms1);
-    int64_t val        = (int64_t)ink_hrtime_to_msec(elapsed);
-    marshal_int(buf, val);
-  }
-  return INK_MIN_ALIGN;
-}
diff --git a/proxy/logging/LogAccessHttp.h b/proxy/logging/LogAccessHttp.h
deleted file mode 100644
index d0cadec..0000000
--- a/proxy/logging/LogAccessHttp.h
+++ /dev/null
@@ -1,222 +0,0 @@
-/** @file
-
-  A brief file description
-
-  @section license License
-
-  Licensed to the Apache Software Foundation (ASF) under one
-  or more contributor license agreements.  See the NOTICE file
-  distributed with this work for additional information
-  regarding copyright ownership.  The ASF licenses this file
-  to you 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
-
-      http://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.
- */
-
-#pragma once
-
-#include "ts/Arena.h"
-#include "HTTP.h"
-#include "LogAccess.h"
-
-class HttpSM;
-class URL;
-
-/*-------------------------------------------------------------------------
-  LogAccessHttp
-
-  This class extends the logging system interface as implemented by the
-  HttpStateMachineGet class.
-  -------------------------------------------------------------------------*/
-
-class LogAccessHttp : public LogAccess
-{
-public:
-  LogAccessHttp(HttpSM *sm);
-  ~LogAccessHttp() override;
-
-  void init() override;
-
-  LogEntryType
-  entry_type() const override
-  {
-    return LOG_ENTRY_HTTP;
-  }
-
-  //
-  // client -> proxy fields
-  //
-  int marshal_client_host_ip(char *) override;                // STR
-  int marshal_host_interface_ip(char *) override;             // STR
-  int marshal_client_host_port(char *) override;              // INT
-  int marshal_client_auth_user_name(char *) override;         // STR
-  int marshal_client_req_text(char *) override;               // STR
-  int marshal_client_req_http_method(char *) override;        // INT
-  int marshal_client_req_url(char *) override;                // STR
-  int marshal_client_req_url_canon(char *) override;          // STR
-  int marshal_client_req_unmapped_url_canon(char *) override; // STR
-  int marshal_client_req_unmapped_url_path(char *) override;  // STR
-  int marshal_client_req_unmapped_url_host(char *) override;  // STR
-  int marshal_client_req_url_path(char *) override;           // STR
-  int marshal_client_req_url_scheme(char *) override;         // STR
-  int marshal_client_req_http_version(char *) override;       // INT
-  int marshal_client_req_protocol_version(char *) override;   // STR
-  int marshal_client_req_header_len(char *) override;         // INT
-  int marshal_client_req_content_len(char *) override;        // INT
-  int marshal_client_req_squid_len(char *) override;          // INT
-  int marshal_client_req_tcp_reused(char *) override;         // INT
-  int marshal_client_req_is_ssl(char *) override;             // INT
-  int marshal_client_req_ssl_reused(char *) override;         // INT
-  int marshal_client_req_timestamp_sec(char *) override;      // INT
-  int marshal_client_req_timestamp_ms(char *) override;       // INT
-  int marshal_client_security_protocol(char *) override;      // STR
-  int marshal_client_security_cipher_suite(char *) override;  // STR
-  int marshal_client_finish_status_code(char *) override;     // INT
-  int marshal_client_req_id(char *) override;                 // INT
-  int marshal_client_req_uuid(char *) override;               // STR
-  int marshal_client_rx_error_code(char *) override;          // STR
-  int marshal_client_tx_error_code(char *) override;          // STR
-
-  //
-  // proxy -> client fields
-  //
-  int marshal_proxy_resp_content_type(char *) override;  // STR
-  int marshal_proxy_resp_reason_phrase(char *) override; // STR
-  int marshal_proxy_resp_header_len(char *) override;    // INT
-  int marshal_proxy_resp_content_len(char *) override;   // INT
-  int marshal_proxy_resp_squid_len(char *) override;     // INT
-  int marshal_proxy_resp_status_code(char *) override;   // INT
-  int marshal_proxy_finish_status_code(char *) override; // INT
-  int marshal_cache_result_code(char *) override;        // INT
-  int marshal_cache_result_subcode(char *) override;     // INT
-  int marshal_cache_hit_miss(char *) override;           // INT
-
-  //
-  // proxy -> server fields
-  //
-  int marshal_proxy_req_header_len(char *) override;  // INT
-  int marshal_proxy_req_content_len(char *) override; // INT
-  int marshal_proxy_req_squid_len(char *) override;   // INT
-  int marshal_proxy_req_server_ip(char *) override;   // INT
-  int marshal_proxy_req_server_port(char *) override; // INT
-  int marshal_proxy_hierarchy_route(char *) override; // INT
-  int marshal_proxy_host_port(char *) override;       // INT
-  int marshal_proxy_req_is_ssl(char *) override;      // INT
-  int marshal_next_hop_ip(char *) override;           // STR
-  int marshal_next_hop_port(char *) override;         // INT
-
-  //
-  // server -> proxy fields
-  //
-  int marshal_server_host_ip(char *) override;           // INT
-  int marshal_server_host_name(char *) override;         // STR
-  int marshal_server_resp_status_code(char *) override;  // INT
-  int marshal_server_resp_header_len(char *) override;   // INT
-  int marshal_server_resp_content_len(char *) override;  // INT
-  int marshal_server_resp_squid_len(char *) override;    // INT
-  int marshal_server_resp_http_version(char *) override; // INT
-  int marshal_server_resp_time_ms(char *) override;      // INT
-  int marshal_server_resp_time_s(char *) override;       // INT
-  int marshal_server_transact_count(char *) override;    // INT
-  int marshal_server_connect_attempts(char *) override;  // INT
-
-  //
-  // cache -> client fields
-  //
-  int marshal_cache_resp_status_code(char *) override;  // INT
-  int marshal_cache_resp_header_len(char *) override;   // INT
-  int marshal_cache_resp_content_len(char *) override;  // INT
-  int marshal_cache_resp_squid_len(char *) override;    // INT
-  int marshal_cache_resp_http_version(char *) override; // INT
-
-  //
-  // congestion control client_retry_after_time
-  //
-  int marshal_client_retry_after_time(char *) override; // INT
-
-  //
-  // cache write fields
-  //
-  int marshal_cache_write_code(char *) override;           // INT
-  int marshal_cache_write_transform_code(char *) override; // INT
-
-  //
-  // other fields
-  //
-  int marshal_transfer_time_ms(char *) override;           // INT
-  int marshal_transfer_time_s(char *) override;            // INT
-  int marshal_file_size(char *) override;                  // INT
-  int marshal_plugin_identity_id(char *) override;         // INT
-  int marshal_plugin_identity_tag(char *) override;        // STR
-  int marshal_cache_lookup_url_canon(char *) override;     // STR
-  int marshal_client_http_connection_id(char *) override;  // INT
-  int marshal_client_http_transaction_id(char *) override; // INT
-
-  //
-  // named fields from within a http header
-  //
-  int marshal_http_header_field(LogField::Container container, char *field, char *buf) override;
-  int marshal_http_header_field_escapify(LogField::Container container, char *field, char *buf) override;
-
-  int marshal_milestone(TSMilestonesType ms, char *buf) override;
-  int marshal_milestone_fmt_sec(TSMilestonesType ms, char *buf) override;
-  int marshal_milestone_diff(TSMilestonesType ms1, TSMilestonesType ms2, char *buf) override;
-
-  int marshal_milestone_fmt_ms(TSMilestonesType ms, char *buf);
-
-  void set_client_req_url(char *, int) override;                // STR
-  void set_client_req_url_canon(char *, int) override;          // STR
-  void set_client_req_unmapped_url_canon(char *, int) override; // STR
-  void set_client_req_unmapped_url_path(char *, int) override;  // STR
-  void set_client_req_unmapped_url_host(char *, int) override;  // STR
-  void set_client_req_url_path(char *, int) override;           // STR
-
-  // noncopyable
-  // -- member functions that are not allowed --
-  LogAccessHttp(const LogAccessHttp &rhs) = delete;
-  LogAccessHttp &operator=(LogAccessHttp &rhs) = delete;
-
-private:
-  HttpSM *m_http_sm;
-
-  Arena m_arena;
-  //  URL *m_url;
-
-  HTTPHdr *m_client_request;
-  HTTPHdr *m_proxy_response;
-  HTTPHdr *m_proxy_request;
-  HTTPHdr *m_server_response;
-  HTTPHdr *m_cache_response;
-
-  char *m_client_req_url_str;
-  int m_client_req_url_len;
-  char *m_client_req_url_canon_str;
-  int m_client_req_url_canon_len;
-  char *m_client_req_unmapped_url_canon_str;
-  int m_client_req_unmapped_url_canon_len;
-  char *m_client_req_unmapped_url_path_str;
-  int m_client_req_unmapped_url_path_len;
-  char *m_client_req_unmapped_url_host_str;
-  int m_client_req_unmapped_url_host_len;
-  char const *m_client_req_url_path_str;
-  int m_client_req_url_path_len;
-  char *m_proxy_resp_content_type_str;
-  int m_proxy_resp_content_type_len;
-  char *m_proxy_resp_reason_phrase_str;
-  int m_proxy_resp_reason_phrase_len;
-  char *m_cache_lookup_url_canon_str;
-  int m_cache_lookup_url_canon_len;
-
-  void validate_unmapped_url(void);
-  void validate_unmapped_url_path(void);
-
-  void validate_lookup_url(void);
-};
diff --git a/proxy/logging/LogAccessTest.h b/proxy/logging/LogAccessTest.h
index 32540bf..6519071 100644
--- a/proxy/logging/LogAccessTest.h
+++ b/proxy/logging/LogAccessTest.h
@@ -46,9 +46,8 @@ public:
   //
   // client -> proxy fields
   //
-  virtual int marshal_client_host_ip(char *);        // INT
-  virtual int marshal_client_auth_user_name(char *); // STR
-  // marshal_client_req_timestamp_sec is non-virtual!
+  virtual int marshal_client_host_ip(char *);            // INT
+  virtual int marshal_client_auth_user_name(char *);     // STR
   virtual int marshal_client_req_text(char *);           // STR
   virtual int marshal_client_req_http_method(char *);    // INT
   virtual int marshal_client_req_url(char *);            // STR
diff --git a/proxy/logging/Makefile.am b/proxy/logging/Makefile.am
index ed8d6e1..9838394 100644
--- a/proxy/logging/Makefile.am
+++ b/proxy/logging/Makefile.am
@@ -41,8 +41,6 @@ liblogging_a_SOURCES = \
 	Log.h \
 	LogAccess.cc \
 	LogAccess.h \
-	LogAccessHttp.cc \
-	LogAccessHttp.h \
 	LogBuffer.cc \
 	LogBuffer.h \
 	LogBufferSink.h \
diff --git a/src/traffic_logcat/Makefile.inc b/src/traffic_logcat/Makefile.inc
index 80dac6d..ec65d41 100644
--- a/src/traffic_logcat/Makefile.inc
+++ b/src/traffic_logcat/Makefile.inc
@@ -40,6 +40,7 @@ traffic_logcat_traffic_logcat_SOURCES = \
 
 traffic_logcat_traffic_logcat_LDADD = \
 	$(top_builddir)/proxy/logging/liblogging.a \
+	$(top_builddir)/proxy/hdrs/libhdrs.a \
 	$(top_builddir)/proxy/shared/libdiagsconfig.a \
 	$(top_builddir)/proxy/shared/libUglyLogStubs.a \
 	$(top_builddir)/mgmt/libmgmt_p.la \
diff --git a/src/traffic_logstats/Makefile.inc b/src/traffic_logstats/Makefile.inc
index 78a3929..3d2b72e 100644
--- a/src/traffic_logstats/Makefile.inc
+++ b/src/traffic_logstats/Makefile.inc
@@ -44,6 +44,7 @@ traffic_logstats_traffic_logstats_SOURCES = \
 
 traffic_logstats_traffic_logstats_LDADD = \
 	$(top_builddir)/proxy/logging/liblogging.a \
+	$(top_builddir)/proxy/hdrs/libhdrs.a \
 	$(top_builddir)/proxy/shared/libdiagsconfig.a \
 	$(top_builddir)/proxy/shared/libUglyLogStubs.a \
 	$(top_builddir)/mgmt/libmgmt_p.la \