blob: 5b19aace7c174cc133f0cb4098f16a41e2c5519c [file] [log] [blame]
/** @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 <string_view>
#include <string>
#include "tscore/ink_platform.h"
#include "tscore/List.h"
#include "tscore/TsBuffer.h"
#include "LogFieldAliasMap.h"
#include "Milestones.h"
class LogAccess;
struct LogSlice {
bool m_enable;
int m_start;
int m_end;
LogSlice()
{
m_enable = false;
m_start = 0;
m_end = INT_MAX;
}
//
// Initialize LogSlice by slice notation,
// the str looks like: "xxx[0:30]".
//
explicit LogSlice(char *str);
//
// Convert slice notation to target string's offset,
// return the available length belongs to this slice.
//
// Use the offset and return value, we can locate the
// string content indicated by this slice.
//
int toStrOffset(int strlen, int *offset);
};
/*-------------------------------------------------------------------------
LogField
This class represents a field that can be logged. To construct a new
field, we need to know its name, its symbol, its datatype, and the
pointer to its LogAccess marshalling routine. Example:
LogField ("client_host_ip", "chi", LogField::INT,
&LogAccess::marshal_client_host_ip);
-------------------------------------------------------------------------*/
class LogField
{
public:
typedef int (LogAccess::*MarshalFunc)(char *buf);
typedef int (*UnmarshalFunc)(char **buf, char *dest, int len);
typedef int (*UnmarshalFuncWithSlice)(char **buf, char *dest, int len, LogSlice *slice);
typedef int (*UnmarshalFuncWithMap)(char **buf, char *dest, int len, const Ptr<LogFieldAliasMap> &map);
typedef void (LogAccess::*SetFunc)(char *buf, int len);
enum Type {
sINT = 0,
dINT,
STRING,
IP, ///< IP Address.
N_TYPES
};
enum Container {
NO_CONTAINER = 0,
CQH,
PSH,
PQH,
SSH,
CSSH,
ECQH,
EPSH,
EPQH,
ESSH,
ECSSH,
ICFG,
SCFG,
RECORD,
MS,
MSDMS,
N_CONTAINERS,
};
enum Aggregate {
NO_AGGREGATE = 0,
eCOUNT,
eSUM,
eAVG,
eFIRST,
eLAST,
N_AGGREGATES,
};
LogField(const char *name, const char *symbol, Type type, MarshalFunc marshal, UnmarshalFunc unmarshal,
SetFunc _setFunc = nullptr);
LogField(const char *name, const char *symbol, Type type, MarshalFunc marshal, UnmarshalFuncWithMap unmarshal,
const Ptr<LogFieldAliasMap> &map, SetFunc _setFunc = nullptr);
LogField(const char *field, Container container, SetFunc _setFunc = nullptr);
LogField(const LogField &rhs);
~LogField();
unsigned marshal_len(LogAccess *lad);
unsigned marshal(LogAccess *lad, char *buf);
unsigned marshal_agg(char *buf);
unsigned unmarshal(char **buf, char *dest, int len);
void display(FILE *fd = stdout);
bool operator==(LogField &rhs);
void updateField(LogAccess *lad, char *val, int len);
const char *
name() const
{
return m_name;
}
const char *
symbol() const
{
return m_symbol;
}
Type
type() const
{
return m_type;
}
Ptr<LogFieldAliasMap>
map()
{
return m_alias_map;
}
Aggregate
aggregate() const
{
return m_agg_op;
}
bool
is_time_field() const
{
return m_time_field;
}
inkcoreapi void set_http_header_field(LogAccess *lad, LogField::Container container, char *field, char *buf, int len);
void set_aggregate_op(Aggregate agg_op);
void update_aggregate(int64_t val);
static void init_milestone_container();
static Container valid_container_name(char *name);
static Aggregate valid_aggregate_name(char *name);
static bool fieldlist_contains_aggregates(const char *fieldlist);
static bool isContainerUpdateFieldSupported(Container container);
private:
char *m_name;
char *m_symbol;
Type m_type;
Container m_container;
MarshalFunc m_marshal_func; // place data into buffer
UnmarshalFunc m_unmarshal_func; // create a string of the data
UnmarshalFuncWithMap m_unmarshal_func_map;
Aggregate m_agg_op;
int64_t m_agg_cnt;
int64_t m_agg_val;
TSMilestonesType m_milestone1; ///< Used for MS and MSDMS as the first (or only) milestone.
TSMilestonesType m_milestone2; ///< Second milestone for MSDMS
bool m_time_field;
Ptr<LogFieldAliasMap> m_alias_map; // map sINT <--> string
SetFunc m_set_func;
TSMilestonesType milestone_from_m_name();
int milestones_from_m_name(TSMilestonesType *m1, TSMilestonesType *m2);
public:
LINK(LogField, link);
LogSlice m_slice;
// noncopyable
// -- member functions that are not allowed --
LogField &operator=(const LogField &rhs) = delete;
private:
LogField();
};
/*-------------------------------------------------------------------------
LogFieldList
This class maintains a list of LogField objects (tah-dah).
-------------------------------------------------------------------------*/
class LogFieldList
{
public:
LogFieldList();
~LogFieldList();
void clear();
void add(LogField *field, bool copy = true);
LogField *find_by_name(const char *name) const;
LogField *find_by_symbol(const char *symbol) const;
unsigned marshal_len(LogAccess *lad);
unsigned marshal(LogAccess *lad, char *buf);
unsigned marshal_agg(char *buf);
LogField *
first() const
{
return m_field_list.head;
}
LogField *
next(LogField *here) const
{
return (here->link).next;
}
unsigned count();
void display(FILE *fd = stdout);
// Add a bad symbol seen in the log format to the list of bad symbols.
//
void addBadSymbol(std::string_view badSymbol);
// Return blank-separated list of added bad symbols.
//
std::string_view
badSymbols() const
{
return _badSymbols;
}
// noncopyable
// -- member functions that are not allowed --
LogFieldList(const LogFieldList &rhs) = delete;
LogFieldList &operator=(const LogFieldList &rhs) = delete;
private:
unsigned m_marshal_len = 0;
Queue<LogField> m_field_list;
std::string _badSymbols;
};
/** Base IP address data.
To unpack an IP address, the generic memory is first cast to
this type to get the family. That pointer can then be static_cast
to the appropriate subtype to get the actual address data.
@note We don't use our own enum for the family. Instead we use
@c AF_INET and @c AF_INET6.
*/
struct LogFieldIp {
uint16_t _family; ///< IP address family.
};
/// IPv4 address as log field.
struct LogFieldIp4 : public LogFieldIp {
in_addr_t _addr; ///< IPv4 address.
};
/// IPv6 address as log field.
struct LogFieldIp6 : public LogFieldIp {
in6_addr _addr; ///< IPv6 address.
};
/// Something big enough to hold any of the IP field types.
union LogFieldIpStorage {
LogFieldIp _ip;
LogFieldIp4 _ip4;
LogFieldIp6 _ip6;
};