1 /** @file 2 3 A brief file description 4 5 @section license License 6 7 Licensed to the Apache Software Foundation (ASF) under one 8 or more contributor license agreements. See the NOTICE file 9 distributed with this work for additional information 10 regarding copyright ownership. The ASF licenses this file 11 to you under the Apache License, Version 2.0 (the 12 "License"); you may not use this file except in compliance 13 with the License. You may obtain a copy of the License at 14 15 http://www.apache.org/licenses/LICENSE-2.0 16 17 Unless required by applicable law or agreed to in writing, software 18 distributed under the License is distributed on an "AS IS" BASIS, 19 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 See the License for the specific language governing permissions and 21 limitations under the License. 22 */ 23 24 #pragma once 25 26 #include <string_view> 27 #include <string> 28 29 #include "tscore/ink_platform.h" 30 #include "tscore/List.h" 31 #include "tscore/TsBuffer.h" 32 #include "LogFieldAliasMap.h" 33 #include "Milestones.h" 34 35 class LogAccess; 36 37 struct LogSlice { 38 bool m_enable; 39 int m_start; 40 int m_end; 41 LogSliceLogSlice42 LogSlice() 43 { 44 m_enable = false; 45 m_start = 0; 46 m_end = INT_MAX; 47 } 48 49 // 50 // Initialize LogSlice by slice notation, 51 // the str looks like: "xxx[0:30]". 52 // 53 explicit LogSlice(char *str); 54 55 // 56 // Convert slice notation to target string's offset, 57 // return the available length belongs to this slice. 58 // 59 // Use the offset and return value, we can locate the 60 // string content indicated by this slice. 61 // 62 int toStrOffset(int strlen, int *offset); 63 }; 64 65 /*------------------------------------------------------------------------- 66 LogField 67 68 This class represents a field that can be logged. To construct a new 69 field, we need to know its name, its symbol, its datatype, and the 70 pointer to its LogAccess marshalling routine. Example: 71 72 LogField ("client_host_ip", "chi", LogField::INT, 73 &LogAccess::marshal_client_host_ip); 74 -------------------------------------------------------------------------*/ 75 76 class LogField 77 { 78 public: 79 typedef int (LogAccess::*MarshalFunc)(char *buf); 80 typedef int (*UnmarshalFunc)(char **buf, char *dest, int len); 81 typedef int (*UnmarshalFuncWithSlice)(char **buf, char *dest, int len, LogSlice *slice); 82 typedef int (*UnmarshalFuncWithMap)(char **buf, char *dest, int len, const Ptr<LogFieldAliasMap> &map); 83 typedef void (LogAccess::*SetFunc)(char *buf, int len); 84 85 enum Type { 86 sINT = 0, 87 dINT, 88 STRING, 89 IP, ///< IP Address. 90 N_TYPES 91 }; 92 93 enum Container { 94 NO_CONTAINER = 0, 95 CQH, 96 PSH, 97 PQH, 98 SSH, 99 CSSH, 100 ECQH, 101 EPSH, 102 EPQH, 103 ESSH, 104 ECSSH, 105 ICFG, 106 SCFG, 107 RECORD, 108 MS, 109 MSDMS, 110 N_CONTAINERS, 111 }; 112 113 enum Aggregate { 114 NO_AGGREGATE = 0, 115 eCOUNT, 116 eSUM, 117 eAVG, 118 eFIRST, 119 eLAST, 120 N_AGGREGATES, 121 }; 122 123 LogField(const char *name, const char *symbol, Type type, MarshalFunc marshal, UnmarshalFunc unmarshal, 124 SetFunc _setFunc = nullptr); 125 126 LogField(const char *name, const char *symbol, Type type, MarshalFunc marshal, UnmarshalFuncWithMap unmarshal, 127 const Ptr<LogFieldAliasMap> &map, SetFunc _setFunc = nullptr); 128 129 LogField(const char *field, Container container, SetFunc _setFunc = nullptr); 130 LogField(const LogField &rhs); 131 ~LogField(); 132 133 unsigned marshal_len(LogAccess *lad); 134 unsigned marshal(LogAccess *lad, char *buf); 135 unsigned marshal_agg(char *buf); 136 unsigned unmarshal(char **buf, char *dest, int len); 137 void display(FILE *fd = stdout); 138 bool operator==(LogField &rhs); 139 void updateField(LogAccess *lad, char *val, int len); 140 141 const char * name()142 name() const 143 { 144 return m_name; 145 } 146 147 const char * symbol()148 symbol() const 149 { 150 return m_symbol; 151 } 152 153 Type type()154 type() const 155 { 156 return m_type; 157 } 158 159 Ptr<LogFieldAliasMap> map()160 map() 161 { 162 return m_alias_map; 163 } 164 165 Aggregate aggregate()166 aggregate() const 167 { 168 return m_agg_op; 169 } 170 171 bool is_time_field()172 is_time_field() const 173 { 174 return m_time_field; 175 } 176 177 inkcoreapi void set_http_header_field(LogAccess *lad, LogField::Container container, char *field, char *buf, int len); 178 void set_aggregate_op(Aggregate agg_op); 179 void update_aggregate(int64_t val); 180 181 static void init_milestone_container(); 182 static Container valid_container_name(char *name); 183 static Aggregate valid_aggregate_name(char *name); 184 static bool fieldlist_contains_aggregates(const char *fieldlist); 185 static bool isContainerUpdateFieldSupported(Container container); 186 187 private: 188 char *m_name; 189 char *m_symbol; 190 Type m_type; 191 Container m_container; 192 MarshalFunc m_marshal_func; // place data into buffer 193 UnmarshalFunc m_unmarshal_func; // create a string of the data 194 UnmarshalFuncWithMap m_unmarshal_func_map; 195 Aggregate m_agg_op; 196 int64_t m_agg_cnt; 197 int64_t m_agg_val; 198 TSMilestonesType m_milestone1; ///< Used for MS and MSDMS as the first (or only) milestone. 199 TSMilestonesType m_milestone2; ///< Second milestone for MSDMS 200 bool m_time_field; 201 Ptr<LogFieldAliasMap> m_alias_map; // map sINT <--> string 202 SetFunc m_set_func; 203 TSMilestonesType milestone_from_m_name(); 204 int milestones_from_m_name(TSMilestonesType *m1, TSMilestonesType *m2); 205 206 public: 207 LINK(LogField, link); 208 LogSlice m_slice; 209 210 // noncopyable 211 // -- member functions that are not allowed -- 212 LogField &operator=(const LogField &rhs) = delete; 213 214 private: 215 LogField(); 216 }; 217 218 /*------------------------------------------------------------------------- 219 LogFieldList 220 221 This class maintains a list of LogField objects (tah-dah). 222 -------------------------------------------------------------------------*/ 223 224 class LogFieldList 225 { 226 public: 227 LogFieldList(); 228 ~LogFieldList(); 229 230 void clear(); 231 void add(LogField *field, bool copy = true); 232 LogField *find_by_name(const char *name) const; 233 LogField *find_by_symbol(const char *symbol) const; 234 unsigned marshal_len(LogAccess *lad); 235 unsigned marshal(LogAccess *lad, char *buf); 236 unsigned marshal_agg(char *buf); 237 238 LogField * first()239 first() const 240 { 241 return m_field_list.head; 242 } 243 LogField * next(LogField * here)244 next(LogField *here) const 245 { 246 return (here->link).next; 247 } 248 unsigned count(); 249 void display(FILE *fd = stdout); 250 251 // Add a bad symbol seen in the log format to the list of bad symbols. 252 // 253 void addBadSymbol(std::string_view badSymbol); 254 255 // Return blank-separated list of added bad symbols. 256 // 257 std::string_view badSymbols()258 badSymbols() const 259 { 260 return _badSymbols; 261 } 262 263 // noncopyable 264 // -- member functions that are not allowed -- 265 LogFieldList(const LogFieldList &rhs) = delete; 266 LogFieldList &operator=(const LogFieldList &rhs) = delete; 267 268 private: 269 unsigned m_marshal_len = 0; 270 Queue<LogField> m_field_list; 271 std::string _badSymbols; 272 }; 273 274 /** Base IP address data. 275 To unpack an IP address, the generic memory is first cast to 276 this type to get the family. That pointer can then be static_cast 277 to the appropriate subtype to get the actual address data. 278 279 @note We don't use our own enum for the family. Instead we use 280 @c AF_INET and @c AF_INET6. 281 */ 282 struct LogFieldIp { 283 uint16_t _family; ///< IP address family. 284 }; 285 /// IPv4 address as log field. 286 struct LogFieldIp4 : public LogFieldIp { 287 in_addr_t _addr; ///< IPv4 address. 288 }; 289 /// IPv6 address as log field. 290 struct LogFieldIp6 : public LogFieldIp { 291 in6_addr _addr; ///< IPv6 address. 292 }; 293 /// Something big enough to hold any of the IP field types. 294 union LogFieldIpStorage { 295 LogFieldIp _ip; 296 LogFieldIp4 _ip4; 297 LogFieldIp6 _ip6; 298 }; 299