From ea8499e49551576fd42474e2ff069c8a83b3aa4f Mon Sep 17 00:00:00 2001 From: Rodrigo Quelca Date: Fri, 20 Dec 2024 09:42:40 -0400 Subject: [PATCH 1/3] FOUR-20916: Create a Dashboard for Monitoring --- ProcessMaker/Cache/AbstractCacheFactory.php | 4 +- .../Monitoring/CacheMetricsInterface.php | 60 ------------------- .../Providers/CacheServiceProvider.php | 4 -- docs/cache-monitoring.md | 2 +- metrics/compose.yaml | 2 + metrics/prometheus/prometheus.yml | 10 +++- 6 files changed, 13 insertions(+), 69 deletions(-) diff --git a/ProcessMaker/Cache/AbstractCacheFactory.php b/ProcessMaker/Cache/AbstractCacheFactory.php index b3a8a2e18b..7ca46776ee 100644 --- a/ProcessMaker/Cache/AbstractCacheFactory.php +++ b/ProcessMaker/Cache/AbstractCacheFactory.php @@ -5,7 +5,7 @@ use Illuminate\Cache\CacheManager; use ProcessMaker\Cache\Monitoring\CacheMetricsDecorator; use ProcessMaker\Cache\Monitoring\CacheMetricsInterface; -use ProcessMaker\Cache\Monitoring\RedisMetricsManager; +use ProcessMaker\Cache\Monitoring\PrometheusMetricsManager; abstract class AbstractCacheFactory implements CacheFactoryInterface { @@ -48,7 +48,7 @@ public static function create(CacheManager $cacheManager, CacheMetricsInterface */ protected static function getInstance(): CacheInterface { - return static::create(app('cache'), app()->make(RedisMetricsManager::class)); + return static::create(app('cache'), app()->make(PrometheusMetricsManager::class)); } /** diff --git a/ProcessMaker/Cache/Monitoring/CacheMetricsInterface.php b/ProcessMaker/Cache/Monitoring/CacheMetricsInterface.php index 6632c6a7f9..421ca457cb 100644 --- a/ProcessMaker/Cache/Monitoring/CacheMetricsInterface.php +++ b/ProcessMaker/Cache/Monitoring/CacheMetricsInterface.php @@ -30,64 +30,4 @@ public function recordMiss(string $key, $microtime): void; * @param int $size Size of the cached data in bytes */ public function recordWrite(string $key, int $size): void; - - /** - * Get the hit rate for a specific cache key - * - * @param string $key Cache key to check - * @return float Hit rate as a percentage between 0 and 1 - */ - public function getHitRate(string $key): float; - - /** - * Get the miss rate for a specific cache key - * - * @param string $key Cache key to check - * @return float Miss rate as a percentage between 0 and 1 - */ - public function getMissRate(string $key): float; - - /** - * Get the average time taken for cache hits - * - * @param string $key Cache key to analyze - * @return float Average time in microseconds - */ - public function getHitAvgTime(string $key): float; - - /** - * Get the average time taken for cache misses - * - * @param string $key Cache key to analyze - * @return float Average time in microseconds - */ - public function getMissAvgTime(string $key): float; - - /** - * Get the most frequently accessed cache keys - * - * @param int $count Number of top keys to return - * @return array Array of top keys with their access counts - */ - public function getTopKeys(int $count = 5): array; - - /** - * Get memory usage statistics for a cache key - * - * @param string $key Cache key to analyze - * @return array Array containing memory usage details - */ - public function getMemoryUsage(string $key): array; - - /** - * Reset all metrics data - */ - public function resetMetrics(): void; - - /** - * Get a summary of all cache metrics - * - * @return array Array containing overall cache statistics - */ - public function getSummary(): array; } diff --git a/ProcessMaker/Providers/CacheServiceProvider.php b/ProcessMaker/Providers/CacheServiceProvider.php index 1d3cb5fdbe..fdd29dbdf3 100644 --- a/ProcessMaker/Providers/CacheServiceProvider.php +++ b/ProcessMaker/Providers/CacheServiceProvider.php @@ -4,7 +4,6 @@ use Illuminate\Support\ServiceProvider; use ProcessMaker\Cache\Monitoring\CacheMetricsInterface; -use ProcessMaker\Cache\Monitoring\RedisMetricsManager; use ProcessMaker\Cache\Screens\LegacyScreenCacheAdapter; use ProcessMaker\Cache\Screens\ScreenCacheFactory; use ProcessMaker\Cache\Screens\ScreenCacheManager; @@ -16,9 +15,6 @@ class CacheServiceProvider extends ServiceProvider { public function register(): void { - // Register the metrics manager - $this->app->bind(CacheMetricsInterface::class, RedisMetricsManager::class); - // Register screen cache with metrics $this->app->singleton(ScreenCacheManager::class, function ($app) { return ScreenCacheFactory::create( diff --git a/docs/cache-monitoring.md b/docs/cache-monitoring.md index a6ec09973d..5626038aeb 100644 --- a/docs/cache-monitoring.md +++ b/docs/cache-monitoring.md @@ -8,7 +8,7 @@ The ProcessMaker Cache Monitoring System is a comprehensive solution for trackin ### Architecture 1. **Core Components**: - `CacheMetricsInterface`: Defines the contract for metrics collection - - `RedisMetricsManager`: Implements metrics storage using Redis + - `PrometheusMetricsManager`: Implements metrics storage using Redis - `CacheMetricsDecorator`: Wraps cache implementations to collect metrics 2. **Key Features**: diff --git a/metrics/compose.yaml b/metrics/compose.yaml index fff14bfeef..2af121147b 100644 --- a/metrics/compose.yaml +++ b/metrics/compose.yaml @@ -10,6 +10,8 @@ services: volumes: - ./prometheus:/etc/prometheus - prom_data:/prometheus + extra_hosts: + - "processmaker.test:host-gateway" # This allows Docker to resolve your Herd domain grafana: image: grafana/grafana container_name: grafana diff --git a/metrics/prometheus/prometheus.yml b/metrics/prometheus/prometheus.yml index 1aae660c50..77d2dc8634 100644 --- a/metrics/prometheus/prometheus.yml +++ b/metrics/prometheus/prometheus.yml @@ -12,5 +12,11 @@ scrape_configs: scheme: http static_configs: - targets: - # Replace this with your local processmaker instance (add port if needed) - - processmaker.test + - "host.docker.internal:80" + relabel_configs: + - source_labels: [__address__] + target_label: __param_target + - source_labels: [__param_target] + target_label: instance + - target_label: __address__ + replacement: processmaker.test From 5ece4b700bcc582c4f0a6a24aee38681e88de6ba Mon Sep 17 00:00:00 2001 From: Rodrigo Quelca Date: Fri, 20 Dec 2024 09:43:27 -0400 Subject: [PATCH 2/3] add prometheusMetricsManager class --- .../Monitoring/PrometheusMetricsManager.php | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 ProcessMaker/Cache/Monitoring/PrometheusMetricsManager.php diff --git a/ProcessMaker/Cache/Monitoring/PrometheusMetricsManager.php b/ProcessMaker/Cache/Monitoring/PrometheusMetricsManager.php new file mode 100644 index 0000000000..97033a120a --- /dev/null +++ b/ProcessMaker/Cache/Monitoring/PrometheusMetricsManager.php @@ -0,0 +1,106 @@ +metrics = Metrics::getFacadeRoot(); + $this->namespace = $namespace; + } + + /** + * Record a cache hit + * + * @param string $key Cache key + * @param float $microtime Time taken in microseconds + */ + public function recordHit(string $key, $microtime): void + { + $sanitizedKey = $this->sanitizeKey($key); + + $this->metrics->counter( + 'cache_hits_total', + 'Total number of cache hits', + ['cache_key'] + )->inc(['cache_key' => $sanitizedKey]); + // record the last write timestamp + $this->metrics->gauge( + 'cache_last_write_timestamp', + 'Last write timestamp', + ['cache_key'] + )->set($microtime, ['cache_key' => $sanitizedKey]); + } + + /** + * Record a cache miss + * + * @param string $key Cache key + * @param float $microtime Time taken in microseconds + */ + public function recordMiss(string $key, $microtime): void + { + $sanitizedKey = $this->sanitizeKey($key); + + $this->metrics->counter( + 'cache_misses_total', + 'Total number of cache misses', + ['cache_key'] + )->inc(['cache_key' => $sanitizedKey]); + + // record the last write timestamp + $this->metrics->gauge( + 'cache_last_write_timestamp', + 'Last write timestamp', + ['cache_key'] + )->set($microtime, ['cache_key' => $sanitizedKey]); + } + + /** + * Record a cache write operation + * + * @param string $key Cache key + * @param int $size Size in bytes + */ + public function recordWrite(string $key, int $size): void + { + $sanitizedKey = $this->sanitizeKey($key); + + $this->metrics->gauge( + 'cache_memory_bytes', + 'Memory usage in bytes', + ['cache_key'] + )->set($size, ['cache_key' => $sanitizedKey]); + } + + /** + * Sanitize a cache key to be used as a Prometheus label + * + * @param string $key Cache key + * @return string Sanitized cache key + */ + protected function sanitizeKey(string $key): string + { + return str_replace([':', '/', ' '], '_', $key); + } +} From 8c1f14f42843aed1c4cc7843c56b69f469ba93de Mon Sep 17 00:00:00 2001 From: Rodrigo Quelca Date: Fri, 20 Dec 2024 10:17:50 -0400 Subject: [PATCH 3/3] comment the herd support --- metrics/compose.yaml | 5 +++-- metrics/prometheus/prometheus.yml | 20 ++++++++++++-------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/metrics/compose.yaml b/metrics/compose.yaml index 2af121147b..27cea568d2 100644 --- a/metrics/compose.yaml +++ b/metrics/compose.yaml @@ -10,8 +10,9 @@ services: volumes: - ./prometheus:/etc/prometheus - prom_data:/prometheus - extra_hosts: - - "processmaker.test:host-gateway" # This allows Docker to resolve your Herd domain + # This allows Docker to resolve your Herd domain + # extra_hosts: + # - "processmaker.test:host-gateway" grafana: image: grafana/grafana container_name: grafana diff --git a/metrics/prometheus/prometheus.yml b/metrics/prometheus/prometheus.yml index 77d2dc8634..786adcf9a8 100644 --- a/metrics/prometheus/prometheus.yml +++ b/metrics/prometheus/prometheus.yml @@ -12,11 +12,15 @@ scrape_configs: scheme: http static_configs: - targets: - - "host.docker.internal:80" - relabel_configs: - - source_labels: [__address__] - target_label: __param_target - - source_labels: [__param_target] - target_label: instance - - target_label: __address__ - replacement: processmaker.test + # Replace this with your local processmaker instance (add port if needed) + - processmaker.test + # This allows Docker to resolve your Herd domain + # - "host.docker.internal:80" + # This allows Docker to resolve your Herd domain + # relabel_configs: + # - source_labels: [__address__] + # target_label: __param_target + # - source_labels: [__param_target] + # target_label: instance + # - target_label: __address__ + # replacement: processmaker.test