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:53 UTC

[trafficserver] branch 8.0.x updated (43bb698 -> fe3c69e)

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

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


    from 43bb698  Updated ChangeLog
     new 988ab10  Collapses LogAccess and LogAccessHttp into LogAccess
     new d8e2a40  logstats conditionally disable format check
     new 121ee0c  Fix Http/2 priority crashes.
     new cd49846  Removes reference to non-existent ssl_multicert option 'exit_on_load_error'
     new fe3c69e  In conf_remap plugin, print name of non-existent or non-overriddable configuration variable in a file to error log.

The 5 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 CMakeLists.txt                                     |    2 -
 doc/admin-guide/files/ssl_multicert.config.en.rst  |   11 -
 .../command-line/traffic_logstats.en.rst           |   46 +
 plugins/conf_remap/conf_remap.cc                   |    3 +-
 proxy/ProxyClientSession.cc                        |   18 -
 proxy/ProxyClientSession.h                         |   18 +-
 proxy/http/HttpBodyFactory.cc                      |    7 +-
 proxy/http/HttpSM.cc                               |    6 +-
 proxy/http2/Http2DependencyTree.h                  |   29 +-
 proxy/http2/test_Http2DependencyTree.cc            |   96 +
 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 +
 src/traffic_logstats/logstats.cc                   |   23 +-
 21 files changed, 2532 insertions(+), 3209 deletions(-)
 delete mode 100644 proxy/logging/LogAccessHttp.cc
 delete mode 100644 proxy/logging/LogAccessHttp.h


[trafficserver] 04/05: Removes reference to non-existent ssl_multicert option 'exit_on_load_error'

Posted by zw...@apache.org.
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 cd4984643102cff3182af8bbc918a7a3a4a8e80b
Author: Randall Meyer <ra...@yahoo.com>
AuthorDate: Wed Aug 1 12:02:54 2018 -0700

    Removes reference to non-existent ssl_multicert option 'exit_on_load_error'
    
    The configurable option is 'proxy.config.ssl.server.multicert.exit_on_load_fail'
    in records.config
    
    (cherry picked from commit a64e8f9e74602a1d38c40b44fe046a3ef30334a1)
---
 doc/admin-guide/files/ssl_multicert.config.en.rst | 11 -----------
 1 file changed, 11 deletions(-)

diff --git a/doc/admin-guide/files/ssl_multicert.config.en.rst b/doc/admin-guide/files/ssl_multicert.config.en.rst
index b4a5ecc..e8112a7 100644
--- a/doc/admin-guide/files/ssl_multicert.config.en.rst
+++ b/doc/admin-guide/files/ssl_multicert.config.en.rst
@@ -119,17 +119,6 @@ ssl_key_dialog=builtin|"exec:/path/to/program [args]" (optional)
       program runs a security check to ensure that the system is not
       compromised by an attacker before providing the pass phrase.
 
-exit_on_load_error=1|0 (optional)
-  If a certificate configuration does not result in a working
-  configuration, traffic server is not allowed to start when this is
-  set. If a new configuration is broken, a working configuration will
-  not be replaced.
-
-  Exit on load error is enabled by default.
-
-  This option can not be applied to a running Traffic Server using
-  :option:`traffic_ctl config reload`.
-
 Certificate Selection
 =====================
 


[trafficserver] 05/05: In conf_remap plugin, print name of non-existent or non-overriddable configuration variable in a file to error log.

Posted by zw...@apache.org.
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 fe3c69e3d93b0bee12e7f64d9599a9b74084d963
Author: Walter Karas <wk...@oath.com>
AuthorDate: Tue Aug 7 18:27:11 2018 -0500

    In conf_remap plugin, print name of non-existent or non-overriddable configuration variable in a file to error log.
    
    (cherry picked from commit 342b3116731abb80134411e624c68b1c58cf9ed3)
---
 plugins/conf_remap/conf_remap.cc | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/plugins/conf_remap/conf_remap.cc b/plugins/conf_remap/conf_remap.cc
index d5dc7f4..6a01772 100644
--- a/plugins/conf_remap/conf_remap.cc
+++ b/plugins/conf_remap/conf_remap.cc
@@ -173,7 +173,8 @@ RemapConfigs::parse_file(const char *filename)
     // Find the configuration name
     tok = strtok_r(nullptr, " \t", &ln);
     if (TSHttpTxnConfigFind(tok, -1, &name, &expected_type) != TS_SUCCESS) {
-      TSError("[%s] File %s, line %d: no records.config name given", PLUGIN_NAME, path.c_str(), line_num);
+      TSError("[%s] File %s, line %d: %s is not a configuration variable or cannot be overridden", PLUGIN_NAME, path.c_str(),
+              line_num, tok);
       continue;
     }
 


[trafficserver] 03/05: Fix Http/2 priority crashes.

Posted by zw...@apache.org.
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 121ee0ced0549005aa5f8cce07675472c5400025
Author: Susan Hinrichs <sh...@oath.com>
AuthorDate: Tue Aug 7 16:52:54 2018 +0000

    Fix Http/2 priority crashes.
    
    (cherry picked from commit 8d982c8cd77923ac5ca8276a20dcabc18ee3c6fa)
---
 proxy/http2/Http2DependencyTree.h       | 29 ++++++++--
 proxy/http2/test_Http2DependencyTree.cc | 96 +++++++++++++++++++++++++++++++++
 2 files changed, 121 insertions(+), 4 deletions(-)

diff --git a/proxy/http2/Http2DependencyTree.h b/proxy/http2/Http2DependencyTree.h
index 9634334..d02e6ad 100644
--- a/proxy/http2/Http2DependencyTree.h
+++ b/proxy/http2/Http2DependencyTree.h
@@ -125,6 +125,7 @@ private:
   Node *_find(Node *node, uint32_t id, uint32_t depth = 1);
   Node *_top(Node *node);
   void _change_parent(Node *new_parent, Node *node, bool exclusive);
+  bool in_parent_chain(Node *maybe_parent, Node *target);
 
   Node *_root = new Node(this);
   uint32_t _max_depth;
@@ -302,7 +303,10 @@ Tree<T>::reprioritize(Node *node, uint32_t new_parent_id, bool exclusive)
   if (new_parent == nullptr) {
     return;
   }
-  _change_parent(new_parent, old_parent, false);
+  // If node is dependent on the new parent, must move the new parent first
+  if (new_parent_id != 0 && in_parent_chain(node, new_parent)) {
+    _change_parent(new_parent, old_parent, false);
+  }
   _change_parent(node, new_parent, exclusive);
 
   // delete the shadow node
@@ -311,6 +315,19 @@ Tree<T>::reprioritize(Node *node, uint32_t new_parent_id, bool exclusive)
   }
 }
 
+template <typename T>
+bool
+Tree<T>::in_parent_chain(Node *maybe_parent, Node *target)
+{
+  bool retval  = false;
+  Node *parent = target->parent;
+  while (parent != nullptr && !retval) {
+    retval = maybe_parent == parent;
+    parent = parent->parent;
+  }
+  return retval;
+}
+
 // Change node's parent to new_parent
 template <typename T>
 void
@@ -339,11 +356,13 @@ Tree<T>::_change_parent(Node *node, Node *new_parent, bool exclusive)
       }
 
       node->children.push(child);
+      ink_release_assert(child != node);
       child->parent = node;
     }
   }
 
   new_parent->children.push(node);
+  ink_release_assert(node != new_parent);
   node->parent = new_parent;
 
   if (node->active || !node->queue->empty()) {
@@ -401,9 +420,11 @@ Tree<T>::deactivate(Node *node, uint32_t sent)
 {
   node->active = false;
 
-  while (node->queue->empty() && node->parent != nullptr) {
-    node->parent->queue->erase(node->entry);
-    node->queued = false;
+  while (!node->active && node->queue->empty() && node->parent != nullptr) {
+    if (node->queued) {
+      node->parent->queue->erase(node->entry);
+      node->queued = false;
+    }
 
     node = node->parent;
   }
diff --git a/proxy/http2/test_Http2DependencyTree.cc b/proxy/http2/test_Http2DependencyTree.cc
index d8fe084..2cccd69 100644
--- a/proxy/http2/test_Http2DependencyTree.cc
+++ b/proxy/http2/test_Http2DependencyTree.cc
@@ -657,6 +657,102 @@ REGRESSION_TEST(Http2DependencyTree_reprioritize_3)(RegressionTest *t, int /* at
   delete tree;
 }
 
+/**
+ * https://github.com/apache/trafficserver/issues/4057
+ * Reprioritization to root
+ *
+ *    x                x
+ *    |               / \
+ *    A              A   D
+ *   / \            / \  |
+ *  B   C     ==>  B   C F
+ *     / \             |
+ *    D   E            E
+ *    |
+ *    F
+ */
+REGRESSION_TEST(Http2DependencyTree_reprioritize_4)(RegressionTest *t, int /* atype ATS_UNUSED */, int *pstatus)
+{
+  TestBox box(t, pstatus);
+  box = REGRESSION_TEST_PASSED;
+
+  Tree *tree = new Tree(100);
+  string a("A"), b("B"), c("C"), d("D"), e("E"), f("F");
+
+  tree->add(0, 1, 0, false, &a);
+  tree->add(1, 3, 0, false, &b);
+  tree->add(1, 5, 0, false, &c);
+  tree->add(5, 7, 0, false, &d);
+  tree->add(5, 9, 0, false, &e);
+  tree->add(7, 11, 0, false, &f);
+
+  Node *node_x = tree->find(0);
+  Node *node_a = tree->find(1);
+  Node *node_c = tree->find(5);
+  Node *node_d = tree->find(7);
+  Node *node_f = tree->find(11);
+
+  tree->activate(node_f);
+  tree->reprioritize(7, 0, false);
+
+  box.check(!node_a->queue->in(node_f->entry), "F should not be in A's queue");
+  box.check(node_d->queue->in(node_f->entry), "F should be in D's queue");
+  box.check(node_x->queue->in(node_d->entry), "D should be in x's queue");
+  box.check(!node_a->queue->in(node_c->entry), "C should not be in A's queue");
+  box.check(node_c->queue->empty(), "C's queue should be empty");
+
+  delete tree;
+}
+
+/**
+ * https://github.com/apache/trafficserver/issues/4057
+ * Reprioritization to unrelated node
+ *
+ *    x                x
+ *    |                |
+ *    A                A
+ *   / \              / \
+ *  B   C     ==>    B   C
+ *     / \           |   |
+ *    D   E          D   E
+ *    |              |
+ *    F              F
+ */
+REGRESSION_TEST(Http2DependencyTree_reprioritize_5)(RegressionTest *t, int /* atype ATS_UNUSED */, int *pstatus)
+{
+  TestBox box(t, pstatus);
+  box = REGRESSION_TEST_PASSED;
+
+  Tree *tree = new Tree(100);
+  string a("A"), b("B"), c("C"), d("D"), e("E"), f("F");
+
+  tree->add(0, 1, 0, false, &a);
+  tree->add(1, 3, 0, false, &b);
+  tree->add(1, 5, 0, false, &c);
+  tree->add(5, 7, 0, false, &d);
+  tree->add(5, 9, 0, false, &e);
+  tree->add(7, 11, 0, false, &f);
+
+  Node *node_x = tree->find(0);
+  Node *node_a = tree->find(1);
+  Node *node_b = tree->find(3);
+  Node *node_c = tree->find(5);
+  Node *node_d = tree->find(7);
+  Node *node_f = tree->find(11);
+
+  tree->activate(node_f);
+  tree->reprioritize(7, 3, false);
+
+  box.check(node_a->queue->in(node_b->entry), "B should be in A's queue");
+  box.check(node_b->queue->in(node_d->entry), "D should be in B's queue");
+  box.check(!node_c->queue->in(node_d->entry), "D should not be in C's queue");
+  box.check(node_x->queue->in(node_a->entry), "A should be in x's queue");
+  box.check(!node_a->queue->in(node_c->entry), "C should not be in A's queue");
+  box.check(node_c->queue->empty(), "C's queue should be empty");
+
+  delete tree;
+}
+
 /** test for https://github.com/apache/trafficserver/issues/2268
  *
  *    root            root                  root


[trafficserver] 02/05: logstats conditionally disable format check

Posted by zw...@apache.org.
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 d8e2a401887dbe0b8ac31e914a25ebe664925424
Author: Gancho Tenev <ga...@apache.org>
AuthorDate: Thu Aug 9 10:46:52 2018 -0700

    logstats conditionally disable format check
    
    Don’t validate the log format field names according to the squid log format.
    This would allow squid format fields to be replaced, i.e. the username of
    the authenticated client caun with a random header value by using cqh,
    or to remove the client’s host IP address from the log for privacy reasons.
    
    Added command line option --no_format_check (default false) and some documentation.
    
    Related to https://issues.apache.org/jira/browse/TS-5069
    
    (cherry picked from commit 63cc2b0db8c40409e21a26dc9d55462828657099)
---
 .../command-line/traffic_logstats.en.rst           | 46 ++++++++++++++++++++++
 src/traffic_logstats/logstats.cc                   | 23 ++++++-----
 2 files changed, 60 insertions(+), 9 deletions(-)

diff --git a/doc/appendices/command-line/traffic_logstats.en.rst b/doc/appendices/command-line/traffic_logstats.en.rst
index dfd4153..481c3d2 100644
--- a/doc/appendices/command-line/traffic_logstats.en.rst
+++ b/doc/appendices/command-line/traffic_logstats.en.rst
@@ -52,40 +52,86 @@ Options
 
 .. option:: -f FILE, --log_file FILE
 
+   Specific logfile to parse
+
 .. option:: -o LIST, --origin_list LIST
 
+   Only show stats for listed Origins
+
 .. option:: -O FILE, --origin_file FILE
 
+   File listing Origins to show
+
 .. option:: -M COUNT, --max_origins COUNT
 
+   Max number of Origins to show
+
 .. option:: -u COUNT, --urls COUNT
 
+   Produce JSON stats for URLs, argument is LRU size
+
 .. option:: -U COUNT, --show_urls COUNT
 
+   Only show max this number of URLs
+
 .. option:: -A, --as_object
 
+   Produce URL stats as a JSON object instead of array
+
 .. option:: -C, --concise
 
+   Eliminate metrics that can be inferred from other values
+
 .. option:: -i, --incremental
 
+   Incremental log parsing
+
 .. option:: -S FILE, --statetag FILE
 
+   Name of the state file to use
+
 .. option:: -t, --tail
 
+   Parse the last <sec> seconds of log
+
 .. option:: -s, --summary
 
+   Only produce the summary
+
 .. option:: -j, --json
 
+   Produce JSON formatted output
+
 .. option:: -c, --cgi
 
+   Produce HTTP headers suitable as a CGI
+
 .. option:: -m, --min_hits
 
+   Minimum total hits for an Origin
+
 .. option:: -a, --max_age
 
+   Max age for log entries to be considered
+
 .. option:: -l COUNT, --line_len COUNT
 
+   Output line length
+
 .. option:: -T TAGS, --debug_tags TAGS
 
+   Colon-Separated Debug Tags
+
+.. option:: -r, --report_per_user
+
+   Report stats per username of the authenticated client ``caun`` instead of host, see `squid log format <../../admin-guide/logging/examples.en.html#squid>`_
+
+.. option:: -n, --no_format_check
+
+   Don't validate the log format field names according to the `squid log format <../../admin-guide/logging/examples.en.html#squid>`_.
+   This would allow squid format fields to be replaced, i.e. the username of the authenticated client ``caun`` with a random header value by using ``cqh``,
+   or to remove the client's host IP address from the log for privacy reasons.
+
 .. option:: -h, --help
 
    Print usage information and exit.
diff --git a/src/traffic_logstats/logstats.cc b/src/traffic_logstats/logstats.cc
index bae5ef1..44cbb1e 100644
--- a/src/traffic_logstats/logstats.cc
+++ b/src/traffic_logstats/logstats.cc
@@ -614,6 +614,7 @@ struct CommandLineArgs {
   int as_object;       // Show the URL stats as a single JSON object (not array)
   int concise;         // Eliminate metrics that can be inferred by other values
   int report_per_user; // A flag to aggregate and report stats per user instead of per host if 'true' (default 'false')
+  int no_format_check; // A flag to skip the log format check if any of the fields is not a standard squid log format field.
 
   CommandLineArgs()
     : max_origins(0),
@@ -629,7 +630,8 @@ struct CommandLineArgs {
       show_urls(0),
       as_object(0),
       concise(0),
-      report_per_user(0)
+      report_per_user(0),
+      no_format_check(0)
   {
     log_file[0]    = '\0';
     origin_file[0] = '\0';
@@ -662,6 +664,7 @@ static ArgumentDescription argument_descriptions[] = {
   {"line_len", 'l', "Output line length", "I", &cl.line_len, nullptr, nullptr},
   {"debug_tags", 'T', "Colon-Separated Debug Tags", "S1023", &error_tags, nullptr, nullptr},
   {"report_per_user", 'r', "Report stats per user instead of host", "T", &cl.report_per_user, nullptr, nullptr},
+  {"no_format_check", 'n', "Don't validate the log format field names", "T", &cl.no_format_check, nullptr, nullptr},
   HELP_ARGUMENT_DESCRIPTION(),
   VERSION_ARGUMENT_DESCRIPTION(),
   RUNROOT_ARGUMENT_DESCRIPTION()};
@@ -1277,15 +1280,17 @@ parse_log_buff(LogBufferHeader *buf_header, bool summary = false, bool aggregate
     LogFormat::parse_symbol_string(buf_header->fmt_fieldlist(), fieldlist, &agg);
   }
 
-  // Validate the fieldlist
-  field                                = fieldlist->first();
-  const std::string_view test_fields[] = {"cqtq", "ttms", "chi", "crc", "pssc", "psql", "cqhm", "cquc", "caun", "phr", "shn"};
-  for (auto i : test_fields) {
-    if (i != field->symbol()) {
-      cerr << "Error parsing log file - expected field: " << i << ", but read field: " << field->symbol() << endl;
-      return 1;
+  if (!cl.no_format_check) {
+    // Validate the fieldlist
+    field                                = fieldlist->first();
+    const std::string_view test_fields[] = {"cqtq", "ttms", "chi", "crc", "pssc", "psql", "cqhm", "cquc", "caun", "phr", "shn"};
+    for (auto i : test_fields) {
+      if (i != field->symbol()) {
+        cerr << "Error parsing log file - expected field: " << i << ", but read field: " << field->symbol() << endl;
+        return 1;
+      }
+      field = fieldlist->next(field);
     }
-    field = fieldlist->next(field);
   }
 
   // Loop over all entries


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

Posted by zw...@apache.org.
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 \