gestione gare pubbliche
Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 
 
 

231 righe
7.1 KiB

<?php
/**
* Gestore delle deleghe ANAC NPA
*/
trait NpaLogger
{
public bool $disableLogs = false;
/**
* Ottiene il path per i log atomici
*
* @param boolean $create Se true e il path non esiste, viene creato
* @return string Ritorna il path in questions
*/
private function getAtomicLogPath(bool $create = false): string
{
global $config;
$fascicolo = $this->fascicolo["codice"] ?? 0;
$scheda = $this->scheda["codice"] ?? 0;
$subPath = "{$fascicolo}";
if ($scheda > 0) {
$subPath .= "/{$scheda}";
}
$domain = $_SESSION["ente"]->getInfo()["dominio"] ?? "global";
$folder = "{$config["npaFolder"]}/smartLog/{$domain}/{$subPath}";
if ($create) {
if (!file_exists($folder))
mkdir($folder, 0777, true);
}
return $folder;
}
/**
* Ottiene i log disponibili per questa scheda o fascicolo
*
* @return array ["endpoint::method" => "filename"]
*/
public function getAvailableLogs(): array
{
$filePath = $this->getAtomicLogPath();
if(!file_exists($filePath)) return [];
$scan = scandir($filePath);
$retval = [];
foreach ($scan as $file) {
if (is_dir("{$filePath}/$file")) continue;
$file = explode(".", $file)[0];
$friendlyName = str_replace("_", "::", $file);
$retval[$friendlyName] = $file;
}
if(!empty($retval)) {
$retval["Tutti i log"] = "combined";
}
return $retval;
}
/**
* Aggiunge un nuovo log
*
* @param string $endpoint Endpoint di riferimento
* @param string $method Metodo di riferimento
* @param array $data Dati da loggare
* @param string|null $error Errore, se presente, da loggare
* @return void
*/
public function appendLog(string $endpoint, string $method, array $data, ?string $error = null): void
{
if ($this->disableLogs) return;
if ($error)
$data["error"] = $error;
foreach ($data as $name => $entry) {
if (is_string($entry)) {
if ($name === "request") {
preg_match_all("/(^.*(GovWay|Agid|Authorization|GET \/|Host:|HTTP\/).*$)/m", $entry, $matches);
$data[$name] = implode("\n", $matches[0] ?? []);
} elseif (valid_json($entry, $rawEntry, true)) {
$data[$name] = $rawEntry;
}
}
}
// Log consultabili
$filePath = $this->getAtomicLogPath(true) . "/{$endpoint}_{$method}.gz";
$data["_datetime"] = (new \DateTime())->format(DateTime::ATOM);
$jsonData = json_encode($data) . "\n";
$fp = fopen("compress.zlib://{$filePath}", 'ab');
if ($fp) {
fwrite($fp, $jsonData);
fclose($fp);
} else {
throw new Exception("Impossibile scrivere sui log.");
}
// Log legacy per archivio
global $config;
$domain = $_SESSION["ente"]->getInfo()["dominio"] ?? "global";
$filename = date('Ymd') . ".log";
$npaFolder = $config["npaFolder"] . "/" . $domain;
if (!is_dir($npaFolder)) {
mkdir($npaFolder, 0755, true);
}
$legacyLog = "[" . date('Y-m-d H:i:s') . "]" . PHP_EOL;
$legacyLog .= "\tURL: {$endpoint}::{$method}" . PHP_EOL;
foreach ($data as $name => $entry) {
if ($name[0] === "_") continue;
$legacyLog .= "\t" . substr(strtoupper($name), 0, 3) . ": " . ($name === "request" ? base64_encode($entry) : json_encode($entry)) . PHP_EOL;
}
error_log($legacyLog . PHP_EOL, 3, "{$npaFolder}/{$filename}");
}
/**
* Ruota i log di piattaforma
*
* @return void
*/
public static function rotateLogs()
{
if (!defined("__CMDS_JOB_EXEC")) {
return;
}
global $config;
// Elimina i log più vecchi di 3 mesi
$smartLogFolder = "{$config["npaFolder"]}/smartLog";
$it = new RecursiveDirectoryIterator($smartLogFolder);
$toDelete = [];
foreach (new RecursiveIteratorIterator($it) as $file) {
if ($file->getExtension() == 'gz') {
if ($file->getmTime() < (time() - (90 * 24 * 60 * 60))) {
$toDelete[] = $file->getPathname();
}
}
}
// Comprime i vecchi log legacy
$today = date('Ymd');
$it = new RecursiveDirectoryIterator($config["npaFolder"]);
foreach (new RecursiveIteratorIterator($it) as $file) {
if ($file->getExtension() == 'log') {
if ($file->getBasename() !== "{$today}.log") {
exec("cd {$file->getPath()} && tar -czvf \"{$file->getBasename()}.tar.gz\" \"{$file->getFilename()}\"");
$toDelete[] = $file->getPathname();
}
}
}
foreach(array_unique($toDelete) as $filePath) {
try{
unlink($filePath);
} catch(\Exception $e) {
alertManager::printCliAlert("Impossibile eliminare il file '{$filePath}'");
alertManager::printCliException($e);
}
}
}
/**
* Ottiene i log da un file dei log atomici
*
* @param string $path Path da caricare
* @return array Ritorna un array con le entry di log
*/
public function retrieveLogs(string $requestedPath): array
{
if($requestedPath === "combined") {
$filePath = $this->getAtomicLogPath();
if(!file_exists($filePath)) return [];
$scan = scandir($filePath);
$entries = [];
foreach ($scan as $file) {
if(str_ends_with($file, ".gz")) {
$logs = $this->retrieveLogs(str_replace(".gz", "", $file));
foreach($logs as &$entry) {
$entry = array_merge(["file" => $file], $entry);
}
$entries = array_merge($entries, $logs);
}
}
usort($entries, function($a, $b) {
return $a["_datetime"] < $b["_datetime"];
});
return $entries;
}
$logFolder = $this->getAtomicLogPath();
// Preveniamo directory trasversal
$realBase = realpath($logFolder);
$browsingPath = $logFolder . "/" . ltrim($requestedPath, "/") . ".gz" ;
$browsingPath = realpath($browsingPath);
if ($browsingPath === false || strpos($browsingPath, $realBase) !== 0) {
// Path non valido
$requestedPath = "";
$browsingPath = $logFolder;
}
$requestedPath = substr($browsingPath, strlen($logFolder));
$data = [];
$fp = fopen("compress.zlib://{$browsingPath}", 'rb');
if ($fp) {
while (($line = fgets($fp)) !== false) {
$data[] = json_decode($line, true);
}
fclose($fp);
}
return array_reverse($data);
}
}