Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FOUR-20916: Create a Dashboard for Monitoring #7850

Open
wants to merge 3 commits into
base: epic/FOUR-20326_and_FOUR-20257
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions ProcessMaker/Cache/AbstractCacheFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -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));
}

/**
Expand Down
60 changes: 0 additions & 60 deletions ProcessMaker/Cache/Monitoring/CacheMetricsInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
106 changes: 106 additions & 0 deletions ProcessMaker/Cache/Monitoring/PrometheusMetricsManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<?php

namespace ProcessMaker\Cache\Monitoring;

use Illuminate\Support\Facades\Redis;
use ProcessMaker\Facades\Metrics;
use Prometheus\CollectorRegistry;

class PrometheusMetricsManager implements CacheMetricsInterface
{
/**
* @var Metrics
*/
protected $metrics;

/**
* @var string
*/
protected $namespace;

/**
* PrometheusMetricsManager constructor.
*
* @param string $namespace
*/
public function __construct(string $namespace = 'cache')
{
$this->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);
}
}
4 changes: 0 additions & 4 deletions ProcessMaker/Providers/CacheServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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(
Expand Down
2 changes: 1 addition & 1 deletion docs/cache-monitoring.md
Original file line number Diff line number Diff line change
Expand Up @@ -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**:
Expand Down
3 changes: 3 additions & 0 deletions metrics/compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ services:
volumes:
- ./prometheus:/etc/prometheus
- prom_data:/prometheus
# This allows Docker to resolve your Herd domain
# extra_hosts:
# - "processmaker.test:host-gateway"
grafana:
image: grafana/grafana
container_name: grafana
Expand Down
10 changes: 10 additions & 0 deletions metrics/prometheus/prometheus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,13 @@ scrape_configs:
- targets:
# 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