Understanding & Extending Cache Eviction

TABLE OF CONTENTS

Part 1: Introduction

Cache eviction is one of the hardest problems to solve in software.

Znode provides a robust and extensible cache eviction framework that can be customized to evict data as needed. This holds true regardless of whether Znode is configured as a simple single-server environment, or, a complex load-balanced environment with many independent nodes.

Cache eviction in Znode is easy. There are 2 main steps to evict data; writing a cache eviction event that describes what has changed, and then evicting the data that has become stale as a result of what has changed. 

Simple Example

The first step is to enqueue a cache eviction event that describes what data has changed.

ClearCacheHelper.EnqueueEviction(new MyCustomDataUpdateEvent()

{

    Comment = "From updating my custom data.",

    CustomDataId = 7

});

The second step is to evict stale data, based on what has changed.

...

protected override bool IsDictionaryItemStale(MyCustomDataUpdateEvent cacheEvent, string key)

{

    string routePrefix = $"my_custom_data_{cacheEvent.CustomDataId}_";

    bool isStale = key.StartsWith(routePrefix);

    return isStale;

}

...

The above example creates a cache eviction event describing the fact that some custom data has changed, specifically an item with “CustomDataId” of 7. The code in the “IsDictionaryItemStale” method says that a cached item should be considered stale for cached items with keys that start with “my_custom_data_7_”.

Sequence Diagram

Continuing the example from above, the following sequence diagram shows the sequence of actions that are carried out by Znode.

  1. The cache eviction event of type “MyCustomDataUpdateEvent” is written to Elasticsearch, as a result of calling the “ClearCacheHelper.EnqueueEviction()” method.
  2. The cache eviction event is read by the API from Elasticsearch. Custom eviction logic is invoked by the framework, marking the proper items stale and ultimately evicting the stale data.
  3. The cache eviction event is read by the WebStore from Elasticsearch. Custom eviction logic is invoked by the framework, marking the proper items stale and ultimately evicting the stale data.

This basic example illustrates the main cache eviction concepts in Znode. There are more details that are good to know while solving more complex use cases. These details are described in the next sections of this documentation.

Part 2: Cache Eviction Events

When a piece of data is updated, resulting in any cached data becoming stale, a “cache eviction event” must be “broadcast” (written to Elasticsearch). This is the basis for allowing the framework to subsequently trigger custom eviction logic that evicts stale cached data.

If a piece of data is not cached anywhere, then there is no need to evict anything and no need to broadcast a cache eviction event.

If a cache eviction event does need to be broadcast, the first step is to write a C# class that defines the cache event.

public class MyCustomDataUpdateEvent : BaseCacheEvent

{

    public int CustomDataId { get; set; }

}


This example class, MyCustomDataUpdateEvent, defines a custom cache eviction event.

The class has a CustomDataId integer property, showing that the ID of the changed data item can be captured, to allow the custom eviction logic to specifically evict cached data related to this item.

The class can have any properties on it that are needed to describe what has changed so that eviction logic can be as efficient as possible, by evicting only necessary stale data. These properties can be integers, strings, booleans, arrays, other objects, and anything that is serializable.

All cache eviction events are defined in the “Znode.Libraries.Caching.Events” project, specifically within the “Events” subfolder of that project.

Part 3: Cache Evictors

A cache “evictor” is a class that defines the logic that evicts necessary cached data, which has become stale as a result of a corresponding cache eviction event.

On a regular basis (every 7 seconds by default) the Znode API and WebStore poll Elasticsearch for new cache eviction events. For each new cache eviction event, the framework will instantiate and invoke 0 or 1 corresponding evictor class to carry out data eviction, depending on whether one is defined.

The API and WebStore each have their own set of evictors, defined in the “Znode.Api.Caching” and “Znode.WebStore.Caching” projects, specifically within the “Evictors” subfolder.

To continue with the custom data example, suppose the API and WebStore may each cache data in memory relating to that custom data item. For example, the API may store an instance of an object in memory describing the raw details of that custom data item, while the WebStore may store a derived HTML representation of that custom data item in a format that is ready to be rendered on the WebStore.

To support the eviction of cached data in both the API and the WebStore, an evictor class can be written in both the API and WebStore.

Here is a more detailed example of the custom evictor that may be written to evict data in the API.

internal class MyCustomDataUpdateEvent_Evictor : BaseApiEvictor<MyCustomDataUpdateEvent>

{

    private string keyPrefix;


    protected override void Setup(MyCustomDataUpdateEvent cacheEvent)

    {

        keyPrefix = $"my_custom_data_{cacheEvent.CustomDataId}_";

    }


    protected override void EvictNonDictionaryCacheData(MyCustomDataUpdateEvent cacheEvent)

    {


    }


    protected override List<string> EvictSpecificDictionaryCacheKeys(MyCustomDataUpdateEvent cacheEvent)

    {

        return new List<string>();

    }


    protected override bool IsDictionaryItemStale(MyCustomDataUpdateEvent cacheEvent, string key)

    {

        bool isStale = key.StartsWith(keyPrefix);

        return isStale;

    }


    protected override void Teardown(MyCustomDataUpdateEvent cacheEvent)

    {


    }

}

 

This example class, MyCustomDataUpdateEvent_Evictor, inherits from a base class and overrides 5 methods. These 5 methods allow custom eviction logic to be written as efficiently as possible. These 5 methods provide the following features.

  • void Setup(MyCustomDataUpdateEvent cacheEvent)
    • This method allows custom setup/initialization logic to be executed before the actual eviction takes place.

    • This will execute exactly once per cache eviction event that is processed.

    • This is the best place to do any calculations that are needed before evicting data, such as determining the prefix of the keys that will be stale.

  • void EvictNonDictionaryCacheData(MyCustomDataUpdateEvent cacheEvent)
    • This method allows custom eviction logic to be executed against any custom cache storage (something outside of the default dictionary cache).
    • This will execute exactly once per cache eviction event that is processed.
  • List<string> EvictSpecificDictionaryCacheKeys(MyCustomDataUpdateEvent cacheEvent)

    • This method allows custom eviction logic to declare that specific data stored under specific keys should be evicted.

    • This will execute exactly once per cache eviction event that is processed.

    • When the keys of all stale items are known, this allows the framework to perform the most efficient eviction of those items.

    • For example, if a custom centralized caching framework were to be used, such as redis, it would be inefficient to iterate over all keys in redis. This method would allow only the specific stale keys to be evicted.

  • bool IsDictionaryItemStale(MyCustomDataUpdateEvent cacheEvent, string key)

    • This method allows custom eviction logic to be executed against each item stored in the dictionary cache.

    • This will execute exactly once per item stored in the dictionary cache.

    • If true is returned, the framework evicts the item. If false is returned, the item is not evicted.

  • void Teardown(MyCustomDataUpdateEvent cacheEvent)

    • This method allows custom teardown/disposal logic to be executed after all eviction logic has been executed.

    • This will execute exactly once per cache eviction event that is processed.

    • This will likely not be needed for 99% of use cases but is provided for future use and for uniformity with the setup method.

As previously explained, an evictor can be defined in both the API and the WebStore to have specific control over the eviction of data in each application. Note that this is optional and that an evictor can be omitted. If an evictor is omitted, the API/WebStore will still read the cache event from Elasticsearch during a poll operation, but no evictor will be executed.

Further building on custom data example, the following evictor may be defined in the WebStore.

internal class MyCustomDataUpdateEvent_Evictor : BaseWebStoreEvictor<MyCustomDataUpdateEvent>

{

    protected override void Setup(MyCustomDataUpdateEvent cacheEvent)

    {

    

    }


    protected override void EvictNonDictionaryCacheData(MyCustomDataUpdateEvent cacheEvent)

    {

        ClearHtmlCache();

    }


    protected override List<string> EvictSpecificDictionaryCacheKeys(MyCustomDataUpdateEvent cacheEvent)

    {

        return new List<string>();

    }


    protected override bool IsDictionaryItemStale(MyCustomDataUpdateEvent cacheEvent, string key)

    {

        return false;

    }


    protected override void Teardown(MyCustomDataUpdateEvent cacheEvent)

    {


    }

}

 

This example class, MyCustomDataUpdateEvent_Evictor, is very similar to the first example evictor class that was defined in the API and even has the same exact name. However, this is defined in a different project (the “Znode.WebStore.Caching” project as opposed to the “Znode.Api.Caching” project) and overrides a different base class (the BaseWebStoreEvictor)

This example evictor (defined for the WebStore) differs from the previous example evictor (the one defined for the API) as follows.

  • No “Setup” logic is performed.
  • The “EvictNonDictionaryCacheData” method calls the “ClearHtmlCache” method. 
    • This method is defined on the base class (the BaseWebStoreEvictor) and clears all cached HTML views.

    • Suppose that the custom data has been rendered into HTML that is cached by the WebStore; calling the “ClearHtmlCache” method helps evict that data.

    • Note: An improvement to this example would be to write more specific eviction logic. For example, the cache eviction event has a CustomDataId describing the ID of the custom data entity that changed, so eviction logic could be written to only evict rendered HTML views that contain the related data.

  • The IsDictionaryItemStale method always returns false. This means that no data in the dictionary cache will be marked stale, and no such data will be evicted.

Part 4: Best Practices

The cache eviction is very flexible, allowing problems to be solved in multiple ways. Follow these best practices to ensure the best performance and maintainability.

Only evict what’s necessary. Don’t evict data unnecessarily because this results in degraded performance. For example, if a CMS page is changed, don’t evict all CMS pages from memory, only evict the page that changed.

Create as few cache eviction events as possible. Creating hundreds of unnecessary cache eviction events at once will start to become a heavy operation for the framework to process. For example, if a  catalog of products is published, create 1 cache eviction event describing the catalog that was published, as opposed to creating 1 cache eviction event for each product within the catalog.

Keep cache eviction events as small as possible. For example, if a product is published, capture the product’s ID in the event, not an object describing all of the product’s attributes.

Create cache eviction events that describe changes, not evictions. This allows for the framework to be extended more naturally. For example, consider a warehouse address that may be cached. Furthermore, consider a My Account page that might be cached and display the warehouse address. It’s better to create a cache eviction event called “WarehouseAddressChanged” than to create a cache eviction event called “MyAccountPageStale”. The “WarehouseAddressChanged” naming convention is better because it describes the data that changed, allowing all future consumers that cache the warehouse address to add their eviction logic in response to the same underlying event.

Part 5: Code Organization

Cache eviction logic is organized across 5 projects in the code, as follows.

  • Znode.API.Caching
    • This project contains all of the API’s eviction logic, that is, the logic that evicts the proper stale API data in response to cache events.
    • This project is included within the SDK so that
      • existing API eviction behavior can be customized if necessary, and
      • so that new eviction logic can be added to evict any necessary stale custom cached API data in response to any custom cache events.
  • Znode.Cloudflare.Caching
    • This project contains all of the eviction logic related to evicting data from Cloudflare, that is, the logic that evicts the proper stale Cloudflare data in response to cache events.
    • This project is included within the SDK so that
      • existing Cloudflare eviction behavior can be customized if necessary, and
      • so that new eviction logic can be added to evict any necessary stale custom cached Cloudflare data in response to any custom cache events.
  • Znode.Libraries.Caching
    • This project contains the core framework code related to cache events and evictions.
    • This project is referenced by the SDK as a NuGet package.
  • Znode.Libraries.Caching.Events
    • This project contains all of the cache events defined in Znode.
    • This project is included within the SDK so that
      • existing cache events can be customized if necessary, and
      • so that new cache events can be added to describe any necessary events related to custom data that need to trigger evictions in the API or the WebStore.
  • Znode.WebStore.Caching
    • This project contains all of the WebStore’s, eviction logic, that is, the logic that evicts the proper stale WebStore data in response to cache events.
    • This project is included within the SDK so that
      •  existing WebStore eviction behavior can be customized if necessary, and
      • so that new eviction logic can be added to evict any necessary stale custom cached WebStore data in response to any custom cache events.

Part 6: Framework Components

There are a few key components that comprise the cache eviction framework.

Cache

There are 3 types of caches shown in the diagram.

  1. API Cache - Cache of data held in memory within each API process. This includes the .Net HttpRuntime.Cache dictionary cache.
  2. WebStore Cache - Cache of data held in-memory within each WebStore process. This includes the .Net HttpRuntime.Cache dictionary cache, and the MVC HTML cache.
  3. Cloudflare Cache - Cache of WebStore endpoint responses (typically HTML) stored on Cloudflare distributed network of computers across the world.

Cache Eviction Event

Cache eviction events are specific subclasses of a common parent class that describe specifically what has changed as the result of a data update or publish operation.

For example, when a product is published, it may make sense to publish a “ProductPublishEvent” with a “ProductId” describing what has been published, allowing an evictor to evict just the minimum amount of cached data related to that product.

Wrapped Cache Eviction Event

Wrapped cache eviction events contain a single serialized cache eviction event, and are written to and read from a single Elasticsearch index.

Writer

One writer class is defined in the code, an Elasticsearch writer.

The writer provides a method to write new cache eviction events to Elasticsearch, making it easy for the business logic to trigger fine grained eviction based on specific changes to data.

The writer also “wraps/serializes” the cache eviction event of any given type (subclass) and indexes the document (wrapped cache event) into a single Elasticsearch index that stores all types of cache eviction events. This provides the benefit of having a single Elasticsearch index that indexes all types (subclasses) of cache eviction events.

Reader

One reader class is defined in the code, an Elasticsearch reader.

The reader provides a method to read new cache eviction events that were created in a desired date-time range, making it easy for the pollers to read cache eviction events that have not yet been processed and are also ready to be processed (remember, cache eviction events must be “old enough” if the poller delays processing of events).

The reader “unwraps/deserializes” the documents (wrapped cache events) returned by the Elasticsearch query.

Poller

Pollers continuously poll for cache eviction events (every 7 seconds by default) by using a reader to read new cache eviction events created in a desired date and time range.

There are 3 types of pollers in Znode.

  1. API Poller
    1. Polls for events that have been created since that last API poll operation. 

    2. Invokes an evictor to evict stale API data based on each new cache eviction event as necessary.

    3. Executes every 7 seconds in the WebStore IIS process.

  2. WebStore Poller
    1. Polls for events that are at least 15 seconds old, and have been created since that last WebStore poll operation.

    2. Invokes an evictor to evict stale WebStore data based on each new cache eviction event as necessary.

    3. Executes every 7 seconds in the API IIS process.

    4. Executes every 7 seconds in the API IIS process.

  3. Cloudflare Poller
    1. Polls for events that are at least 30 seconds old, and have been created since that last Cloudflare poll operation.

    2. Invokes an evictor to evict stale WebStore data based on each new cache eviction event as necessary.

    3. Executes every 7 seconds in the API IIS process.

All 3 types of pollers share the following characteristics.

  1. If IIS is configured with multiple IIS worker's processes, an individual poller is running in each process (because each process has its full copy of the code running).
  2. The poller executes at most every 7 seconds. Note that pollers are triggered by the IIS application receiving traffic, and if the IIS application is not receiving traffic, the poller stops polling until the next request is received.

Evictor

Evictors process cache eviction events, evicting necessary stale data.

Evictors are all implemented as subclasses of a shared parent class. Each evictor processes exactly one type of cache eviction event (one class type).

Evictors have a lifecycle per cache eviction event. In other words, if the poller receives 2 new cache eviction events of type X, the cache evictor that can handle events of type X is instantiated twice; once to process the first cache eviction event, and again to process the second cache eviction event.

Part 7: Load Balancing and Multiple IIS Worker Processes

Multiple WebStore and API processes will exist if the IIS application is configured with multiple IIS worker processes. Also, if traffic is load balanced across multiple servers this results in more processes executing across the servers. Each WebStore and API process will have its in-memory cache and its own OS process executing all of the steps described.

If for example, there are 2 IIS worker processes and 2 load-balanced servers for both the WebStore and API, then there will be 4 WebStore processes and 4 API processes with all components duplicated and executing independently as shown in this diagram.

 

Part 8: Framework Execution Sequence

This section provides a more in-depth look at how the cache eviction framework polls and executes eviction logic continuously (every 7 seconds by default).

Step 0: Poller Continuously Polling

Even while no cache eviction events are being produced, the cache eviction framework is still polling for cache eviction events continuously in the background. When it polls and there are no cache eviction events available, it gets 0 results and performs no evictions.

3 types of pollers continuously poll for events, the API poller, the WebStore poller, and the Cloudflare poller. Each poller will poll every 7 seconds by default.

The diagram below shows an example sequence of poll operations that may occur, all returning 0 results. The diagram shows the API poll happening first, the WebStore poll happening second, and the Cloudflare poll happening third, but there is no coordination of the relative timing between these pollers; the only guarantee is that the pollers will poll at some point within every 7-second window of time (unless the application is not receiving requests and is sitting idle, in which case polling is suspended). 

  1. The API poller polls for events.
    1. The API poller asks the reader to read cache eviction events created in the window of time between now and the time of the previous poll operation. This window of time spans from 0 to 7 seconds ago in this example.

    2. The reader queries Elasticsearch for matching wrapped cache eviction events.

    3. The reader receives 0 hits from the elastic search.

    4. The poller receives 0 cache eviction events from the reader and does nothing as a result.

  2. The WebStore poller polls for events.
    1. The WebStore poller asks the reader to read cache eviction events created in a window of time that has a duration equal to the amount of time since the previous poll operation was performed, shifted back in time by an amount equal to the configured delay (15 seconds by default). This window of time spans from 15 to 22 seconds ago in this example.

    2. The reader queries Elasticsearch for matching wrapped cache eviction events.

    3. The reader receives 0 hits from Elasticsearch.

    4. The poller receives 0 cache eviction events from the reader and does nothing as a result.

  3. The Cloudflare poller polls for events.
    1. The Cloudflare poller asks the reader to read cache eviction events created in a window of time that has a duration equal to the amount of time since the previous poll operation was performed, shifted back in time by an amount equal to the configured delay (30 seconds by default). This window of time spans from 30 to 37 seconds ago in this example.
    2. The reader queries Elasticsearch for matching wrapped cache eviction events.
    3. The reader receives 0 hits from Elasticsearch.The poller receives 0 cache eviction events from the reader and does nothing as a result.

Step 1: Write Cache Eviction Event(s)

The first step to initiate a cache eviction sequence is to write at least one cache eviction event.

The following diagram shows two different types of cache eviction events being written.

  1. Business logic in the API updates data and calls the writer to write a cache eviction event, Event A.

  2. The writer serializes cache eviction event A, stores it in a wrapped cache eviction event, and writes the wrapped cache eviction event as a document to Elasticsearch.

  3. Immediately, more business logic in the API updates data and calls the writer to write another cache eviction event, Event B.

  4. The writer serializes cache eviction event B, stores it in a wrapped cache eviction event, and writes the wrapped cache eviction event as a document to Elasticsearch.

Step 2: Poll, Read, and Evict API Cache

During the timeframe of 0 to 7 seconds after the cache eviction events are written to Elasticsearch, each of the pollers will perform a poll operation, in an unknown order. However, the API poller will be the only poller to read the cache eviction events at this time because the WebStore and Cloudflare poller won’t process events until they are at least 15 and 30 seconds old, respectively.

  1. The API poller asks the reader to read cache eviction events created in the window of time between now and the time of the previous poll operation. This window of time spans from 0 to 7 seconds ago in this example.
  2. The reader queries Elasticsearch for matching wrapped cache eviction events.
  3. The reader receives 2 hits from Elasticsearch.
  4. The poller receives 2 cache eviction events from the reader.
  5. The poller finds the type of evictor class that can process the type of Event X. It instantiates a new instance of the evictor and asks it to process Event X.
  6. The newly instantiated evictor evicts data that it determines has become stale as a result of the information captured by Event X.
  7. The poller finds the type of evictor class that can process the type of Event Y. It instantiates a new instance of the evictor and asks it to process Event Y.
  8. The newly instantiated evictor evicts data that it determines has become stale as a result of the information captured by Event Y.

Step 3: Poll, Read, and Evict WebStore Cache

During the timeframe of 15 to 22 seconds after the cache eviction events are written to Elasticsearch, each of the pollers will perform a poll operation, in an unknown order. However, the WebStore poller will be the only poller to read the cache eviction events at this time because the API poller will have already processed the cache eviction events and the Cloudflare poller won’t process events until they are at least 30 seconds old.

  1. The WebStore poller asks the reader to read cache eviction events created in a window of time that has a duration equal to the amount of time since the previous poll operation was performed, shifted back in time by an amount equal to the configured delay (15 seconds by default). This window of time spans from 15 to 22 seconds ago in this example.
  2. The reader queries Elasticsearch for matching wrapped cache eviction events.
  3. The reader receives 2 hits from Elasticsearch.
  4. The poller receives 2 cache eviction events from the reader.
  5. The poller finds the type of evictor class that can process the type of Event X. It instantiates a new instance of the evictor and asks it to process Event X.
  6. The newly instantiated evictor evicts data that it determines has become stale as a result of the information captured by Event X.
  7. The poller finds the type of evictor class that can process the type of Event Y. It instantiates a new instance of the evictor and asks it to process Event Y.
  8. The newly instantiated evictor evicts data that it determines has become stale as a result of the information captured by Event Y.

Step 4: Poll, Read and Evict Cloudflare Cache

During the timeframe of 30 to 37 seconds after the cache eviction events are written to Elasticsearch, each of the pollers will perform a poll operation, in an unknown order. However, the Cloudflare poller will be the only poller to read the cache eviction events at this time because the API and WebStore poller will have already processed the cache eviction events.

  1. The Cloudflare poller asks the reader to read cache eviction events created in a window of time that has a duration equal to the amount of time since the previous poll operation was performed, shifted back in time by an amount equal to the configured delay (30 seconds by default). This window of time spans from 30 to 37 seconds ago in this example.
  2. The reader queries Elasticsearch for matching wrapped cache eviction events.
  3. The reader receives 2 hits from Elasticsearch.
  4. The poller receives 2 cache eviction events from the reader.
  5. The poller finds the type of evictor class that can process the type of Event X. It instantiates a new instance of the evictor and asks it to process Event X.
  6. The newly instantiated evictor evicts data that it determines has become stale as a result of the information captured by Event X.
  7. The poller finds the type of evictor class that can process the type of Event Y. It instantiates a new instance of the evictor and asks it to process Event Y.
  8. The newly instantiated evictor evicts data that it determines has become stale as a result of the information captured by Event Y.

Remember that each of the poll operations described in this example are independently executing across each instance of the application process. This example shows that the WebStore and the API are each configured with 2 IIS worker processes and 2 load balanced nodes. Therefore, the poll operations would be happening 4 times more than what is shown in the example.

Part 9: Configuration Reference

The API and WebStore Web.configs have a number of settings to configure cache eviction. These settings are all set to sensible defaults and don’t need to be modified, but they are available in case there is any desire to fine tune caching.

  • CacheIndexBaseName
    • Exists in: Both the API’s Web.config and WebStore’s Web.config

    • Default value: “cache-dev-”

    • Base name (prefix) used for all Elasticsearch indexes related to cache events.

    • Znode’s caching framework will create an index in Elasticsearch to store cache eviction events. The index is named with a prefix based on this setting, eg: “cache-dev-events”

    • If sharing a single Elasticsearch instance between multiple Znode environments, this setting should be changed to a unique value per Znode environment to avoid collisions, eg: “cache-dev-events”, cache-qa-events”

  • CacheMetricRecordingEnabled
    • Exists in: Both the API’s Web.config and WebStore’s Web.config

    • Default value: false

    • Enable to record metrics related to caching, such as detailed cache eviction information.

    • Keep this "false" in production because setting to "true" will decrease performance.

    • A later section of this documentation describes how these cache metrics can be visualized in Kibana.

  • CachePollFrequencyInMilliseconds
    • Exists in: Both the API’s Web.config and WebStore’s Web.config

    • Default value: 7000

    • Frequency of polling Elasticsearch for new cache events.

    • By default, the API and WebStore both poll Elasticsearch for new cache events every 7 seconds.

  • CacheEventProcessingDelayInMilliseconds
    • Exists in: Both the API’s Web.config and WebStore’s Web.config

    • Default value: 0 for API, 15000 for WebStore

    • Time to delay the processing of cache events. Used to allow downstream caches to wait for upstream caches to be cleared first.

    • By default, the API has no delay for processing eviction events, but the WebStore has a delay of 15 seconds before processing eviction events. This allows the API to clear data before the WebStore clears data; this way, if the WebStore re-fetches data from the API, it will not re-fetch stale data.

  • CloudflareCacheEventProcessingDelayInMilliseconds
    • Exists in: Only the API’s Web.config

    • Default value: 30000

    • When Cloudflare is used as an edge caching service with Znode, it also needs to have data evicted from it.

    • The API is responsible for triggering the eviction of stale Cloudflare data.

    • By default, the API delays the processing of Cloudflare-related eviction events by 30 seconds; this way, if Cloudflare re-fetches data from the WebStore, it will not re-fetch stale data.

Part 10: Metrics with Kibana

It’s possible to view cache eviction events and metrics in a Kibana dashboard. To do so, follow these steps:

  1. Confirm that API and WebStore caching are enabled. This can be configured in Admin UI > Dev Center > Global Settings > Cache Management.
  2. Enable metrics. Edit the API and WebStore Web.configs. Set the CacheMetricRecordingEnabled setting to true.
  3. Ensure proper cache eviction data exists in Elasticsearch.
    1. Open http://localhost:9200/_cat/indices?v in a browser tab (change from 9200 to match the port Elasticsearch is hosted on if necessary).
    2. Confirm that two cache eviction-related indexes exist and have at least 1 doc each. The indexes will be named starting with the string defined in the CacheIndexBaseName web.config setting (which must be identical across all 3 web.configs), and ending with “events” and “metrics”. For example, default Znode settings will create the following 2 indices:
      1. cache-dev-events
      2. cache-dev-metrics
    3. If Znode has never been run with the CacheMetricRecordingEnabled setting enabled, then the “cache-dev-metrics” index will have 0 docs. If this is the case, follow the next steps to create some docs.
    4. Run Znode and trigger at least one cache eviction. For example, go to the Admin UI > Dev Center > Global Settings > Cache Management and refresh the API cache.
    5. Wait a few seconds, while periodically navigating through the WebStore UI, to wait for the cache eviction to occur.
    6. Confirm both indexes now exist, by refreshing http://localhost:9200/_cat/indices?v in a browser tab.
  4. Install Kibana.
    1. https://www.elastic.co/downloads/past-releases/kibana-7-6-0
  5. Run Kibana. By default, Kibana will host a browser-based UI on port 5601 and connect to Elasticsearch on port 9200. Changing either of these settings is possible through configuration
  6. Create the following index patterns in Kibana, under Management > Index Patterns. For each pattern, select the created DateTime field to be used as the Time Filter.
    1. cache-dev-events*

    2. cache-dev-metrics*

  7. Import the cache metrics dashboard into Kibana.
    1. Download the saved dashboard in this JSON file.
    2. In Kibana, go to Management > Saved Objects.
    3. Click Import.
    4. Select the JSON file.
    5. Choose Yes, to overwrite all existing objects if prompted.
    6. Select both of the index patterns to be mapped if they are not automatically mapped.
  8. Go to Dashboard and click “cache dashboard” to view the dashboard.
    1. There will be no data if no cache events have been created yet.
    2. Do something to trigger a cache event. For example, publish a Banner Slider.
    3. After some time, and triggering requests in the UI’s, the API will be the first application to clear items from its cache.
    4. Next, the WebStore will clear its cache.

Did you find it helpful? Yes No

Send feedback
Sorry we couldn't be helpful. Help us improve this article with your feedback.