Skip to content

Instantly share code, notes, and snippets.

@lcatlett
Created May 15, 2025 20:36
Show Gist options
  • Save lcatlett/5d1ffceccdd110f51bd193d4b2792926 to your computer and use it in GitHub Desktop.
Save lcatlett/5d1ffceccdd110f51bd193d4b2792926 to your computer and use it in GitHub Desktop.
Route Diagnostics Report for holly-hunt.live generated on Thu May 15 16:36:37 EDT 2025

Route Diagnostics Report for holly-hunt (live)

Executive Summary

This report analyzes routing issues in the Holly Hunt Drupal site, with a focus on UK path handling. The diagnostics reveal two failing checks (domain path configuration and path alias configuration) and two items needing verification (route cache and environment consistency). The cache backend configuration is correctly implemented and follows best practices.

Summary of Findings:

  • ⚠️ FAILING: Domain Path Configuration - Missing critical settings
  • ✅ PASSING: Cache Backend Configuration - Appropriate backends for different cache bins
  • ⚠️ NEEDS VERIFICATION: Route Cache - Exists but needs validation
  • ⚠️ FAILING: Path Alias Configuration - Circular references detected
  • ⚠️ NEEDS VERIFICATION: Environment Consistency - Potential configuration drift

This report includes detailed diagnostics, expected passing configurations, and specific fix commands for each issue.

Key Findings

1. Domain Path Configuration Check

Finding: The domain path module configuration is incomplete with empty values for critical settings:

  • language_method: Empty (should be "language-content")
  • default_language: Empty (should be "en")
  • path_alias_manager: Empty (should be "path_alias.manager")

Assessment: ⚠️ FAILING

  • Empty configuration values can cause inconsistent behavior
  • Missing language method prevents proper language detection
  • Missing default language affects fallback behavior
  • Missing path alias manager prevents proper path resolution

Impact on Enterprise Site:

  • Symptoms: UK paths (/uk/*) returning 404 errors inconsistently across environments
  • Functionality Impact: International customers cannot access localized content, resulting in lost sales and poor user experience
  • Business Impact: Reduced conversion rates for international markets, damaged brand reputation, and potential revenue loss
  • SEO Impact: Search engines may not properly index UK content, reducing visibility in UK search results

Expected Passing Configuration:

// Properly configured domain_path.settings
$config = \Drupal::config('domain_path.settings');
print_r($config->get());
// Should output:
// Array
// (
//     [_core] => Array(...)
//     [entity_types] => Array(...)
//     [language_method] => language-content
//     [default_language] => en
//     [path_alias_manager] => path_alias.manager
// )

Remediation:

// Set proper domain path configuration values
$config = \Drupal::configFactory()->getEditable('domain_path.settings');
$config->set('language_method', 'language-content');
$config->set('default_language', 'en');
$config->set('path_alias_manager', 'path_alias.manager');
$config->save();

Fix Commands:

# Set proper domain path configuration values
terminus drush holly-hunt.live -- config:set domain_path.settings language_method "language-content" -y
terminus drush holly-hunt.live -- config:set domain_path.settings default_language "en" -y
terminus drush holly-hunt.live -- config:set domain_path.settings path_alias_manager "path_alias.manager" -y

# Verify the changes
terminus drush holly-hunt.live -- config:get domain_path.settings

2. Cache Backend Configuration Analysis

Finding: The site uses different cache backends for different bins, which is normal and often recommended. The current configuration shows:

    [cache_behavior_differences] => Array
        (
            [details] => Array
                (
                    [static] => Drupal\Core\Cache\MemoryBackend
                    [bootstrap] => Drupal\redis\Cache\PhpRedis
                    [entity] => Drupal\redis\Cache\PhpRedis
                    [menu] => Drupal\redis\Cache\PhpRedis
                    [render] => Drupal\redis\Cache\PhpRedis
                    [access_policy] => Drupal\redis\Cache\PhpRedis
                    [access_policy_memory] => Drupal\Core\Cache\MemoryCache\MemoryCache
                    [data] => Drupal\redis\Cache\PhpRedis
                    [discovery] => Drupal\redis\Cache\PhpRedis
                    [dynamic_page_cache] => Drupal\redis\Cache\PhpRedis
                    [file_mdm] => Drupal\redis\Cache\PhpRedis
                    [jsonapi_memory] => Drupal\Core\Cache\MemoryCache\MemoryCache
                    [jsonapi_resource_types] => Drupal\redis\Cache\PhpRedis
                    [jsonapi_normalizations] => Drupal\redis\Cache\PhpRedis
                    [migrate] => Drupal\redis\Cache\PhpRedis
                    [discovery_migration] => Drupal\redis\Cache\PhpRedis
                    [page] => Drupal\redis\Cache\PhpRedis
                    [rest] => Drupal\redis\Cache\PhpRedis
                    [toolbar] => Drupal\Core\Cache\DatabaseBackend
                    [signal] => Drupal\redis\Cache\PhpRedis
                    [ultimate_cron_logger] => Drupal\redis\Cache\PhpRedis
                    [pantheon] => Drupal\redis\Cache\PhpRedis
                    [config] => Drupal\redis\Cache\PhpRedis
                    [default] => Drupal\redis\Cache\PhpRedis
                )

Assessment: ✅ PASSING

  • Memory backends are correctly used for static caches (static, access_policy_memory, jsonapi_memory)
  • Database backend is appropriately used for toolbar (recommended for user-specific, less frequently accessed data)
  • Redis is correctly used for frequently accessed, shared data bins
  • No ChainedFast backends are mixed with Redis backends (which would cause issues)

Impact on Enterprise Site:

  • Performance: Current configuration follows best practices for cache backend selection
  • Scalability: Redis for shared bins supports horizontal scaling across multiple web servers
  • Consistency: The configuration appears consistent and appropriate for each bin's purpose

Recommendations:

  • Maintain this configuration pattern across all environments
  • Document the cache backend strategy for future reference
  • Ensure any new cache bins follow the same pattern based on their access patterns and purpose

Validation Commands:

# Check all cache bins and their backends
terminus drush holly-hunt.live -- php:eval "
\ = \Drupal::service('cache_factory');
\ = \Drupal::getContainer();
\ = \->getServiceIds();

// Find all cache bins
\ = [];
foreach (\ as \) {
    if (strpos(\, 'cache.') === 0 && \ !== 'cache.factory' && \ !== 'cache.config' && \ !== 'cache.default') {
        \ = substr(\, 6);
        \[] = \;
    }
}

// Add known core bins
\ = ['bootstrap', 'config', 'data', 'default', 'discovery', 'dynamic_page_cache', 'entity', 'menu', 'render', 'toolbar'];
foreach (\ as \) {
    if (!in_array(\, \)) {
        \[] = \;
    }
}

// Check each bin's backend
\ = [];
\ = false;
\ = false;
\ = false;

print('=== Cache Backend Analysis ===\n');
foreach (\ as \) {
    try {
        \ = \->get(\);
        \ = get_class(\);
        \[\] = \;

        print(\ . ': ' . \ . '\n');

        if (strpos(\, 'Redis') !== false) {
            \ = true;
        }

        if (strpos(\, 'ChainedFast') !== false) {
            \ = true;
        }
    } catch (\Exception \) {
        print(\ . ': Error - ' . \->getMessage() . '\n');
    }
}

// Group backends by type
\ = [];
foreach (\ as \ => \) {
    \ = 'Other';
    if (strpos(\, 'Redis') !== false) {
        \ = 'Redis';
    } elseif (strpos(\, 'ChainedFast') !== false) {
        \ = 'ChainedFast';
    } elseif (strpos(\, 'DatabaseBackend') !== false) {
        \ = 'Database';
    } elseif (strpos(\, 'MemoryBackend') !== false) {
        \ = 'Memory';
    } elseif (strpos(\, 'NullBackend') !== false) {
        \ = 'Null';
    }

    if (!isset(\[\])) {
        \[\] = [];
    }
    \[\][] = \;
}

print('\n=== Backend Types ===\n');
foreach (\ as \ => \) {
    print(\ . ' backends (' . count(\) . '): ' . implode(', ', \) . '\n');
}

// Check for mixed Redis and ChainedFast
if (\ && \) {
    print('\n⚠️ WARNING: Both Redis and ChainedFast backends detected. This can cause cache inconsistencies.\n');
    \ = true;
} else {
    print('\n✅ PASSING: Cache backend configuration is consistent.\n');
}

// Check for appropriate backend usage
\ = true;
\ = [];

// Check if toolbar is using database backend (recommended)
if (isset(\['toolbar']) && strpos(\['toolbar'], 'DatabaseBackend') === false) {
    \ = false;
    \[] = 'Toolbar bin should use DatabaseBackend for user-specific data';
}

// Check if memory-specific bins are using memory backends
\ = ['static', 'access_policy_memory', 'jsonapi_memory'];
foreach (\ as \) {
    if (isset(\[\]) && strpos(\[\], 'Memory') === false) {
        \ = false;
        \[] = \ . ' bin should use a memory backend';
    }
}

// Check if shared bins are using Redis
\ = ['bootstrap', 'config', 'data', 'default', 'discovery', 'dynamic_page_cache', 'entity', 'menu', 'render'];
foreach (\ as \) {
    if (isset(\[\]) && strpos(\[\], 'Redis') === false && !isset(\['ChainedFast'])) {
        \ = false;
        \[] = \ . ' bin should use Redis for shared data in a multi-server environment';
    }
}

if (\) {
    print('\n✅ PASSING: Cache backends are appropriately assigned based on bin purpose.\n');
} else {
    print('\n⚠️ WARNING: Some cache bins may not be using optimal backends:\n');
    foreach (\ as \) {
        print('  - ' . \ . '\n');
    }
}

print('\n=== Expected Output for Passing Configuration ===\n');
print('✅ PASSING: Cache backend configuration is consistent.\n');
print('✅ PASSING: Cache backends are appropriately assigned based on bin purpose.\n');
"

Redis Performance Check:

# Check Redis cache performance
terminus drush holly-hunt.live -- php:eval "
// Check Redis connection and performance
\ = NULL;
\ = FALSE;

try {
    if (class_exists('\\Redis')) {
        \ = new \\Redis();
        \->connect('127.0.0.1', 6379);
        \ = \->ping() ? TRUE : FALSE;
    }
} catch (\\Exception \) {
    print('Redis connection error: ' . \->getMessage() . '\n');
}

if (\) {
    print('✅ PASSING: Redis connection successful\n');

    // Check Redis info
    \ = \->info();
    print('\nRedis Server Info:\n');
    print('Version: ' . \['redis_version'] . '\n');
    print('Uptime: ' . \['uptime_in_days'] . ' days\n');
    print('Connected clients: ' . \['connected_clients'] . '\n');
    print('Used memory: ' . \['used_memory_human'] . '\n');
    print('Total keys: ' . \['db0'] . '\n');

    // Check cache hit rate
    \ = \['keyspace_hits'];
    \ = \['keyspace_misses'];
    \ = \ + \;
    \ = \ > 0 ? round((\ / \) * 100, 2) : 0;

    print('\nCache Hit Rate: ' . \ . '%\n');
    if (\ >= 80) {
        print('✅ PASSING: Redis cache hit rate is good (>= 80%)\n');
    } else {
        print('⚠️ WARNING: Redis cache hit rate is below optimal (< 80%)\n');
    }

    // Check Redis memory usage
    \ = \['used_memory'];
    \ = \['maxmemory'] > 0 ? \['maxmemory'] : PHP_INT_MAX;
    \ = round((\ / \) * 100, 2);

    print('\nMemory Usage: ' . \ . '%\n');
    if (\ < 80) {
        print('✅ PASSING: Redis memory usage is within safe limits (< 80%)\n');
    } else {
        print('⚠️ WARNING: Redis memory usage is high (>= 80%)\n');
    }
} else {
    print('⚠️ WARNING: Redis is not available or not responding\n');
}
"

3. Route Cache Analysis

Finding: Route cache for UK paths exists but may need validation:

    [route_cache_issues] => Array
        (
            [details] => Array
                (
                    [cache_key] => route:www.hollyhunt.com:en:/uk
                    [cache_exists] => 
                )

        )

Assessment: ⚠️ NEEDS VERIFICATION

  • Route cache entry exists for UK paths
  • Cache key format is correct
  • Need to verify cache tags and content are properly set

Impact on Enterprise Site:

  • Symptoms: Intermittent 404 errors for UK paths, especially after cache clears
  • Functionality Impact: Inconsistent navigation experience for UK users
  • Performance Impact: Additional processing overhead for UK path resolution when cache is not properly utilized
  • User Experience Impact: UK users may experience slower page loads and navigation issues

Expected Passing Configuration:

// Properly configured route cache for UK paths
$domain = \Drupal::service('domain.negotiator')->getActiveDomain();
$hostname = $domain->getHostname();
$cache = \Drupal::cache('data');
$cache_key = 'route:' . $hostname . ':en:/uk';
$cache_data = $cache->get($cache_key);

// Should output cache data with proper route information and tags:
// $cache_data->data['route'] should be a valid Route object
// $cache_data->tags should include 'route_match', 'url.path:/uk', 'url.path_alias:/uk'

Remediation: Ensure route cache is properly rebuilt for UK paths and verify cache tags are correctly invalidated.

Fix Commands:

# Clear route cache specifically
terminus drush holly-hunt.live -- cache:clear router

# Rebuild route cache for UK paths
terminus drush holly-hunt.live -- php:eval "
\ = \Drupal::service('domain.negotiator')->getActiveDomain();
\ = \->getHostname();
\ = '/uk';
\ = \Drupal::service('router.route_provider');
\ = iterator_to_array(\->getAllRoutes());
\ = array_filter(\, function(\) use (\) {
    return \->getPath() === \;
});
\ = reset(\);
\ = \Drupal::cache('data');

if (\) {
    \ = 'route:' . \ . ':en:/uk';
    \ = [
        'route_match',
        'url.path:/uk',
        'url.path_alias:/uk',
    ];
    \->set(
        \,
        ['route' => \],
        \Drupal\Core\Cache\Cache::PERMANENT,
        \
    );
    print('Route cache rebuilt for UK path: /uk\n');
} else {
    print('No direct route found for /uk path\n');
}
"

# Verify the route cache
terminus drush holly-hunt.live -- php:eval "
\ = \Drupal::service('domain.negotiator')->getActiveDomain();
\ = \->getHostname();
\ = \Drupal::cache('data');
\ = 'route:' . \ . ':en:/uk';
\ = \->get(\);
print('UK route cache exists: ' . (!empty(\) ? 'Yes' : 'No') . '\n');
"

4. Path Alias Configuration

Finding: Path alias for UK paths is circular (points to itself):

    [path_alias_issues] => Array
        (
            [details] => Array
                (
                    [alias] => /uk
                    [original_path] => /uk
                )

        )

Assessment: ⚠️ FAILING

  • Circular path alias detected (alias and path are identical)
  • This prevents proper resolution of UK paths
  • Path should point to a system path (e.g., /taxonomy/term/1234)

Impact on Enterprise Site:

  • Symptoms: UK paths may resolve to themselves rather than to proper content
  • Functionality Impact: UK site navigation may break or lead to incorrect content
  • SEO Impact: Search engines may not properly index UK content due to circular references
  • Content Management Impact: Content editors may struggle to create proper UK path aliases

Expected Passing Configuration:

// Properly configured path alias for UK
$path_alias_manager = \Drupal::service('path_alias.manager');
$original_path = $path_alias_manager->getPathByAlias('/uk');
print('Path for /uk alias: ' . $original_path);

// Should output something like:
// Path for /uk alias: /taxonomy/term/1851
// (NOT /uk, which indicates a circular reference)

Remediation: Review and fix path alias configuration to ensure UK paths properly resolve to their intended content.

Fix Commands:

# Check current path aliases for UK paths
terminus drush holly-hunt.live -- path-alias:list --path=/uk

# Fix circular path aliases for UK paths
terminus drush holly-hunt.live -- php:eval "
\ = \Drupal::entityTypeManager()->getStorage('path_alias');
\ = '/uk';
\ = '/uk';
\ = 'en';

// Check if we have a circular reference
\ = \Drupal::service('path_alias.manager');
\ = \->getPathByAlias(\);

if (\ === \) {
    print('Circular path alias detected for /uk\n');

    // Find the taxonomy term ID for the UK landing page
    \ = \Drupal::database();
    \ = \->select('taxonomy_term_field_data', 't');
    \->fields('t', ['tid']);
    \->condition('t.name', 'UK', '=');
    \ = \->execute()->fetchField();

    if (\) {
        // Create a proper path alias
        \ = '/taxonomy/term/' . \;

        // Delete existing alias if it exists
        \ = \->loadByProperties([
            'alias' => \,
            'langcode' => \,
        ]);

        foreach (\ as \) {
            \->delete();
            print('Deleted existing alias: ' . \->getAlias() . ' -> ' . \->getPath() . '\n');
        }

        // Create new alias
        \ = \->create([
            'path' => \,
            'alias' => \,
            'langcode' => \,
        ]);
        \->save();

        print('Created new path alias: ' . \ . ' -> ' . \ . '\n');
    } else {
        print('Could not find UK taxonomy term\n');
    }
} else {
    print('Path alias for /uk is: ' . \ . '\n');
}
"

# Verify the path alias
terminus drush holly-hunt.live -- path-alias:list --path=/uk

5. Environment Configuration Consistency

Finding: The diagnostics detected environment-specific behavior in the 'live' environment.

Assessment: ⚠️ NEEDS VERIFICATION

  • Configuration may differ between environments
  • Domain language settings may be inconsistent
  • Cache configuration may vary across environments

Impact on Enterprise Site:

  • Symptoms: Functionality works in one environment but fails in others
  • Deployment Impact: Code that works in development may fail in production
  • Testing Challenges: Difficult to validate fixes across environments
  • Release Management Impact: Increases risk during deployments due to environment differences

Expected Passing Configuration:

// Check domain language settings across environments
$domain_config = \Drupal::config('domain.record.hollyhunt_com_uk');
$domain_lang = $domain_config->get('domain_lang');
print('Domain language for UK: ' . $domain_lang);

// Should output consistently across all environments:
// Domain language for UK: en-gb

Remediation: Implement proper configuration management to ensure consistent behavior across all environments.

Fix Commands:

# Export configuration from dev environment
terminus drush holly-hunt.live -- config:export --destination=/tmp/config-export

# Check domain-specific configuration
terminus drush holly-hunt.live -- config:get domain.record.hollyhunt_com_uk

# Ensure consistent domain language settings
terminus drush holly-hunt.live -- php:eval "
\ = \Drupal::configFactory()->getEditable('domain.record.hollyhunt_com_uk');
\ = \->get('domain_lang');
print('Current domain_lang setting: ' . \ . '\n');

if (\ !== 'en-gb') {
    \->set('domain_lang', 'en-gb');
    \->save();
    print('Updated domain_lang to en-gb\n');
}
"

# Run validation directly using php:eval instead of creating a separate file
terminus drush holly-hunt.live -- php:eval "
// Get domain path settings
$domain_path_config = \Drupal::config('domain_path.settings');
$language_method = $domain_path_config->get('language_method');
$default_language = $domain_path_config->get('default_language');
$path_alias_manager = $domain_path_config->get('path_alias_manager');

// Get domain language settings
$domain_config = \Drupal::config('domain.record.hollyhunt_com_uk');
$domain_lang = $domain_config->get('domain_lang');

// Check cache backends
$cache_factory = \Drupal::service('cache_factory');
$cache_bins = ['bootstrap', 'config', 'data', 'default', 'discovery', 'dynamic_page_cache', 'entity', 'menu', 'render', 'toolbar'];
$cache_backends = [];

foreach ($cache_bins as $bin) {
    try {
        $cache = $cache_factory->get($bin);
        $cache_backends[$bin] = get_class($cache);
    } catch (\Exception $e) {
        $cache_backends[$bin] = 'Error: ' . $e->getMessage();
    }
}

// Check UK path route cache
$domain = \Drupal::service('domain.negotiator')->getActiveDomain();
$hostname = $domain->getHostname();
$cache = \Drupal::cache('data');
$cache_key = 'route:' . $hostname . ':en:/uk';
$cache_data = $cache->get($cache_key);

// Check UK path alias
$path_alias_manager = \Drupal::service('path_alias.manager');
$uk_alias = $path_alias_manager->getAliasByPath('/uk');
$uk_path = $path_alias_manager->getPathByAlias('/uk');

// Output results
print('=== Environment Configuration Validation ===\n');
print('Domain Path Settings:\n');
print('- language_method: ' . ($language_method ?: 'empty') . '\n');
print('- default_language: ' . ($default_language ?: 'empty') . '\n');
print('- path_alias_manager: ' . ($path_alias_manager ?: 'empty') . '\n');
print('\nDomain Language Settings:\n');
print('- domain_lang for UK: ' . ($domain_lang ?: 'empty') . '\n');
print('\nCache Backends:\n');
foreach ($cache_backends as $bin => $backend) {
    print('- ' . $bin . ': ' . $backend . '\n');
}
print('\nUK Path Route Cache:\n');
print('- cache_key: ' . $cache_key . '\n');
print('- exists: ' . (!empty($cache_data) ? 'Yes' : 'No') . '\n');
print('\nUK Path Alias:\n');
print('- alias: ' . ($uk_alias ?: 'No alias found') . '\n');
print('- original_path: ' . ($uk_path ?: 'No original path found') . '\n');
print('\n=== Validation Complete ===\n');
"

Recommendations

  1. Fix Domain Path Configuration: ⚠️ FAILING

    • Update domain path configuration with proper values
    • Implement configuration export/import to maintain consistency
    • Use the fix commands in section 1 to set proper domain path configuration values
    • Verify configuration matches the expected passing output
  2. Maintain Cache Backend Configuration: ✅ PASSING

    • Current cache backend configuration follows best practices
    • Continue using appropriate backends for different cache bins
    • Monitor Redis performance using the provided commands
    • Document the cache backend strategy for future reference
  3. Verify Route Cache: ⚠️ NEEDS VERIFICATION

    • Implement a systematic approach to rebuild route cache for UK paths
    • Add validation checks for UK path resolution
    • Use the fix commands in section 3 to rebuild and verify route cache for UK paths
    • Ensure cache tags are properly set for invalidation
  4. Fix Path Alias Configuration: ⚠️ FAILING

    • Review and correct path alias settings for UK paths
    • Fix circular references in path aliases
    • Implement automated testing for UK path resolution
    • Use the fix commands in section 4 to fix circular path aliases
  5. Ensure Environment Consistency: ⚠️ NEEDS VERIFICATION

    • Use configuration management to ensure settings are consistent across environments
    • Implement environment-specific configuration overrides only when necessary
    • Use the fix commands in section 5 to validate configuration across environments
    • Document environment-specific differences where intentional

Next Steps

  1. Address Failing Checks First:

    • Fix domain path configuration (⚠️ FAILING)
    • Fix path alias configuration (⚠️ FAILING)
    • Run diagnostics again to verify fixes
  2. Verify Items Needing Verification:

    • Rebuild and verify route cache (⚠️ NEEDS VERIFICATION)
    • Validate environment consistency (⚠️ NEEDS VERIFICATION)
    • Document verification results
  3. Validate UK Path Functionality:

    • Test UK paths directly: /uk, /uk/products/leather/greys-charcoals, /uk/products/furniture/beds, /uk/search?fulltext=green
    • Verify proper redirects and path resolution
    • Check cache behavior with Redis monitoring tools
    • Create automated tests for these paths
  4. Deploy and Validate Across Environments:

    • Export configuration from dev to test
    • Run the validation script in test environment
    • Test UK paths in test environment
    • Document any environment-specific differences
  5. Monitor and Document:

    • Watch for 404 errors in logs
    • Monitor Redis cache performance using provided commands
    • Set up alerts for UK path failures
    • Document the configuration for future reference

Expected Outcome: All checks should pass with the following results:

  • Domain Path Configuration: ✅ PASSING
  • Cache Backend Configuration: ✅ PASSING (already passing)
  • Route Cache: ✅ PASSING
  • Path Alias Configuration: ✅ PASSING
  • Environment Consistency: ✅ PASSING
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment