You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by wa...@apache.org on 2012/05/03 22:36:56 UTC

[3/4] git commit: TS-1237 Added log fields and containers for cached headers/data, added filtering by container field to custom logs

TS-1237 Added log fields and containers for cached headers/data, added filtering by container field to custom logs


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/0e20aad0
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/0e20aad0
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/0e20aad0

Branch: refs/heads/master
Commit: 0e20aad0c272a0295789926aa9f9c3b80ed2a412
Parents: b778389
Author: Bart Wyatt <wa...@apache.org>
Authored: Thu May 3 15:13:19 2012 -0500
Committer: Bart Wyatt <wa...@apache.org>
Committed: Thu May 3 15:13:19 2012 -0500

----------------------------------------------------------------------
 proxy/http/HttpSM.cc           |   70 ++++++++++++++++++++++++++----
 proxy/http/HttpSM.h            |    2 +
 proxy/http/HttpTransact.cc     |    4 +-
 proxy/http/HttpTransact.h      |   10 +++--
 proxy/logging/Log.cc           |   24 ++++++++++
 proxy/logging/LogAccess.cc     |   43 +++++++++++++++++++
 proxy/logging/LogAccess.h      |    9 ++++
 proxy/logging/LogAccessHttp.cc |   80 ++++++++++++++++++++++++++++++++++-
 proxy/logging/LogAccessHttp.h  |    9 ++++
 proxy/logging/LogConfig.cc     |   24 ++++++++++
 proxy/logging/LogField.cc      |    8 ++++
 proxy/logging/LogField.h       |    2 +
 12 files changed, 268 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0e20aad0/proxy/http/HttpSM.cc
----------------------------------------------------------------------
diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc
index ebc9c4f..e014afa 100644
--- a/proxy/http/HttpSM.cc
+++ b/proxy/http/HttpSM.cc
@@ -326,6 +326,7 @@ HttpSM::HttpSM()
     server_request_hdr_bytes(0), server_request_body_bytes(0),
     server_response_hdr_bytes(0), server_response_body_bytes(0),
     client_response_hdr_bytes(0), client_response_body_bytes(0),
+    cache_response_hdr_bytes(0), cache_response_body_bytes(0),
     pushed_response_hdr_bytes(0), pushed_response_body_bytes(0),
     hooks_set(0), cur_hook_id(TS_HTTP_LAST_HOOK), cur_hook(NULL),
     cur_hooks(0), callout_state(HTTP_API_NO_CALLOUT), terminate_sm(false), kill_this_async_done(false)
@@ -2710,7 +2711,6 @@ HttpSM::tunnel_handler_server(int event, HttpTunnelProducer * p)
 {
   STATE_ENTER(&HttpSM::tunnel_handler_server, event);
 
-  server_response_body_bytes += p->bytes_read;
   milestones.server_close = ink_get_hrtime();
 
   bool close_connection = false;
@@ -3023,6 +3023,29 @@ HttpSM::tunnel_handler_ua(int event, HttpTunnelConsumer * c)
   if (client_response_body_bytes < 0)
     client_response_body_bytes = 0;
 
+  // attribute the size written to the client from various sources
+  // NOTE: responses that go through a range transform are attributed
+  // to their original sources
+  // all other transforms attribute the total number of input bytes
+  // to a source in HttpSM::tunnel_handler_transform_write
+  //
+  HttpTransact::Source_t original_source = t_state.source;
+  if (HttpTransact::SOURCE_TRANSFORM == original_source &&
+      t_state.range_setup == HttpTransact::RANGE_TRANSFORM) {
+    original_source = t_state.pre_transform_source;
+  }
+
+  switch (original_source) {
+  case HttpTransact::SOURCE_HTTP_ORIGIN_SERVER:
+    server_response_body_bytes = client_response_body_bytes;
+    break;
+  case HttpTransact::SOURCE_CACHE:
+    cache_response_body_bytes = client_response_body_bytes;
+    break;
+  default:
+    break;
+  }
+
   ink_assert(ua_entry->vc == c->vc);
   if (close_connection) {
     // If the client could be pipelining or is doing a POST, we need to
@@ -3546,6 +3569,28 @@ HttpSM::tunnel_handler_transform_write(int event, HttpTunnelConsumer * c)
     ink_release_assert(0);
   }
 
+  // attribute the size written to the transform from various sources
+  // NOTE: the range transform is excluded from this accounting and
+  // is instead handled in HttpSM::tunnel_handler_ua
+  //
+  // the reasoning is that the range transform is internal functionality
+  // in support of HTTP 1.1 compliance, therefore part of "normal" operation
+  // all other transforms are plugin driven and the difference between
+  // source data and final data should represent the transformation delta
+  //
+  if (t_state.range_setup != HttpTransact::RANGE_TRANSFORM) {
+    switch (t_state.pre_transform_source) {
+    case HttpTransact::SOURCE_HTTP_ORIGIN_SERVER:
+      server_response_body_bytes = client_response_body_bytes;
+      break;
+    case HttpTransact::SOURCE_CACHE:
+      cache_response_body_bytes = client_response_body_bytes;
+      break;
+    default:
+      break;
+    }
+  }
+
   return 0;
 }
 
@@ -5290,6 +5335,8 @@ HttpSM::setup_cache_read_transfer()
   // Now dump the header into the buffer
   ink_assert(t_state.hdr_info.client_response.status_get() != HTTP_STATUS_NOT_MODIFIED);
   client_response_hdr_bytes = hdr_size = write_response_header_into_buffer(&t_state.hdr_info.client_response, buf);
+  cache_response_hdr_bytes = client_response_hdr_bytes;
+
 
   HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::tunnel_handler);
 
@@ -5320,6 +5367,9 @@ HttpSM::setup_cache_transfer_to_transform()
   ink_assert(transform_info.vc != NULL);
   ink_assert(transform_info.entry->vc == transform_info.vc);
 
+  // grab this here
+  cache_response_hdr_bytes = t_state.hdr_info.cache_response.length_get();
+
   doc_size = t_state.cache_info.object_read->object_size_get();
   alloc_index = buffer_size_to_index(doc_size);
   MIOBuffer *buf = new_MIOBuffer(alloc_index);
@@ -5340,12 +5390,6 @@ HttpSM::setup_cache_transfer_to_transform()
   transform_info.entry->in_tunnel = true;
   cache_sm.cache_read_vc = NULL;
 
-  // We need to copy to header cached request header since the
-  //   cache read may finish before we do an open write to
-  //   write the transformed copy to the cache
-  t_state.hdr_info.transform_cached_request.create(HTTP_TYPE_REQUEST);
-  t_state.hdr_info.transform_cached_request.copy(t_state.cache_info.object_read->request_get());
-
   return p;
 }
 
@@ -5574,7 +5618,7 @@ HttpSM::server_transfer_init(MIOBuffer * buf, int hdr_size)
   // Next order of business if copy the remaining data from the
   //  header buffer into new buffer.
 
-  server_response_body_bytes =
+  int64_t server_response_pre_read_bytes =
 #ifdef WRITE_AND_TRANSFER
     /* relinquish the space in server_buffer and let
        the tunnel use the trailing space
@@ -5583,13 +5627,13 @@ HttpSM::server_transfer_init(MIOBuffer * buf, int hdr_size)
 #else
     buf->write(server_buffer_reader, to_copy);
 #endif
-  server_buffer_reader->consume(server_response_body_bytes);
+  server_buffer_reader->consume(server_response_pre_read_bytes);
 
   //  If we know the length & copied the entire body
   //   of the document out of the header buffer make
   //   sure the server isn't screwing us by having sent too
   //   much.  If it did, we want to close the server connection
-  if (server_response_body_bytes == to_copy && server_buffer_reader->read_avail() > 0) {
+  if (server_response_pre_read_bytes == to_copy && server_buffer_reader->read_avail() > 0) {
     t_state.current.server->keep_alive = HTTP_NO_KEEPALIVE;
   }
 #ifdef LAZY_BUF_ALLOC
@@ -6560,11 +6604,17 @@ HttpSM::set_next_state()
       if (transform_info.vc) {
         ink_assert(t_state.hdr_info.client_response.valid() == 0);
         ink_assert((t_state.hdr_info.transform_response.valid()? true : false) == true);
+        t_state.hdr_info.cache_response.create(HTTP_TYPE_RESPONSE);
+        t_state.hdr_info.cache_response.copy(&t_state.hdr_info.transform_response);
+
         HttpTunnelProducer *p = setup_cache_transfer_to_transform();
         perform_cache_write_action();
         tunnel.tunnel_run(p);
       } else {
         ink_assert((t_state.hdr_info.client_response.valid()? true : false) == true);
+        t_state.hdr_info.cache_response.create(HTTP_TYPE_RESPONSE);
+        t_state.hdr_info.cache_response.copy(&t_state.hdr_info.client_response);
+
         perform_cache_write_action();
         t_state.api_next_action = HttpTransact::HTTP_API_SEND_REPONSE_HDR;
         if (hooks_set) {

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0e20aad0/proxy/http/HttpSM.h
----------------------------------------------------------------------
diff --git a/proxy/http/HttpSM.h b/proxy/http/HttpSM.h
index e80e133..d2eb74c 100644
--- a/proxy/http/HttpSM.h
+++ b/proxy/http/HttpSM.h
@@ -473,6 +473,8 @@ public:
   int64_t server_response_body_bytes;
   int client_response_hdr_bytes;
   int64_t client_response_body_bytes;
+  int cache_response_hdr_bytes;
+  int64_t cache_response_body_bytes;
   int pushed_response_hdr_bytes;
   int64_t pushed_response_body_bytes;
   TransactionMilestones milestones;

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0e20aad0/proxy/http/HttpTransact.cc
----------------------------------------------------------------------
diff --git a/proxy/http/HttpTransact.cc b/proxy/http/HttpTransact.cc
index dd91fb8..5d60c6c 100644
--- a/proxy/http/HttpTransact.cc
+++ b/proxy/http/HttpTransact.cc
@@ -4653,7 +4653,7 @@ HttpTransact::handle_transform_ready(State* s)
 {
   ink_assert(s->hdr_info.transform_response.valid() == true);
 
-  Source_t orig_source = s->source;
+  s->pre_transform_source = s->source;
   s->source = SOURCE_TRANSFORM;
 
   if (!s->cop_test_page)
@@ -4664,7 +4664,7 @@ HttpTransact::handle_transform_ready(State* s)
   if (s->cache_info.action != CACHE_DO_NO_ACTION &&
       s->cache_info.action != CACHE_DO_DELETE && s->api_info.cache_transformed && !s->range_setup) {
     HTTPHdr *transform_store_request = 0;
-    switch (orig_source) {
+    switch (s->pre_transform_source) {
     case SOURCE_CACHE:
       // If we are transforming from the cache, treat
       //  the transform as if it were virtual server

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0e20aad0/proxy/http/HttpTransact.h
----------------------------------------------------------------------
diff --git a/proxy/http/HttpTransact.h b/proxy/http/HttpTransact.h
index 4a51fff..0a9f7dd 100644
--- a/proxy/http/HttpTransact.h
+++ b/proxy/http/HttpTransact.h
@@ -856,8 +856,8 @@ public:
     HTTPHdr server_request;
     HTTPHdr server_response;
     HTTPHdr transform_response;
-    HTTPHdr transform_cached_request;
-    int64_t request_content_length;
+    HTTPHdr cache_response;
+   int64_t request_content_length;
     int64_t response_content_length;
     int64_t transform_request_cl;
     int64_t transform_response_cl;
@@ -873,7 +873,7 @@ public:
         server_request(),
         server_response(),
         transform_response(),
-        transform_cached_request(),
+        cache_response(),
         request_content_length(HTTP_UNDEFINED_CL),
         response_content_length(HTTP_UNDEFINED_CL),
         transform_request_cl(HTTP_UNDEFINED_CL),
@@ -923,6 +923,7 @@ public:
     // ConnectionAttributes     router_info;
 
     Source_t source;
+    Source_t pre_transform_source;
     HttpRequestFlavor_t req_flavor;
 
     CurrentInfo current;
@@ -1068,6 +1069,7 @@ public:
         updated_server_version(HostDBApplicationInfo::HTTP_VERSION_UNDEFINED), is_revalidation_necessary(false),
         request_will_not_selfloop(false),       //YTS Team, yamsat
         source(SOURCE_NONE),
+        pre_transform_source(SOURCE_NONE),
         req_flavor(REQ_FLAVOR_FWDPROXY),
         pending_work(NULL),
         cdn_saved_next_action(STATE_MACHINE_ACTION_UNDEFINED),
@@ -1208,7 +1210,7 @@ public:
       hdr_info.server_request.destroy();
       hdr_info.server_response.destroy();
       hdr_info.transform_response.destroy();
-      hdr_info.transform_cached_request.destroy();
+      hdr_info.cache_response.destroy();
       cache_info.lookup_url_storage.destroy();
       cache_info.original_url.destroy();
       cache_info.store_url.destroy();

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0e20aad0/proxy/logging/Log.cc
----------------------------------------------------------------------
diff --git a/proxy/logging/Log.cc b/proxy/logging/Log.cc
index a4d6947..9b06b63 100644
--- a/proxy/logging/Log.cc
+++ b/proxy/logging/Log.cc
@@ -789,6 +789,30 @@ Log::init_fields()
   global_field_list.add(field, false);
   ink_hash_table_insert(field_symbol_hash, "sshv", field);
 
+  field = NEW(new LogField("cached_resp_status_code", "csssc",
+                           LogField::sINT,
+                           &LogAccess::marshal_cache_resp_status_code, &LogAccess::unmarshal_http_status));
+  global_field_list.add(field, false);
+  ink_hash_table_insert(field_symbol_hash, "csssc", field);
+
+  field = NEW(new LogField("cached_resp_content_len", "csscl",
+                           LogField::sINT,
+                           &LogAccess::marshal_cache_resp_content_len, &LogAccess::unmarshal_int_to_str));
+  global_field_list.add(field, false);
+  ink_hash_table_insert(field_symbol_hash, "csscl", field);
+
+  field = NEW(new LogField("cached_resp_header_len", "csshl",
+                           LogField::sINT,
+                           &LogAccess::marshal_cache_resp_header_len, &LogAccess::unmarshal_int_to_str));
+  global_field_list.add(field, false);
+  ink_hash_table_insert(field_symbol_hash, "csshl", field);
+
+  field = NEW(new LogField("cached_resp_http_version", "csshv",
+                           LogField::dINT,
+                           &LogAccess::marshal_cache_resp_http_version, &LogAccess::unmarshal_http_version));
+  global_field_list.add(field, false);
+  ink_hash_table_insert(field_symbol_hash, "csshv", field);
+
   field = NEW(new LogField("client_retry_after_time", "crat",
                            LogField::sINT,
                            &LogAccess::marshal_client_retry_after_time, &LogAccess::unmarshal_int_to_str));

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0e20aad0/proxy/logging/LogAccess.cc
----------------------------------------------------------------------
diff --git a/proxy/logging/LogAccess.cc b/proxy/logging/LogAccess.cc
index 45c71c9..4a0b106 100644
--- a/proxy/logging/LogAccess.cc
+++ b/proxy/logging/LogAccess.cc
@@ -461,6 +461,49 @@ LogAccess::marshal_server_resp_http_version(char *buf)
   return (2 * INK_MIN_ALIGN);
 }
 
+/*-------------------------------------------------------------------------
+  -------------------------------------------------------------------------*/
+
+int
+LogAccess::marshal_cache_resp_status_code(char *buf)
+{
+  DEFAULT_INT_FIELD;
+}
+
+/*-------------------------------------------------------------------------
+  -------------------------------------------------------------------------*/
+
+int
+LogAccess::marshal_cache_resp_content_len(char *buf)
+{
+  DEFAULT_INT_FIELD;
+}
+
+/*-------------------------------------------------------------------------
+  -------------------------------------------------------------------------*/
+
+int
+LogAccess::marshal_cache_resp_header_len(char *buf)
+{
+  DEFAULT_INT_FIELD;
+}
+
+/*-------------------------------------------------------------------------
+  This case is special because it really stores 2 ints.
+  -------------------------------------------------------------------------*/
+
+int
+LogAccess::marshal_cache_resp_http_version(char *buf)
+{
+  if (buf) {
+    int64_t major = 0;
+    int64_t minor = 0;
+    marshal_int(buf, major);
+    marshal_int((buf + INK_MIN_ALIGN), minor);
+  }
+  return (2 * INK_MIN_ALIGN);
+}
+
 int
 LogAccess::marshal_cache_write_code(char *buf)
 {

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0e20aad0/proxy/logging/LogAccess.h
----------------------------------------------------------------------
diff --git a/proxy/logging/LogAccess.h b/proxy/logging/LogAccess.h
index ea05d1e..0fd0405 100644
--- a/proxy/logging/LogAccess.h
+++ b/proxy/logging/LogAccess.h
@@ -225,6 +225,15 @@ public:
   inkcoreapi virtual int marshal_server_resp_http_version(char *);      // INT
 
   //
+  // cache -> client fields
+  //
+  inkcoreapi virtual int marshal_cache_resp_status_code(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
+
+
+  //
   // congestion control -- client_retry_after_time
   //
   inkcoreapi virtual int marshal_client_retry_after_time(char *);       // INT

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0e20aad0/proxy/logging/LogAccessHttp.cc
----------------------------------------------------------------------
diff --git a/proxy/logging/LogAccessHttp.cc b/proxy/logging/LogAccessHttp.cc
index fc9ce26..026f07e 100644
--- a/proxy/logging/LogAccessHttp.cc
+++ b/proxy/logging/LogAccessHttp.cc
@@ -51,7 +51,7 @@
   -------------------------------------------------------------------------*/
 
 LogAccessHttp::LogAccessHttp(HttpSM * sm)
-:m_http_sm(sm), m_arena(), m_url(NULL), m_client_request(NULL), m_proxy_response(NULL), m_proxy_request(NULL), m_server_response(NULL), m_client_req_url_str(NULL), m_client_req_url_len(0), m_client_req_url_canon_str(NULL), m_client_req_url_canon_len(0), m_client_req_unmapped_url_canon_str(NULL), m_client_req_unmapped_url_canon_len(-1),      // undetermined
+:m_http_sm(sm), m_arena(), m_url(NULL), m_client_request(NULL), m_proxy_response(NULL), m_proxy_request(NULL), m_server_response(NULL), m_cache_response(NULL), m_client_req_url_str(NULL), m_client_req_url_len(0), m_client_req_url_canon_str(NULL), m_client_req_url_canon_len(0), m_client_req_unmapped_url_canon_str(NULL), m_client_req_unmapped_url_canon_len(-1),      // undetermined
   m_client_req_unmapped_url_path_str(NULL), m_client_req_unmapped_url_path_len(-1),     // undetermined
   m_client_req_unmapped_url_host_str(NULL), m_client_req_unmapped_url_host_len(-1),
   m_client_req_url_path_str(NULL),
@@ -125,6 +125,9 @@ LogAccessHttp::init()
   if (hdr->server_response.valid()) {
     m_server_response = &(hdr->server_response);
   }
+  if (hdr->cache_response.valid()) {
+    m_cache_response = &(hdr->cache_response);
+  }
 }
 
 /*-------------------------------------------------------------------------
@@ -830,6 +833,73 @@ LogAccessHttp::marshal_server_resp_http_version(char *buf)
   return (2 * 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_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)
 {
@@ -958,6 +1028,10 @@ LogAccessHttp::marshal_http_header_field(LogField::Container container, char *fi
     header = m_server_response;
     break;
 
+  case LogField::CSSH:
+    header = m_cache_response;
+    break;
+
   default:
     header = NULL;
     break;
@@ -1055,6 +1129,10 @@ LogAccessHttp::marshal_http_header_field_escapify(LogField::Container container,
     header = m_server_response;
     break;
 
+  case LogField::ECSSH:
+    header = m_cache_response;
+    break;
+
   default:
     header = NULL;
     break;

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0e20aad0/proxy/logging/LogAccessHttp.h
----------------------------------------------------------------------
diff --git a/proxy/logging/LogAccessHttp.h b/proxy/logging/LogAccessHttp.h
index 952622a..8692831 100644
--- a/proxy/logging/LogAccessHttp.h
+++ b/proxy/logging/LogAccessHttp.h
@@ -104,6 +104,14 @@ public:
   virtual int marshal_server_resp_http_version(char *); // INT
 
   //
+  // cache -> client fields
+  //
+  virtual int marshal_cache_resp_status_code(char *);  // INT
+  virtual int marshal_cache_resp_content_len(char *);  // INT
+  virtual int marshal_cache_resp_header_len(char *);   // INT
+  virtual int marshal_cache_resp_http_version(char *); // INT
+
+  //
   // congestion control client_retry_after_time
   //
   virtual int marshal_client_retry_after_time(char *);  // INT
@@ -136,6 +144,7 @@ private:
   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;

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0e20aad0/proxy/logging/LogConfig.cc
----------------------------------------------------------------------
diff --git a/proxy/logging/LogConfig.cc b/proxy/logging/LogConfig.cc
index b06c2d8..94160c4 100644
--- a/proxy/logging/LogConfig.cc
+++ b/proxy/logging/LogConfig.cc
@@ -1998,6 +1998,30 @@ LogConfig::read_xml_log_config(int from_memory)
       }
 
       LogField *logfield = Log::global_field_list.find_by_symbol(field_str);
+      if (!logfield) {
+        // check for container fields
+        if (*field_str == '{') {
+          Note("%s appears to be a container field", field_str);
+          char *fname_end = strchr(field_str, '}');
+          if (NULL != fname_end) {
+            char *fname = field_str + 1;
+            *fname_end = 0;          // changes '}' to '\0'
+            char *cname = fname_end + 1;     // start of container symbol
+            Note("Found Container Field: Name = %s, symbol = %s", fname, cname);
+            LogField::Container container = LogField::valid_container_name(cname);
+            if (container == LogField::NO_CONTAINER) {
+              Warning("%s is not a valid container; " "cannot create filter %s.", cname, filter_name);
+              continue;
+            } else {
+              logfield = new LogField(fname, container);
+              ink_assert(logfield != NULL);
+            }
+          } else {
+            Warning("Invalid container field specification: no trailing " "'}' in %s" "cannot create filter %s.", field_str, filter_name);
+            continue;
+          }
+        }
+      }
 
       if (!logfield) {
         Warning("%s is not a valid field; " "cannot create filter %s.", field_str, filter_name);

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0e20aad0/proxy/logging/LogField.cc
----------------------------------------------------------------------
diff --git a/proxy/logging/LogField.cc b/proxy/logging/LogField.cc
index 6a781a8..f3fbc52 100644
--- a/proxy/logging/LogField.cc
+++ b/proxy/logging/LogField.cc
@@ -43,10 +43,12 @@ const char *container_names[] = {
   "psh",
   "pqh",
   "ssh",
+  "cssh",
   "ecqh",
   "epsh",
   "epqh",
   "essh",
+  "ecssh",
   "icfg",
   "scfg",
   "record",
@@ -122,10 +124,12 @@ LogField::LogField(const char *field, Container container)
   case PSH:
   case PQH:
   case SSH:
+  case CSSH:
   case ECQH:
   case EPSH:
   case EPQH:
   case ESSH:
+  case ECSSH:
   case SCFG:
     m_unmarshal_func = &(LogAccess::unmarshal_str);
     break;
@@ -182,12 +186,14 @@ LogField::marshal_len(LogAccess *lad)
   case PSH:
   case PQH:
   case SSH:
+  case CSSH:
     return lad->marshal_http_header_field(m_container, m_name, NULL);
 
   case ECQH:
   case EPSH:
   case EPQH:
   case ESSH:
+  case ECSSH:
     return lad->marshal_http_header_field_escapify(m_container, m_name, NULL);
 
   case ICFG:
@@ -221,12 +227,14 @@ LogField::marshal(LogAccess *lad, char *buf)
   case PSH:
   case PQH:
   case SSH:
+  case CSSH:
     return lad->marshal_http_header_field(m_container, m_name, buf);
 
   case ECQH:
   case EPSH:
   case EPQH:
   case ESSH:
+  case ECSSH:
     return lad->marshal_http_header_field_escapify(m_container, m_name, buf);
 
   case ICFG:

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0e20aad0/proxy/logging/LogField.h
----------------------------------------------------------------------
diff --git a/proxy/logging/LogField.h b/proxy/logging/LogField.h
index 20b2957..6aa35d1 100644
--- a/proxy/logging/LogField.h
+++ b/proxy/logging/LogField.h
@@ -66,10 +66,12 @@ public:
     PSH,
     PQH,
     SSH,
+    CSSH,
     ECQH,
     EPSH,
     EPQH,
     ESSH,
+    ECSSH,
     ICFG,
     SCFG,
     RECORD,