diff --git a/app/.env.sample b/app/.env.sample index a9349b6..e4e99df 100644 --- a/app/.env.sample +++ b/app/.env.sample @@ -34,3 +34,6 @@ SELENIUM_HOST=localhost:4444 # Configurações de Debug DEBUG=true + +# Configurações do Hawk.so +HAWK_TOKEN= \ No newline at end of file diff --git a/app/composer.json b/app/composer.json index b5a2852..e7be92d 100644 --- a/app/composer.json +++ b/app/composer.json @@ -3,7 +3,8 @@ "vlucas/phpdotenv": "^5.6.1", "aws/aws-sdk-php": "^3.0", "php-curl-class/php-curl-class": "^11.0", - "php-webdriver/webdriver": "^1.15" + "php-webdriver/webdriver": "^1.15", + "codex-team/hawk.php": "^2.2" }, "autoload": { "psr-4": { diff --git a/app/config.php b/app/config.php index f0cab82..f33a2b1 100644 --- a/app/config.php +++ b/app/config.php @@ -31,11 +31,18 @@ define('SELENIUM_HOST', isset($_ENV['SELENIUM_HOST']) ? $_ENV['SELENIUM_HOST'] : define('CACHE_DIR', __DIR__ . '/cache'); define('DEBUG', isset($_ENV['DEBUG']) ? filter_var($_ENV['DEBUG'], FILTER_VALIDATE_BOOLEAN) : false); -// Configurações de Redis +/** + * Configurações de Redis + */ define('REDIS_HOST', isset($_ENV['REDIS_HOST']) ? $_ENV['REDIS_HOST'] : 'localhost'); define('REDIS_PORT', isset($_ENV['REDIS_PORT']) ? $_ENV['REDIS_PORT'] : 6379); define('REDIS_PREFIX', isset($_ENV['REDIS_PREFIX']) ? $_ENV['REDIS_PREFIX'] : 'marreta:'); +/** + * Configurações do Hawk.so + */ +define('HAWK_TOKEN', isset($_ENV['HAWK_TOKEN']) ? $_ENV['HAWK_TOKEN'] : null); + /** * Configurações de Cache S3 */ diff --git a/app/inc/Logger.php b/app/inc/Logger.php new file mode 100644 index 0000000..3aa823b --- /dev/null +++ b/app/inc/Logger.php @@ -0,0 +1,73 @@ + HAWK_TOKEN, + ]); + } + } + + public static function getInstance(): Logger + { + if (self::$instance === null) { + self::$instance = new self(); + } + return self::$instance; + } + + /** + * Registra um erro com contexto + * + * @param string $message Mensagem de erro + * @param array $context Dados adicionais de contexto + * @param string $type Tipo/categoria do erro + */ + public function error(string $message, array $context = [], string $type = 'WARNING'): void + { + // Se não houver token do Hawk configurado, não gera log + if (empty(HAWK_TOKEN)) { + return; + } + + // Registra no Hawk + try { + Catcher::get()->sendException(new Exception($message), [ + 'type' => $type, + 'context' => $context + ]); + } catch (Exception $e) { + // Se o Hawk falhar, já temos o log em arquivo como backup + error_log("Falha ao enviar erro para o Hawk: " . $e->getMessage()); + } + } + + /** + * Registra um erro específico de URL + * + * @param string $url A URL que gerou o erro + * @param string $error_group Grupo/categoria do erro + * @param string $message_error Detalhes adicionais do erro + * @param string $type Tipo/categoria do erro + */ + public function log(string $url, string $error_group, string $message_error = '', string $type = 'WARNING'): void + { + $this->error($error_group, [ + 'url' => $url, + 'timestamp' => time(), + 'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown', + 'message_error' => $message_error + ], $type); + } +} \ No newline at end of file diff --git a/app/inc/URLAnalyzer.php b/app/inc/URLAnalyzer.php index 5a168eb..d08860c 100644 --- a/app/inc/URLAnalyzer.php +++ b/app/inc/URLAnalyzer.php @@ -15,6 +15,7 @@ require_once 'Rules.php'; require_once 'Cache.php'; +require_once 'Logger.php'; use Curl\Curl; use Facebook\WebDriver\Remote\DesiredCapabilities; @@ -22,6 +23,7 @@ use Facebook\WebDriver\Remote\RemoteWebDriver; use Facebook\WebDriver\Firefox\FirefoxOptions; use Facebook\WebDriver\Firefox\FirefoxProfile; use Facebook\WebDriver\Chrome\ChromeOptions; +use Inc\Logger; class URLAnalyzer { @@ -88,19 +90,6 @@ class URLAnalyzer ]; } - /** - * Registra erros no arquivo de log - * - * @param string $url URL que gerou o erro - * @param string $error Mensagem de erro - */ - private function logError($url, $error) - { - $timestamp = date('Y-m-d H:i:s'); - $logEntry = "[{$timestamp}] URL: {$url} - Error: {$error}" . PHP_EOL; - file_put_contents(__DIR__ . '/../logs/error.log', $logEntry, FILE_APPEND); - } - /** * Método principal para análise de URLs * @@ -126,8 +115,8 @@ class URLAnalyzer $host = preg_replace('/^www\./', '', $host); if (in_array($host, BLOCKED_DOMAINS)) { - $error = 'Este domínio está bloqueado para extração.'; - $this->logError($cleanUrl, $error); + $error = 'BLOCKED_DOMAINS'; + Logger::getInstance()->log($cleanUrl, $error); throw new Exception($error); } @@ -142,8 +131,9 @@ class URLAnalyzer return $processedContent; } } catch (Exception $e) { - $this->logError($cleanUrl, "Selenium fetch error: " . $e->getMessage()); - throw new Exception("Não foi possível obter o conteúdo via Selenium"); + $error = 'SELENIUM_ERROR'; + Logger::getInstance()->log($cleanUrl, 'SELENIUM_ERROR', $e->getMessage()); + throw new Exception($error); } } @@ -156,7 +146,7 @@ class URLAnalyzer return $processedContent; } } catch (Exception $e) { - $this->logError($cleanUrl, "Direct fetch error: " . $e->getMessage()); + Logger::getInstance()->log($cleanUrl, 'DIRECT_FETCH_ERROR', $e->getMessage()); } // 6. Tenta buscar do Wayback Machine como fallback @@ -168,9 +158,10 @@ class URLAnalyzer return $processedContent; } } catch (Exception $e) { - $this->logError($cleanUrl, "Wayback Machine error: " . $e->getMessage()); + Logger::getInstance()->log($cleanUrl, 'WAYBACK_FETCH_ERROR', $e->getMessage()); } + Logger::getInstance()->log($cleanUrl, 'GENERAL_FETCH_ERROR'); throw new Exception("Não foi possível obter o conteúdo da URL"); } diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index 4e11fb3..1aca2d5 100644 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -90,6 +90,11 @@ if [ -n "${SELENIUM_HOST}" ]; then echo "SELENIUM_HOST=${SELENIUM_HOST}" >> /app/.env fi +# Configurações do Hawk.so +if [ -n "${HAWK_TOKEN}" ]; then + echo "HAWK_TOKEN=${HAWK_TOKEN}" >> /app/.env +fi + log_success "Variáveis de ambiente configuradas" # === Ajuste de Permissões ===