952 days continuous production uptime, 40k+ tp/s single node. Original corpo Bitbucket history not included — clean archive commit.
435 lines
21 KiB
PHP
435 lines
21 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Class gatLog
|
|
*
|
|
* This is the logging class definition that records application-generated events.
|
|
*
|
|
* Design Notes:
|
|
* -------------
|
|
* because this is a log, and log events are processed by a FnF queue, we're not going to cache, or use auditing.
|
|
* History is not recorded for this class.
|
|
* Only one status is supported: ACTIVE and there are no updates allowed making record-locking unnecessary.
|
|
* Cache timers on the class are disabled because recursion.
|
|
* id's (auto-incrementing integers) are deprecated and replaced by the native _id.
|
|
* The created date is stored an epoch time (integer).
|
|
*
|
|
* @author mike@givingassistant.org
|
|
* @version 1.0
|
|
*
|
|
* HISTORY:
|
|
* ========
|
|
* 07-06-17 mks CORE-463: code complete (refactor from ddb to mdb)
|
|
* 07-12-17 mks added log-level value column to collection for ranged searching
|
|
* 08-04-17 mks added version control, partialIndexes
|
|
* 08-11-17 mks CORE-467: indexes brought up to mongo 3.2 standards and made consistent
|
|
* 04-19-18 mks _INF-188: warehousing section added
|
|
* 01-13-20 mks DB-150: PHP7.4 class member type-casting
|
|
* 06-01-20 mks ECI-108: support for auth token
|
|
*
|
|
*/
|
|
class gatLogs {
|
|
public int $version = 1;
|
|
public string $service = CONFIG_DATABASE_SERVICE_ADMIN; // defines the mongo server destination
|
|
public string $schema = TEMPLATE_DB_MONGO; // defines the storage schema for the class
|
|
public string $templateClass = TEMPLATE_CLASS_LOGS; // defines the clear-text template class name
|
|
public string $collection = COLLECTION_MONGO_LOGS; // sets the collection (table) name
|
|
public ?string $whTemplate = null; // sets the WH(cool) collection name, null if not wh'd
|
|
public string $extension = COLLECTION_MONGO_LOGS_EXT; // sets the extension for the collection
|
|
public bool $closedClass = true; // set to false to allow partner instantiations
|
|
public bool $setCache = false; // set to true to cache class data
|
|
public bool $setDeletes = true; // set to true to allow HARD deletes (otherwise: SOFT)
|
|
public int $setAuditing = AUDIT_NOT_ENABLED; // set to AUDIT_value constant
|
|
public bool $setJournaling = false; // set to true to allow journaling
|
|
public bool $setUpdates = false; // set to true to allow record updates
|
|
public bool $setHistory = false; // set to true to enable detailed record history tracking
|
|
public string $setDefaultStatus = STATUS_ACTIVE; // set the default status for each record
|
|
public string $setSearchStatus = STATUS_ACTIVE; // set the default search status
|
|
public bool $setLocking = false; // set to true to enable record locking for collection
|
|
public bool $setTimers = false; // set to true to enable collection query timers
|
|
public string $setPKey = MONGO_ID; // sets the primary key for the collection
|
|
public bool $setTokens = false; // set to true: adds the idToken field functionality
|
|
public bool $selfDestruct = true; // set to false if the class contains methods
|
|
public int $cacheTimer = 0; // number of seconds a tuple will remain in-cache
|
|
public bool $isGA = true; // set to true is this class is a Namaste internal class
|
|
public ?string $authToken = null; // if this data class is registered to a partner, you will
|
|
// need to initialize this member in the constructor (hard-coded)
|
|
|
|
|
|
// fields: a key-value paired array, defines the field name and the data type for each field. Prior to insertion,
|
|
// all data is validated for type and membership. Data that does not satisfy these requirements is
|
|
// silently dropped prior to insertion.
|
|
public array $fields = [
|
|
MONGO_ID => DATA_TYPE_OBJECT, // sorting by the id is just like sorting by createdDate
|
|
LOG_FILE => DATA_TYPE_STRING,
|
|
LOG_METHOD => DATA_TYPE_STRING,
|
|
LOG_LINE => DATA_TYPE_INTEGER,
|
|
LOG_CLASS => DATA_TYPE_STRING,
|
|
LOG_LEVEL => DATA_TYPE_STRING,
|
|
LOG_VALUE => DATA_TYPE_INTEGER,
|
|
LOG_MESSAGE => DATA_TYPE_STRING,
|
|
DB_STATUS => DATA_TYPE_STRING,
|
|
DB_EVENT_GUID => DATA_TYPE_STRING,
|
|
LOG_CREATED => DATA_TYPE_INTEGER
|
|
];
|
|
|
|
|
|
// all index names that are explicitly declared in the indexes below must also appear in this array. If there are
|
|
// no pre-defined index names, then this field should be set to null.
|
|
//
|
|
// Note that if you're allowing mysql to generate the index names for you, and if you use a partial index (below)
|
|
// that references that randomly-generated index name, and that name does not appear in this list, then you will
|
|
// fail to load that template at run time, every time.
|
|
//
|
|
// You have been warned.
|
|
//
|
|
public ?array $indexNameList = null;
|
|
|
|
|
|
// all fields that appear in any of the index declarations must appear in this list as this is the property
|
|
// that's used in the framework as an authoritative check to qualify discriminant fields as indexes.
|
|
//
|
|
// indexes are always declared with the template column name and not the cache-map column name
|
|
//
|
|
// warehouse indexes are limited to the original record's created date and the three WH fields only
|
|
//
|
|
public array $indexFields = [ MONGO_ID, LOG_CREATED, LOG_VALUE, LOG_FILE, LOG_LEVEL, DB_EVENT_GUID ];
|
|
|
|
// single field index declarations -- since you can have a field in more than one index
|
|
// (MONGO_ID should NEVER be listed as it's the default single-field index.)
|
|
// the format for the single-field index declaration is the same format used for all the
|
|
// index declarations:
|
|
// [ FIELD_NAME => <SORT-DIRECTION> ] where <SORT_DIR> = [ 1 | -1 ]
|
|
//
|
|
// NOTE: if you're going to declare a single column as a property, then do NOT also declare it as a single index!
|
|
//
|
|
public ?array $singleFields = [
|
|
LOG_CREATED => -1,
|
|
LOG_VALUE => 1,
|
|
LOG_FILE => 1,
|
|
LOG_LEVEL => 1,
|
|
DB_EVENT_GUID => 1
|
|
];
|
|
|
|
// compound indexes have format of:
|
|
// [ INDEX-NAME => [ FIELD_NAME => <SORT-DIR>, ... ]]
|
|
// where INDEX-NAME is a unique string and SORT-DIR = [1|-1]
|
|
// unless it's for mongoDB -- mongoDB does not use index labels
|
|
public ?array $compoundIndexes = null;
|
|
|
|
// multiKey indexes are indexes on fields that are arrays (not the same as sub-collections) which indexes the
|
|
// content stored in the array based on the column names.
|
|
//
|
|
// mongo, as of 3.4, automatically creates a multi-key index on any field declared as a (sic) index that's
|
|
// an array. Meaning: we don't need to explicitly create a multi-key index on an array field if that field
|
|
// is declared as a single-key, compound, or unique index.
|
|
//
|
|
// -----------------------------------------------------------------------------------------------------------------
|
|
// NOTES: if you implicitly declare a multi-key index by using the column as a compound-index field, then you
|
|
// may, at MOST, have one array within the compound index.
|
|
//
|
|
// You may NOT declare a multi-key index as a shard key.
|
|
//
|
|
// Hashed keys may NOT be multi-key.
|
|
// -----------------------------------------------------------------------------------------------------------------
|
|
//
|
|
// In other words, if you want to apply an index to ALL of the array element then declare the column as singleField,
|
|
// or compound, or unique. This will have the multi-key index automagically applied by mongoDB.
|
|
//
|
|
// If you want to index a subset of the array, then declare the fields to be indexed by using dot notation:
|
|
//
|
|
// [ 'someIndex' => [ arrayColumnName.subField1 => 1, arrayColumnName.subField3 => -1 ... ] ]
|
|
//
|
|
// And this will apply the multi-key index property to subField1 and subField3 only.
|
|
//
|
|
// multiKey indexes are referenced by an index name in order to remove ambiguity when parsing index-properties
|
|
// against this and other indexes that may have the same field name. In other words, index-properties that will
|
|
// be applied to a multiKey index must reference the multiKey index by the index (and not the column) name.
|
|
//
|
|
// example:
|
|
// [ 'mIdx1Test' => [ ARRAY_FIELD_NAME => <1|-1>, ... ]]
|
|
//
|
|
public ?array $multiKey = null;
|
|
|
|
/*
|
|
* Valid index-type constants are:
|
|
* MONGO_INDEX_TYPE_SINGLE
|
|
* MONGO_INDEX_TYPE_COMPOUND
|
|
* MONGO_INDEX_TYPE_MULTIKEY
|
|
*
|
|
* INDEXES NOT SUPPORTED BY NAMASTE AT THIS TIME:
|
|
* ----------------------------------------------
|
|
* geoSpatial
|
|
* text
|
|
* hashed
|
|
*
|
|
*/
|
|
|
|
// =================================================================================================================
|
|
// INDEX PROPERTIES
|
|
// ----------------
|
|
// Index properties are applied to indexes. The supported properties are:
|
|
// unique, partial and ttl
|
|
// sparse is not supported because partial
|
|
//
|
|
// If a property is not in-use, then you must still declare the property as a class object but the
|
|
// value of the property will be set to null.
|
|
//
|
|
// Sparse property types are not supported in favor of partials.
|
|
//
|
|
// =================================================================================================================
|
|
|
|
|
|
// Partial Indexes are supported as of MongoDB 3.2 and replace sparse indexes. Format for declaration is the
|
|
// column name as an array key, with the value being a sub-array of a mongo operand and a value, all of which is
|
|
// associated with either an existing column name or index label.
|
|
//
|
|
// If an existing column name is used, then that field must be defined (exists) in one of the above index
|
|
// declarations for single, compound, or multikey indexes.
|
|
//
|
|
// Format:
|
|
// { expr1 }, { expr2 }
|
|
// Where:
|
|
// expr1 is an indexed column and the index direction. e.g.: { created_tst : 1 }
|
|
// AND
|
|
// expr2 is the keyword "partialFilterExpression : { [ query ] }
|
|
// e.g.: { partialFilterExpression : { integer_tst : { $gte : 10 }}
|
|
//
|
|
// db.myTable.createIndex({ lastName: -1, firstName : 1 }, { partialFilterExpression : { age : { $gte : 62 }})
|
|
// The above index would return a list of names (sorted DESC by last name) for people aged 62 or older.
|
|
//
|
|
//
|
|
public ?array $partialIndexes = null;
|
|
|
|
// unique indexes cause MongoDB to reject duplicate values for the indexed field. Unique indexes
|
|
// are functionally interchangeable with other mongo indexes.
|
|
// Format:
|
|
// [ < FIELD_NAME | INDEX-NAME > => <SORT_DIR>, ... ]
|
|
//
|
|
public ?array $uniqueIndexes = null; // token is not required for system collections
|
|
|
|
// ttl indexes contain the column name and the time-to-live in seconds (e.g.: MONGO_TOKEN => 3600)
|
|
// ttl indexes can only be applied to fields that are MongoDB Date() (object) types, or an array that
|
|
// contains date values.
|
|
//
|
|
// If the field is an array, and there are multiple date values in the index, MongoDB uses lowest
|
|
// (i.e. earliest) date value in the array to calculate the expiration threshold. If the indexed
|
|
// field in a document is not a date or an array that holds a date value(s), the document will not expire.
|
|
//
|
|
// Format:
|
|
// [ SOME_FIELD_NAME => ExpireVal ]
|
|
//
|
|
// Example:
|
|
// [ SOME_FIELD_NAME => 86400 ] --- record will be sorted ASC and deleted after 1 day
|
|
//
|
|
public ?array $ttlIndexes = null; // ttl indexes appear in $indexFields
|
|
|
|
|
|
// cache maps are requires for namaste service classes. Even if caching is disabled for a class, a cache map is
|
|
// still required for the class. For PDO classes, the PDO_ID is never included in the mapping, nor is MONGO_ID.
|
|
public ?array $cacheMap = null;
|
|
|
|
public ?array $binFields = null; // binary fields require special handling; define binary fields here
|
|
|
|
// regex fields -- within the indexFields array, which fields enable regex searches?
|
|
public ?array $regexFields = null;
|
|
|
|
/*
|
|
* if there is no cache-mapping supported for the class, and you want to limit the fields returned,
|
|
* then those fields are listed here as an associative array.
|
|
*
|
|
* NOTE: You can have caching disabled for the class and still have a cache-map -- this controls the labels
|
|
* assigned to the returned data column names exposed to the client. Schema should never be exposed.
|
|
*
|
|
* NOTE: if you do not support caching for the class and this class is one that is returned to a client,
|
|
* (some classes are limited to internal use only, like logging), then you should (at a minimum)
|
|
* exclude the primary key field (integer).
|
|
*
|
|
*
|
|
* This array is an associative array -- the key is the native column name and the value doesn't matter. The
|
|
* important thing is that the keys are the column names that you want to return back to the client.
|
|
*
|
|
* If $exposedFields is to be undefined for the class, then assign it to null.
|
|
*
|
|
*/
|
|
public ?array $exposedFields = null; // lists the fields that will be sent to clients; null => all data
|
|
// cache map, if defined, will always override.
|
|
// mongo IDs are NEVER returned
|
|
|
|
/*
|
|
* sub-collections represent the implementation of a 1:M relationship at the record-entity level in mongoDB.
|
|
*
|
|
* A great example of a sub-collection implementation would be a parent collection called questions and
|
|
* a sub-collection called answers.
|
|
*
|
|
* sub-collections are declared as key->value pairs where each key value is, itself, an array of field names:
|
|
*
|
|
* public $subC = [
|
|
* FIELD_ONE => [
|
|
* SUB_COLLECTION_FIELD_ONE,
|
|
* SUB_COLLECTION_FIELD_TWO,
|
|
* ...
|
|
* ],
|
|
* ...
|
|
* ];
|
|
*
|
|
* Each sub-collection field should also appear in both the fields list (to define the types), and in the
|
|
* cacheMap (if used). If you're not using a cacheMap, and you're limiting the exposed fields, then each
|
|
* sub-collection field exposed must be listed in the exposed field list. (e.g.: normal rules for exposure
|
|
* for a collection are applied the same way to a sub-collection.)
|
|
*
|
|
* Note that if a sub-Collection key is not listed in either the cacheMap or the exposed field list, then
|
|
* the entire sub-collection will be invisible to the client. If you list the sub-collection key, you can
|
|
* limit the sub-collection fields that are exposed by not listing them in either the cacheMap or the
|
|
* exposed-field lists, respectively.
|
|
*
|
|
* Sub-collections are managed within Namaste to allow the sub-collection elements to be either inserted,
|
|
* or deleted (an update is a delete + insert) without changing the parent field values and, accordingly,
|
|
* are enabled via discrete class methods.
|
|
*
|
|
*/
|
|
// sub-collection fields must be declared here (need not be indexed)
|
|
public ?array $subC = null; // sub-collection fields must be declared here
|
|
// see gatTestMongo.class.inc for explanation & examples
|
|
|
|
|
|
//=================================================================================================================
|
|
// WAREHOUSE DECLARATIONS
|
|
// ----------------------
|
|
// This section handles the warehousing configuration for the class. If a data table is eligible to be ware-
|
|
// housed, then this section contains all the configuration information, including permissions, for the destination
|
|
// repository. Note that we need to support bi-directional flow for data.
|
|
//
|
|
// Terms/Definitions:
|
|
// ------------------
|
|
// HOT -- data is in production
|
|
// COOL -- data has been warehoused, maintains schema, but with indexing changes.
|
|
// COLD -- data has been warehoused but formatted to the destination schema, usually CSV.
|
|
// WARM -- indicates any data moving from COLD -> HOT
|
|
//
|
|
// Design Features:
|
|
// ----------------
|
|
// Supported
|
|
// This is a boolean value that indicates if the class supports warehousing. If this is set to false, then
|
|
// warehousing requests for the class will be rejected.
|
|
//
|
|
// Remote Support
|
|
// --------------
|
|
// This is a boolean value that indicates if the class will support a warehouse source outside of the Namaste
|
|
// framework. If this is set to false, and a user submits a request defining the data source as a remote
|
|
// repository, the request will be rejected.
|
|
//
|
|
// Automated
|
|
// This is a boolean value that indicates if the class allows automated warehousing, meaning that data will be
|
|
// warehoused once the qualifying condition has been met.
|
|
//
|
|
// Dynamic
|
|
// Boolean value that, if set to true, indicates that the class will accept dynamic requests. Otherwise, the
|
|
// warehousing operations will follow the interval schedule. Defaults to false.
|
|
//
|
|
// Interval
|
|
// This is a string value that tells the AT_micro-service how often to run automated warehousing on the data.
|
|
// D = Daily, M = 1st of every month, Q = 1st of every quarter, Y = 1st of every year
|
|
// The default setting for this value should be monthly (M).
|
|
//
|
|
// Qualifier
|
|
// This is a query string, similar to what you would provide to Namaste for a fetch operation, that establishes
|
|
// the filter/criteria for moving data to the warehouse. If Supported is set to true, this cannot be blank.
|
|
//
|
|
// Override
|
|
// Boolean value indicating if, and only for dynamic event requests, if the Qualifier can be overridden. If
|
|
// set to true, the the event request must contain a valid query filter.
|
|
//
|
|
// Delete
|
|
// This is a string value that tells Namaste what to do with the source data once successfully warehoused.
|
|
// H = hard delete, S = soft delete
|
|
// Note that this value overrides the $setDeletes setting.
|
|
//
|
|
//=================================================================================================================
|
|
|
|
public ?array $wareHouse = [
|
|
WH_SUPPORTED => false, // must be set to true for data class to support any warehousing
|
|
WH_REMOTE_SUPPORT => false, // must be set to true to import data into this class from remote source
|
|
WH_AUTOMATED => false, // must be set to true for warehousing to be automatically processed
|
|
WH_DYNAMIC => false, // must be set to true to allow non-scheduled event requests
|
|
WH_INTERVAL => 'M', // must be either D, M, Q or A, defaults to M
|
|
WH_OVERRIDE => false, // must be set to true to allow an ad-hoc query filter
|
|
WH_DELETE => 'H', // must be either H, or S. Can be reset to T via meta. Default: H
|
|
|
|
// default warehouse query to grab records where the date is LT a value and the status is active:
|
|
// the null value will be replaced with the value provided by the client in the wh request payload.
|
|
WH_QUALIFIER => [
|
|
DB_CREATED => [ OPERAND_NULL => [ OPERATOR_LT => [ null ] ] ],
|
|
DB_STATUS => [ OPERAND_NULL => [ OPERATOR_EQ => [ STATUS_ACTIVE ]]],
|
|
OPERAND_AND => null
|
|
]
|
|
];
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// CLASS METHODS...
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/**
|
|
* __construct() -- public method
|
|
*
|
|
* we have a constructor to register the destructor.
|
|
*
|
|
* @author mike@givingassistant.org
|
|
* @version 1.0
|
|
*
|
|
* HISTORY:
|
|
* ========
|
|
* 07-06-17 mks CORE-463: code complete (refactor from ddb to mdb)
|
|
*
|
|
*/
|
|
public function __construct()
|
|
{
|
|
$this->authToken = NULL_TOKEN;
|
|
register_shutdown_function([$this, STRING_DESTRUCTOR]);
|
|
}
|
|
|
|
|
|
/**
|
|
* __clone() -- private function
|
|
*
|
|
* Silently disallows cloning of the object
|
|
*
|
|
* @author mike@givingassistant.org
|
|
* @version 1.0
|
|
*
|
|
* @return null
|
|
*
|
|
* HISTORY:
|
|
* ========
|
|
* 07-06-17 mks CORE-463: code complete (refactor from ddb to mdb)
|
|
*
|
|
*/
|
|
private function __clone()
|
|
{
|
|
return(null);
|
|
}
|
|
|
|
|
|
/**
|
|
* __destruct() -- public function
|
|
*
|
|
* As of PHP 5.3.10 destructors are not run on shutdown caused by fatal errors.
|
|
*
|
|
* The destructor is registered as a shut-down function in the constructor -- so any recovery
|
|
* efforts should go in this method.
|
|
*
|
|
* @author mike@givingassistant.org
|
|
* @version 1.0
|
|
*
|
|
* HISTORY:
|
|
* ========
|
|
* 07-06-17 mks CORE-463: code complete (refactor from ddb to mdb)
|
|
*
|
|
*/
|
|
public function __destruct()
|
|
{
|
|
;
|
|
}
|
|
}
|