npm package diff

Package: @forge/storage

Versions: 1.5.15-experimental-10722bc - 1.6.0-next.0

File: package/out/__test__/global-storage.test.js

Index: package/out/__test__/global-storage.test.js
===================================================================
--- package/out/__test__/global-storage.test.js
+++ package/out/__test__/global-storage.test.js
@@ -2,17 +2,48 @@
 Object.defineProperty(exports, "__esModule", { value: true });
 const errors_1 = require("../errors");
 const global_storage_1 = require("../global-storage");
 const gql_queries_1 = require("../gql-queries");
+const mocks_1 = require("@atlassian/metrics-interface/dist/mocks");
 const contextAri = 'app-ari';
-const getStorage = (apiClientMock) => new global_storage_1.GlobalStorage(() => contextAri, apiClientMock);
+const getStorage = (apiClientMock, metrics) => new global_storage_1.GlobalStorage(() => contextAri, apiClientMock, () => metrics);
 const getApiClientMock = (response, statusCode = 200) => {
     return jest.fn().mockReturnValue({
         ok: statusCode === 200,
         status: statusCode,
         text: jest.fn().mockResolvedValue(JSON.stringify(response))
     });
 };
+const getMetricMock = () => {
+    const mockMetrics = new mocks_1.MockMetrics();
+    const mockCounter = new mocks_1.MockCounter('');
+    const mockTiming = new mocks_1.MockTiming('');
+    const mockStopTiming = jest.fn();
+    const mockMeasure = {
+        stop: mockStopTiming
+    };
+    mockMetrics.counter.mockReturnValue(mockCounter);
+    mockMetrics.timing.mockReturnValue(mockTiming);
+    mockTiming.measure.mockReturnValue(mockMeasure);
+    return {
+        mockMetrics,
+        mockCounter,
+        mockStopTiming
+    };
+};
+const checkMetricsFired = ({ mockMetrics, mockCounter, mockStopTiming }, { encrypted, ...restTags }, success) => {
+    expect(mockMetrics.counter).toHaveBeenCalledWith('forge.runtime.storage.operation', {
+        ...restTags,
+        encrypted: String(encrypted),
+        success: String(success)
+    });
+    expect(mockCounter.incr).toHaveBeenCalled();
+    expect(mockMetrics.timing).toHaveBeenCalledWith('forge.runtime.storage.operation.latency', {
+        ...restTags,
+        encrypted: String(encrypted)
+    });
+    expect(mockStopTiming).toHaveBeenCalledWith({ success: String(success) });
+};
 const getApiClientMockInvalidJson = (response, statusCode = 200) => {
     return jest.fn().mockReturnValue({
         ok: statusCode === 200,
         status: statusCode,
@@ -42,691 +73,686 @@
         global.api = {
             __getAppAri: jest.fn().mockReturnValue(contextAri)
         };
     });
-    describe('Untyped entities', () => {
-        describe('get', () => {
-            it('should call the storage API, passing the provided key and returning the stored value', async () => {
-                const apiClientMock = getApiClientMock({
-                    data: {
-                        appStoredEntity: {
-                            value: 'testValue'
-                        }
+    describe('get', () => {
+        it('should call the storage API, passing the provided key and returning the stored value', async () => {
+            const apiClientMock = getApiClientMock({
+                data: {
+                    appStoredEntity: {
+                        value: 'testValue'
                     }
-                });
-                const globalStorage = getStorage(apiClientMock);
-                const returnedValue = await globalStorage.get('testKey');
-                verifyApiClientCalledWith(apiClientMock, {
-                    contextAri,
-                    key: 'testKey',
-                    encrypted: false
-                });
-                expect(returnedValue).toEqual('testValue');
+                }
             });
-            it('should call the storage API, passing the provided key and returning undefined if the key doesnt exist', async () => {
-                const apiClientMock = getApiClientMock({
-                    data: {
-                        appStoredEntity: {
-                            value: null
-                        }
-                    }
-                });
-                const globalStorage = getStorage(apiClientMock);
-                const returnedValue = await globalStorage.get('testKey');
-                verifyApiClientCalledWith(apiClientMock, {
-                    contextAri,
-                    key: 'testKey',
-                    encrypted: false
-                });
-                expect(returnedValue).toEqual(undefined);
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            const returnedValue = await globalStorage.get('testKey');
+            verifyApiClientCalledWith(apiClientMock, {
+                contextAri,
+                key: 'testKey',
+                encrypted: false
             });
-            it('should call the storage API, passing the provided key and returning the stored falsey value 0', async () => {
-                const apiClientMock = getApiClientMock({
-                    data: {
-                        appStoredEntity: {
-                            value: 0
-                        }
+            expect(returnedValue).toEqual('testValue');
+            checkMetricsFired(metricMocks, { store: 'untyped', operation: 'get', encrypted: false }, true);
+        });
+        it('should call the storage API, passing the provided key and returning undefined if the key doesnt exist', async () => {
+            const apiClientMock = getApiClientMock({
+                data: {
+                    appStoredEntity: {
+                        value: null
                     }
-                });
-                const globalStorage = getStorage(apiClientMock);
-                const returnedValue = await globalStorage.get('testKey');
-                verifyApiClientCalledWith(apiClientMock, {
-                    contextAri,
-                    key: 'testKey',
-                    encrypted: false
-                });
-                expect(returnedValue).toEqual(0);
+                }
             });
-            it('should call the storage API, passing the provided key and returning the stored empty string', async () => {
-                const apiClientMock = getApiClientMock({
-                    data: {
-                        appStoredEntity: {
-                            value: ''
-                        }
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            const returnedValue = await globalStorage.get('testKey');
+            verifyApiClientCalledWith(apiClientMock, {
+                contextAri,
+                key: 'testKey',
+                encrypted: false
+            });
+            expect(returnedValue).toEqual(undefined);
+            checkMetricsFired(metricMocks, { store: 'untyped', operation: 'get', encrypted: false }, true);
+        });
+        it('should call the storage API, passing the provided key and returning the stored falsey value 0', async () => {
+            const apiClientMock = getApiClientMock({
+                data: {
+                    appStoredEntity: {
+                        value: 0
                     }
-                });
-                const globalStorage = getStorage(apiClientMock);
-                const returnedValue = await globalStorage.get('testKey');
-                verifyApiClientCalledWith(apiClientMock, {
-                    contextAri,
-                    key: 'testKey',
-                    encrypted: false
-                });
-                expect(returnedValue).toEqual('');
+                }
             });
-            it('should throw an error with the returned status for non-200 status codes', async () => {
-                const apiClientMock = getApiClientMock(undefined, 400);
-                const globalStorage = getStorage(apiClientMock);
-                const response = globalStorage.get('testKey');
-                expect(apiClientMock).toHaveBeenCalled();
-                await expect(response).rejects.toThrow(errors_1.APIError.forStatus(400));
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            const returnedValue = await globalStorage.get('testKey');
+            verifyApiClientCalledWith(apiClientMock, {
+                contextAri,
+                key: 'testKey',
+                encrypted: false
             });
-            it('should throw an error with the returned error message for failed responses', async () => {
-                const apiClientMock = getApiClientMock({
-                    errors: [INVALID_CURSOR_ERROR]
-                }, 200);
-                const globalStorage = getStorage(apiClientMock);
-                const response = globalStorage.get('testKey');
-                expect(apiClientMock).toHaveBeenCalled();
-                await expect(response).rejects.toThrow(errors_1.APIError.forErrorCode('CURSOR_INVALID', 'error message'));
+            expect(returnedValue).toEqual(0);
+            checkMetricsFired(metricMocks, { store: 'untyped', operation: 'get', encrypted: false }, true);
+        });
+        it('should call the storage API, passing the provided key and returning the stored empty string', async () => {
+            const apiClientMock = getApiClientMock({
+                data: {
+                    appStoredEntity: {
+                        value: ''
+                    }
+                }
             });
-            it('should throw an error if the response is not a valid JSON', async () => {
-                const apiClientMock = getApiClientMockInvalidJson('test', 200);
-                const globalStorage = getStorage(apiClientMock);
-                const response = globalStorage.get('testKey');
-                expect(apiClientMock).toHaveBeenCalled();
-                await expect(response).rejects.toThrow(errors_1.APIError.forUnexpected('Response text was not a valid JSON: test'));
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            const returnedValue = await globalStorage.get('testKey');
+            verifyApiClientCalledWith(apiClientMock, {
+                contextAri,
+                key: 'testKey',
+                encrypted: false
             });
+            expect(returnedValue).toEqual('');
+            checkMetricsFired(metricMocks, { store: 'untyped', operation: 'get', encrypted: false }, true);
         });
-        describe('set', () => {
-            it('should call the storage API, passing the provided key and value', async () => {
-                const apiClientMock = getApiClientMock({
-                    data: {
-                        appStorage: {
-                            setAppStoredEntity: {
-                                success: true
-                            }
-                        }
+        it('should throw an error with the returned status for non-200 status codes', async () => {
+            const apiClientMock = getApiClientMock(undefined, 400);
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            const response = globalStorage.get('testKey');
+            expect(apiClientMock).toHaveBeenCalled();
+            await expect(response).rejects.toThrow(errors_1.APIError.forStatus(400));
+            checkMetricsFired(metricMocks, { store: 'untyped', operation: 'get', encrypted: false }, false);
+        });
+        it('should throw an error with the returned error message for failed responses', async () => {
+            const apiClientMock = getApiClientMock({
+                errors: [INVALID_CURSOR_ERROR]
+            }, 200);
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            const response = globalStorage.get('testKey');
+            expect(apiClientMock).toHaveBeenCalled();
+            await expect(response).rejects.toThrow(errors_1.APIError.forErrorCode('CURSOR_INVALID', 'error message'));
+            checkMetricsFired(metricMocks, { store: 'untyped', operation: 'get', encrypted: false }, false);
+        });
+        it('should throw an error if the response is not a valid JSON', async () => {
+            const apiClientMock = getApiClientMockInvalidJson('test', 200);
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            const response = globalStorage.get('testKey');
+            expect(apiClientMock).toHaveBeenCalled();
+            await expect(response).rejects.toThrow(errors_1.APIError.forUnexpected('Response text was not a valid JSON: test'));
+            checkMetricsFired(metricMocks, { store: 'untyped', operation: 'get', encrypted: false }, false);
+        });
+    });
+    describe('get secret', () => {
+        it('should call the storage API, passing the provided key and returning the stored value', async () => {
+            const apiClientMock = getApiClientMock({
+                data: {
+                    appStoredEntity: {
+                        value: 'testValue'
                     }
-                });
-                const globalStorage = getStorage(apiClientMock);
-                await globalStorage.set('testKey', 'testValue');
-                verifyApiClientCalledWith(apiClientMock, {
-                    input: {
-                        contextAri,
-                        key: 'testKey',
-                        value: 'testValue',
-                        encrypted: false
-                    }
-                });
+                }
             });
-            it('should throw an error if the storage API returns successful = false', async () => {
-                const apiClientMock = getApiClientMock({
-                    data: {
-                        appStorage: {
-                            setAppStoredEntity: {
-                                success: false,
-                                errors: [INVALID_CURSOR_ERROR]
-                            }
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            const returnedValue = await globalStorage.getSecret('testKey');
+            verifyApiClientCalledWith(apiClientMock, {
+                contextAri,
+                key: 'testKey',
+                encrypted: true
+            });
+            expect(returnedValue).toEqual('testValue');
+            checkMetricsFired(metricMocks, { store: 'untyped', operation: 'get', encrypted: true }, true);
+        });
+    });
+    describe('set', () => {
+        it('should call the storage API, passing the provided key and value', async () => {
+            const apiClientMock = getApiClientMock({
+                data: {
+                    appStorage: {
+                        setAppStoredEntity: {
+                            success: true
                         }
                     }
-                });
-                const globalStorage = getStorage(apiClientMock);
-                const response = globalStorage.set('testKey', 'testValue');
-                expect(apiClientMock).toHaveBeenCalled();
-                await expect(response).rejects.toThrow(errors_1.APIError.forErrorCode('INVALID_CURSOR', 'error message'));
+                }
             });
-            it('should throw an error if the storage API returns a non 200 status code', async () => {
-                const apiClientMock = getApiClientMockInvalidJson('', 400);
-                const globalStorage = getStorage(apiClientMock);
-                const response = globalStorage.set('testKey', 'testValue');
-                expect(apiClientMock).toHaveBeenCalled();
-                await expect(response).rejects.toThrow(errors_1.APIError.forStatus(400));
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            await globalStorage.set('testKey', 'testValue');
+            verifyApiClientCalledWith(apiClientMock, {
+                input: {
+                    contextAri,
+                    key: 'testKey',
+                    value: 'testValue',
+                    encrypted: false
+                }
             });
-            it('should throw a 500 error if success=false but no errors were returned', async () => {
-                const apiClientMock = getApiClientMock({
-                    data: {
-                        appStorage: {
-                            setAppStoredEntity: {
-                                success: false
-                            }
+            checkMetricsFired(metricMocks, { store: 'untyped', operation: 'set', encrypted: false }, true);
+        });
+        it('should throw an error if the storage API returns successful = false', async () => {
+            const apiClientMock = getApiClientMock({
+                data: {
+                    appStorage: {
+                        setAppStoredEntity: {
+                            success: false,
+                            errors: [INVALID_CURSOR_ERROR]
                         }
                     }
-                });
-                const globalStorage = getStorage(apiClientMock);
-                await expect(globalStorage.set('testKey', 'testValue')).rejects.toThrow(errors_1.APIError.forStatus(500));
-                verifyApiClientCalledWith(apiClientMock, {
-                    input: {
-                        contextAri,
-                        key: 'testKey',
-                        value: 'testValue',
-                        encrypted: false
-                    }
-                });
+                }
             });
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            const response = globalStorage.set('testKey', 'testValue');
+            expect(apiClientMock).toHaveBeenCalled();
+            await expect(response).rejects.toThrow(errors_1.APIError.forErrorCode('INVALID_CURSOR', 'error message'));
+            checkMetricsFired(metricMocks, { store: 'untyped', operation: 'set', encrypted: false }, false);
         });
-        describe('delete', () => {
-            it('should call the storage API, passing the provided key', async () => {
-                const apiClientMock = getApiClientMock({
-                    data: {
-                        appStorage: {
-                            deleteAppStoredEntity: {
-                                success: true
-                            }
+        it('should throw an error if the storage API returns a non 200 status code', async () => {
+            const apiClientMock = getApiClientMockInvalidJson('', 400);
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            const response = globalStorage.set('testKey', 'testValue');
+            expect(apiClientMock).toHaveBeenCalled();
+            await expect(response).rejects.toThrow(errors_1.APIError.forStatus(400));
+            checkMetricsFired(metricMocks, { store: 'untyped', operation: 'set', encrypted: false }, false);
+        });
+        it('should throw a 500 error if success=false but no errors were returned', async () => {
+            const apiClientMock = getApiClientMock({
+                data: {
+                    appStorage: {
+                        setAppStoredEntity: {
+                            success: false
                         }
                     }
-                });
-                const globalStorage = getStorage(apiClientMock);
-                await globalStorage.delete('testKey');
-                verifyApiClientCalledWith(apiClientMock, {
-                    input: {
-                        contextAri,
-                        key: 'testKey',
-                        encrypted: false
-                    }
-                });
+                }
             });
-            it('should throw an error if the storage API returns successful = false', async () => {
-                const apiClientMock = getApiClientMock({
-                    data: {
-                        appStorage: {
-                            deleteAppStoredEntity: {
-                                success: false,
-                                errors: [INVALID_CURSOR_ERROR]
-                            }
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            await expect(globalStorage.set('testKey', 'testValue')).rejects.toThrow(errors_1.APIError.forStatus(500));
+            verifyApiClientCalledWith(apiClientMock, {
+                input: {
+                    contextAri,
+                    key: 'testKey',
+                    value: 'testValue',
+                    encrypted: false
+                }
+            });
+            checkMetricsFired(metricMocks, { store: 'untyped', operation: 'set', encrypted: false }, false);
+        });
+    });
+    describe('set secret', () => {
+        it('should call the storage API, passing the provided key and value', async () => {
+            const apiClientMock = getApiClientMock({
+                data: {
+                    appStorage: {
+                        setAppStoredEntity: {
+                            success: true
                         }
                     }
-                });
-                const globalStorage = getStorage(apiClientMock);
-                const response = globalStorage.delete('testKey');
-                expect(apiClientMock).toHaveBeenCalled();
-                await expect(response).rejects.toThrow(errors_1.APIError.forErrorCode('CURSOR_INVALID', 'error message'));
+                }
             });
-            it('should throw an error if the storage API returns a non 200 status code and has no body', async () => {
-                const apiClientMock = getApiClientMockInvalidJson('', 400);
-                const globalStorage = getStorage(apiClientMock);
-                const response = globalStorage.delete('testKey');
-                expect(apiClientMock).toHaveBeenCalled();
-                await expect(response).rejects.toThrow(errors_1.APIError.forStatus(400));
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            await globalStorage.setSecret('testKey', 'testValue');
+            verifyApiClientCalledWith(apiClientMock, {
+                input: {
+                    contextAri,
+                    key: 'testKey',
+                    value: 'testValue',
+                    encrypted: true
+                }
             });
+            checkMetricsFired(metricMocks, { store: 'untyped', operation: 'set', encrypted: true }, true);
         });
-        describe('bulkSet', () => {
-            it('should call the storage API for bulkSet and return savedKeys', async () => {
-                const apiClientMock = getApiClientMock({
-                    data: {
-                        appStorage: {
-                            setAppStoredEntities: {
-                                success: true,
-                                savedKeys: ['testKey'],
-                                failedKeys: [
-                                    {
-                                        key: 'testKey2',
-                                        code: 'KEY_TOO_LARGE',
-                                        message: 'The provided key exceeds maximum allowed length'
-                                    }
-                                ]
-                            }
+    });
+    describe('delete', () => {
+        it('should call the storage API, passing the provided key', async () => {
+            const apiClientMock = getApiClientMock({
+                data: {
+                    appStorage: {
+                        deleteAppStoredEntity: {
+                            success: true
                         }
                     }
-                });
-                const globalStorage = getStorage(apiClientMock);
-                const response = await globalStorage.bulkSet([
-                    {
-                        key: 'testKey',
-                        value: 'testValue'
-                    },
-                    {
-                        key: 'testKey2',
-                        value: 'testValue2'
-                    }
-                ]);
-                verifyApiClientCalledWith(apiClientMock, {
-                    input: {
-                        contextAri,
-                        entities: [
-                            {
-                                key: 'testKey',
-                                value: 'testValue'
-                            },
-                            {
-                                key: 'testKey2',
-                                value: 'testValue2'
-                            }
-                        ],
-                        encrypted: false
-                    }
-                });
-                expect(response).toHaveProperty('savedKeys', ['testKey']);
-                expect(response).toHaveProperty('failedKeys', [
-                    { key: 'testKey2', code: 'KEY_TOO_LARGE', message: 'The provided key exceeds maximum allowed length' }
-                ]);
+                }
             });
-            it('should throw an error if the storage API returns successful = false', async () => {
-                const apiClientMock = getApiClientMock({
-                    data: {
-                        appStorage: {
-                            setAppStoredEntities: {
-                                success: false,
-                                errors: [INVALID_CURSOR_ERROR]
-                            }
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            await globalStorage.delete('testKey');
+            verifyApiClientCalledWith(apiClientMock, {
+                input: {
+                    contextAri,
+                    key: 'testKey',
+                    encrypted: false
+                }
+            });
+            checkMetricsFired(metricMocks, { store: 'untyped', operation: 'delete', encrypted: false }, true);
+        });
+        it('should throw an error if the storage API returns successful = false', async () => {
+            const apiClientMock = getApiClientMock({
+                data: {
+                    appStorage: {
+                        deleteAppStoredEntity: {
+                            success: false,
+                            errors: [INVALID_CURSOR_ERROR]
                         }
                     }
-                });
-                const globalStorage = getStorage(apiClientMock);
-                const response = globalStorage.bulkSet([
-                    {
-                        key: 'testKey',
-                        value: 'testValue'
-                    }
-                ]);
-                expect(apiClientMock).toHaveBeenCalled();
-                await expect(response).rejects.toThrow(errors_1.APIError.forErrorCode('INVALID_CURSOR', 'error message'));
+                }
             });
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            const response = globalStorage.delete('testKey');
+            expect(apiClientMock).toHaveBeenCalled();
+            await expect(response).rejects.toThrow(errors_1.APIError.forErrorCode('CURSOR_INVALID', 'error message'));
+            checkMetricsFired(metricMocks, { store: 'untyped', operation: 'delete', encrypted: false }, false);
         });
+        it('should throw an error if the storage API returns a non 200 status code and has no body', async () => {
+            const apiClientMock = getApiClientMockInvalidJson('', 400);
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            const response = globalStorage.delete('testKey');
+            expect(apiClientMock).toHaveBeenCalled();
+            await expect(response).rejects.toThrow(errors_1.APIError.forStatus(400));
+            checkMetricsFired(metricMocks, { store: 'untyped', operation: 'delete', encrypted: false }, false);
+        });
     });
-    describe('Secret storage', () => {
-        describe('get secret', () => {
-            it('should call the storage API, passing the provided key and returning the stored value', async () => {
-                const apiClientMock = getApiClientMock({
-                    data: {
-                        appStoredEntity: {
-                            value: 'testValue'
+    describe('delete secret', () => {
+        it('should call the storage API, passing the provided key', async () => {
+            const apiClientMock = getApiClientMock({
+                data: {
+                    appStorage: {
+                        deleteAppStoredEntity: {
+                            success: true
                         }
                     }
-                });
-                const globalStorage = getStorage(apiClientMock);
-                const returnedValue = await globalStorage.getSecret('testKey');
-                verifyApiClientCalledWith(apiClientMock, {
+                }
+            });
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            await globalStorage.deleteSecret('testKey');
+            verifyApiClientCalledWith(apiClientMock, {
+                input: {
                     contextAri,
                     key: 'testKey',
                     encrypted: true
-                });
-                expect(returnedValue).toEqual('testValue');
+                }
             });
+            checkMetricsFired(metricMocks, { store: 'untyped', operation: 'delete', encrypted: true }, true);
         });
-        describe('set secret', () => {
-            it('should call the storage API, passing the provided key and value', async () => {
-                const apiClientMock = getApiClientMock({
-                    data: {
-                        appStorage: {
-                            setAppStoredEntity: {
-                                success: true
-                            }
-                        }
+    });
+    describe('getEntity', () => {
+        it('should call the storage API, passing the provided entity name and entity key and returning the stored value', async () => {
+            const apiClientMock = getApiClientMock({
+                data: {
+                    appStoredCustomEntity: {
+                        value: 'testValue'
                     }
-                });
-                const globalStorage = getStorage(apiClientMock);
-                await globalStorage.setSecret('testKey', 'testValue');
-                verifyApiClientCalledWith(apiClientMock, {
-                    input: {
-                        contextAri,
-                        key: 'testKey',
-                        value: 'testValue',
-                        encrypted: true
+                }
+            });
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            const returnedValue = await globalStorage.getEntity('testEntityName', 'testEntityKey');
+            verifyApiClientCalledWith(apiClientMock, {
+                contextAri,
+                entityName: 'testEntityName',
+                key: 'testEntityKey'
+            });
+            expect(returnedValue).toEqual('testValue');
+            checkMetricsFired(metricMocks, { store: 'typed', operation: 'get', encrypted: false }, true);
+        });
+        it('should call the storage API, passing the provided entity key and returning undefined if the key doesnt exist', async () => {
+            const apiClientMock = getApiClientMock({
+                data: {
+                    appStoredCustomEntity: {
+                        value: null
                     }
-                });
+                }
             });
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            const returnedValue = await globalStorage.getEntity('testEntityName', 'testEntityKey');
+            verifyApiClientCalledWith(apiClientMock, {
+                contextAri,
+                entityName: 'testEntityName',
+                key: 'testEntityKey'
+            });
+            expect(returnedValue).toEqual(undefined);
+            checkMetricsFired(metricMocks, { store: 'typed', operation: 'get', encrypted: false }, true);
         });
-        describe('delete secret', () => {
-            it('should call the storage API, passing the provided key', async () => {
-                const apiClientMock = getApiClientMock({
-                    data: {
-                        appStorage: {
-                            deleteAppStoredEntity: {
-                                success: true
-                            }
-                        }
+        it('should call the storage API, passing the provided key and returning the stored falsey value 0', async () => {
+            const apiClientMock = getApiClientMock({
+                data: {
+                    appStoredCustomEntity: {
+                        value: 0
                     }
-                });
-                const globalStorage = getStorage(apiClientMock);
-                await globalStorage.deleteSecret('testKey');
-                verifyApiClientCalledWith(apiClientMock, {
-                    input: {
-                        contextAri,
-                        key: 'testKey',
-                        encrypted: true
+                }
+            });
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            const returnedValue = await globalStorage.getEntity('testEntityName', 'testEntityKey');
+            verifyApiClientCalledWith(apiClientMock, {
+                contextAri,
+                entityName: 'testEntityName',
+                key: 'testEntityKey'
+            });
+            expect(returnedValue).toEqual(0);
+            checkMetricsFired(metricMocks, { store: 'typed', operation: 'get', encrypted: false }, true);
+        });
+        it('should call the storage API, passing the provided key and returning the stored empty string', async () => {
+            const apiClientMock = getApiClientMock({
+                data: {
+                    appStoredCustomEntity: {
+                        value: ''
                     }
-                });
+                }
             });
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            const returnedValue = await globalStorage.getEntity('testEntityName', 'testEntityKey');
+            verifyApiClientCalledWith(apiClientMock, {
+                contextAri,
+                entityName: 'testEntityName',
+                key: 'testEntityKey'
+            });
+            expect(returnedValue).toEqual('');
+            checkMetricsFired(metricMocks, { store: 'typed', operation: 'get', encrypted: false }, true);
         });
+        it('should throw an error with the returned status for non-200 status codes', async () => {
+            const apiClientMock = getApiClientMock(undefined, 400);
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            const response = globalStorage.getEntity('testEntityName', 'testEntityKey');
+            expect(apiClientMock).toHaveBeenCalled();
+            await expect(response).rejects.toThrow(errors_1.APIError.forStatus(400));
+            checkMetricsFired(metricMocks, { store: 'typed', operation: 'get', encrypted: false }, false);
+        });
+        it('should throw an error with the returned error message for failed responses', async () => {
+            const apiClientMock = getApiClientMock({
+                errors: [INVALID_CURSOR_ERROR]
+            }, 200);
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            const response = globalStorage.getEntity('testEntityName', 'testEntityKey');
+            expect(apiClientMock).toHaveBeenCalled();
+            await expect(response).rejects.toThrow(errors_1.APIError.forErrorCode('CURSOR_INVALID', 'error message'));
+            checkMetricsFired(metricMocks, { store: 'typed', operation: 'get', encrypted: false }, false);
+        });
+        it('should throw an error if the response is not a valid JSON', async () => {
+            const apiClientMock = getApiClientMockInvalidJson('test', 200);
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            const response = globalStorage.getEntity('testEntityName', 'testEntityKey');
+            expect(apiClientMock).toHaveBeenCalled();
+            await expect(response).rejects.toThrow(errors_1.APIError.forUnexpected('Response text was not a valid JSON: test'));
+            checkMetricsFired(metricMocks, { store: 'typed', operation: 'get', encrypted: false }, false);
+        });
     });
-    describe('Custom entities', () => {
-        describe('getEntity', () => {
-            it('should call the storage API, passing the provided entity name and entity key and returning the stored value', async () => {
-                const apiClientMock = getApiClientMock({
-                    data: {
-                        appStoredCustomEntity: {
-                            value: 'testValue'
+    describe('setEntity', () => {
+        it('should call the storage API, passing the provided entity name, entity key and value', async () => {
+            const apiClientMock = getApiClientMock({
+                data: {
+                    appStorageCustomEntity: {
+                        setAppStoredCustomEntity: {
+                            success: true
                         }
                     }
-                });
-                const globalStorage = getStorage(apiClientMock);
-                const returnedValue = await globalStorage.getEntity('testEntityName', 'testEntityKey');
-                verifyApiClientCalledWith(apiClientMock, {
+                }
+            });
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            await globalStorage.setEntity('testEntityName', 'testEntityKey', 'testValue');
+            verifyApiClientCalledWith(apiClientMock, {
+                input: {
                     contextAri,
                     entityName: 'testEntityName',
-                    key: 'testEntityKey'
-                });
-                expect(returnedValue).toEqual('testValue');
+                    key: 'testEntityKey',
+                    value: 'testValue'
+                }
             });
-            it('should call the storage API, passing the provided entity key and returning undefined if the key doesnt exist', async () => {
-                const apiClientMock = getApiClientMock({
-                    data: {
-                        appStoredCustomEntity: {
-                            value: null
+            checkMetricsFired(metricMocks, { store: 'typed', operation: 'set', encrypted: false }, true);
+        });
+        it('should throw an error if the storage API returns successful = false', async () => {
+            const apiClientMock = getApiClientMock({
+                data: {
+                    appStorageCustomEntity: {
+                        setAppStoredCustomEntity: {
+                            success: false,
+                            errors: [INVALID_CURSOR_ERROR]
                         }
                     }
-                });
-                const globalStorage = getStorage(apiClientMock);
-                const returnedValue = await globalStorage.getEntity('testEntityName', 'testEntityKey');
-                verifyApiClientCalledWith(apiClientMock, {
-                    contextAri,
-                    entityName: 'testEntityName',
-                    key: 'testEntityKey'
-                });
-                expect(returnedValue).toEqual(undefined);
+                }
             });
-            it('should call the storage API, passing the provided key and returning the stored falsey value 0', async () => {
-                const apiClientMock = getApiClientMock({
-                    data: {
-                        appStoredCustomEntity: {
-                            value: 0
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            const response = globalStorage.setEntity('testEntityName', 'testEntityKey', 'testValue');
+            expect(apiClientMock).toHaveBeenCalled();
+            await expect(response).rejects.toThrow(errors_1.APIError.forErrorCode('INVALID_CURSOR', 'error message'));
+            checkMetricsFired(metricMocks, { store: 'typed', operation: 'set', encrypted: false }, false);
+        });
+        it('should throw an error if the storage API returns a non 200 status code', async () => {
+            const apiClientMock = getApiClientMockInvalidJson('', 400);
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            const response = globalStorage.setEntity('testEntityName', 'testEntityKey', 'testValue');
+            expect(apiClientMock).toHaveBeenCalled();
+            await expect(response).rejects.toThrow(errors_1.APIError.forStatus(400));
+            checkMetricsFired(metricMocks, { store: 'typed', operation: 'set', encrypted: false }, false);
+        });
+        it('should throw a 500 error if success=false but no errors were returned', async () => {
+            const apiClientMock = getApiClientMock({
+                data: {
+                    appStorageCustomEntity: {
+                        setAppStoredCustomEntity: {
+                            success: false
                         }
                     }
-                });
-                const globalStorage = getStorage(apiClientMock);
-                const returnedValue = await globalStorage.getEntity('testEntityName', 'testEntityKey');
-                verifyApiClientCalledWith(apiClientMock, {
+                }
+            });
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            await expect(globalStorage.setEntity('testEntityName', 'testEntityKey', 'testValue')).rejects.toThrow(errors_1.APIError.forStatus(500));
+            verifyApiClientCalledWith(apiClientMock, {
+                input: {
                     contextAri,
                     entityName: 'testEntityName',
-                    key: 'testEntityKey'
-                });
-                expect(returnedValue).toEqual(0);
+                    key: 'testEntityKey',
+                    value: 'testValue'
+                }
             });
-            it('should call the storage API, passing the provided key and returning the stored empty string', async () => {
-                const apiClientMock = getApiClientMock({
-                    data: {
-                        appStoredCustomEntity: {
-                            value: ''
+            checkMetricsFired(metricMocks, { store: 'typed', operation: 'set', encrypted: false }, false);
+        });
+    });
+    describe('deleteEntity', () => {
+        it('should call the storage API, passing the provided entity name and key', async () => {
+            const apiClientMock = getApiClientMock({
+                data: {
+                    appStorageCustomEntity: {
+                        deleteAppStoredCustomEntity: {
+                            success: true
                         }
                     }
-                });
-                const globalStorage = getStorage(apiClientMock);
-                const returnedValue = await globalStorage.getEntity('testEntityName', 'testEntityKey');
-                verifyApiClientCalledWith(apiClientMock, {
+                }
+            });
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            await globalStorage.deleteEntity('testEntityName', 'testEntityKey');
+            verifyApiClientCalledWith(apiClientMock, {
+                input: {
                     contextAri,
                     entityName: 'testEntityName',
                     key: 'testEntityKey'
-                });
-                expect(returnedValue).toEqual('');
+                }
             });
-            it('should throw an error with the returned status for non-200 status codes', async () => {
-                const apiClientMock = getApiClientMock(undefined, 400);
-                const globalStorage = getStorage(apiClientMock);
-                const response = globalStorage.getEntity('testEntityName', 'testEntityKey');
-                expect(apiClientMock).toHaveBeenCalled();
-                await expect(response).rejects.toThrow(errors_1.APIError.forStatus(400));
-            });
-            it('should throw an error with the returned error message for failed responses', async () => {
-                const apiClientMock = getApiClientMock({
-                    errors: [INVALID_CURSOR_ERROR]
-                }, 200);
-                const globalStorage = getStorage(apiClientMock);
-                const response = globalStorage.getEntity('testEntityName', 'testEntityKey');
-                expect(apiClientMock).toHaveBeenCalled();
-                await expect(response).rejects.toThrow(errors_1.APIError.forErrorCode('CURSOR_INVALID', 'error message'));
-            });
-            it('should throw an error if the response is not a valid JSON', async () => {
-                const apiClientMock = getApiClientMockInvalidJson('test', 200);
-                const globalStorage = getStorage(apiClientMock);
-                const response = globalStorage.getEntity('testEntityName', 'testEntityKey');
-                expect(apiClientMock).toHaveBeenCalled();
-                await expect(response).rejects.toThrow(errors_1.APIError.forUnexpected('Response text was not a valid JSON: test'));
-            });
+            checkMetricsFired(metricMocks, { store: 'typed', operation: 'delete', encrypted: false }, true);
         });
-        describe('setEntity', () => {
-            it('should call the storage API, passing the provided entity name, entity key and value', async () => {
-                const apiClientMock = getApiClientMock({
-                    data: {
-                        appStorageCustomEntity: {
-                            setAppStoredCustomEntity: {
-                                success: true
-                            }
+        it('should throw an error if the storage API returns successful = false', async () => {
+            const apiClientMock = getApiClientMock({
+                data: {
+                    appStorageCustomEntity: {
+                        deleteAppStoredCustomEntity: {
+                            success: false,
+                            errors: [INVALID_CURSOR_ERROR]
                         }
                     }
-                });
-                const globalStorage = getStorage(apiClientMock);
-                await globalStorage.setEntity('testEntityName', 'testEntityKey', 'testValue');
-                verifyApiClientCalledWith(apiClientMock, {
-                    input: {
-                        contextAri,
-                        entityName: 'testEntityName',
-                        key: 'testEntityKey',
-                        value: 'testValue'
-                    }
-                });
+                }
             });
-            it('should throw an error if the storage API returns successful = false', async () => {
-                const apiClientMock = getApiClientMock({
-                    data: {
-                        appStorageCustomEntity: {
-                            setAppStoredCustomEntity: {
-                                success: false,
-                                errors: [INVALID_CURSOR_ERROR]
-                            }
-                        }
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            const response = globalStorage.deleteEntity('testEntityKey', 'testEntityKey');
+            expect(apiClientMock).toHaveBeenCalled();
+            await expect(response).rejects.toThrow(errors_1.APIError.forErrorCode('CURSOR_INVALID', 'error message'));
+            checkMetricsFired(metricMocks, { store: 'typed', operation: 'delete', encrypted: false }, false);
+        });
+        it('should throw an error if the storage API returns a non 200 status code and has no body', async () => {
+            const apiClientMock = getApiClientMockInvalidJson('', 400);
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            const response = globalStorage.deleteEntity('testEntityKey', 'testEntityKey');
+            expect(apiClientMock).toHaveBeenCalled();
+            await expect(response).rejects.toThrow(errors_1.APIError.forStatus(400));
+            checkMetricsFired(metricMocks, { store: 'typed', operation: 'delete', encrypted: false }, false);
+        });
+    });
+    describe('list', () => {
+        it('should call the storage API with the provided parameters', async () => {
+            const apiClientMock = getApiClientMock({
+                data: {
+                    appStoredEntities: {
+                        edges: [
+                            { node: { key: 'key1', value: 'testValue' }, cursor: 'cursor1' },
+                            { node: { key: 'key2', value: 'testValue' }, cursor: 'cursor2' }
+                        ]
                     }
-                });
-                const globalStorage = getStorage(apiClientMock);
-                const response = globalStorage.setEntity('testEntityName', 'testEntityKey', 'testValue');
-                expect(apiClientMock).toHaveBeenCalled();
-                await expect(response).rejects.toThrow(errors_1.APIError.forErrorCode('INVALID_CURSOR', 'error message'));
+                }
             });
-            it('should throw an error if the storage API returns a non 200 status code', async () => {
-                const apiClientMock = getApiClientMockInvalidJson('', 400);
-                const globalStorage = getStorage(apiClientMock);
-                const response = globalStorage.setEntity('testEntityName', 'testEntityKey', 'testValue');
-                expect(apiClientMock).toHaveBeenCalled();
-                await expect(response).rejects.toThrow(errors_1.APIError.forStatus(400));
-            });
-            it('should throw a 500 error if success=false but no errors were returned', async () => {
-                const apiClientMock = getApiClientMock({
-                    data: {
-                        appStorageCustomEntity: {
-                            setAppStoredCustomEntity: {
-                                success: false
-                            }
-                        }
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            const where = [
+                {
+                    field: 'key',
+                    condition: 'STARTS_WITH',
+                    value: 'test'
+                }
+            ];
+            const cursor = 'cursor';
+            const limit = 10;
+            const response = await globalStorage.list({ where, cursor, limit });
+            verifyApiClientCalledWith(apiClientMock, {
+                contextAri,
+                where,
+                cursor,
+                limit
+            }, gql_queries_1.UntypedQueries.listQuery(contextAri, {}).query);
+            expect(response).toEqual(expect.objectContaining({
+                results: [
+                    { key: 'key1', value: 'testValue' },
+                    { key: 'key2', value: 'testValue' }
+                ],
+                nextCursor: 'cursor2'
+            }));
+            checkMetricsFired(metricMocks, { store: 'untyped', operation: 'query', encrypted: false }, true);
+        });
+        it('should query the appStoredEntitiesForCleanup endpoint given process.env.IS_CLEANUP_FUNCTION is set to true', async () => {
+            process.env.IS_CLEANUP_FUNCTION = 'true';
+            const apiClientMock = getApiClientMock({
+                data: {
+                    appStoredEntitiesForCleanup: {
+                        edges: [
+                            { node: { key: 'key1', value: 'testValue' }, cursor: 'cursor1' },
+                            { node: { key: 'key2', value: 'testValue' }, cursor: 'cursor2' }
+                        ]
                     }
-                });
-                const globalStorage = getStorage(apiClientMock);
-                await expect(globalStorage.setEntity('testEntityName', 'testEntityKey', 'testValue')).rejects.toThrow(errors_1.APIError.forStatus(500));
-                verifyApiClientCalledWith(apiClientMock, {
-                    input: {
-                        contextAri,
-                        entityName: 'testEntityName',
-                        key: 'testEntityKey',
-                        value: 'testValue'
-                    }
-                });
+                }
             });
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            const where = [
+                {
+                    field: 'key',
+                    condition: 'STARTS_WITH',
+                    value: 'test'
+                }
+            ];
+            const cursor = 'cursor';
+            const limit = 10;
+            const response = await globalStorage.list({ where, cursor, limit });
+            verifyApiClientCalledWith(apiClientMock, {
+                contextAri,
+                where,
+                cursor,
+                limit
+            }, gql_queries_1.UntypedQueries.listQueryForCleanup(contextAri, {}).query);
+            expect(response).toEqual(expect.objectContaining({
+                results: [
+                    { key: 'key1', value: 'testValue' },
+                    { key: 'key2', value: 'testValue' }
+                ],
+                nextCursor: 'cursor2'
+            }));
+            checkMetricsFired(metricMocks, { store: 'untyped', operation: 'query', encrypted: false }, true);
+            process.env.IS_CLEANUP_FUNCTION = '';
         });
-        describe('deleteEntity', () => {
-            it('should call the storage API, passing the provided entity name and key', async () => {
-                const apiClientMock = getApiClientMock({
-                    data: {
-                        appStorageCustomEntity: {
-                            deleteAppStoredCustomEntity: {
-                                success: true
-                            }
-                        }
+        it('should use default values', async () => {
+            const apiClientMock = getApiClientMock({
+                data: {
+                    appStoredEntities: {
+                        edges: []
                     }
-                });
-                const globalStorage = getStorage(apiClientMock);
-                await globalStorage.deleteEntity('testEntityName', 'testEntityKey');
-                verifyApiClientCalledWith(apiClientMock, {
-                    input: {
-                        contextAri,
-                        entityName: 'testEntityName',
-                        key: 'testEntityKey'
-                    }
-                });
+                }
             });
-            it('should throw an error if the storage API returns successful = false', async () => {
-                const apiClientMock = getApiClientMock({
-                    data: {
-                        appStorageCustomEntity: {
-                            deleteAppStoredCustomEntity: {
-                                success: false,
-                                errors: [INVALID_CURSOR_ERROR]
-                            }
-                        }
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            await globalStorage.list({});
+            verifyApiClientCalledWith(apiClientMock, {
+                contextAri,
+                where: null,
+                cursor: null,
+                limit: null
+            }, gql_queries_1.UntypedQueries.listQuery(contextAri, {}).query);
+            checkMetricsFired(metricMocks, { store: 'untyped', operation: 'query', encrypted: false }, true);
+        });
+        it('should handle an empty result set', async () => {
+            const apiClientMock = getApiClientMock({
+                data: {
+                    appStoredEntities: {
+                        edges: []
                     }
-                });
-                const globalStorage = getStorage(apiClientMock);
-                const response = globalStorage.deleteEntity('testEntityKey', 'testEntityKey');
-                expect(apiClientMock).toHaveBeenCalled();
-                await expect(response).rejects.toThrow(errors_1.APIError.forErrorCode('CURSOR_INVALID', 'error message'));
+                }
             });
-            it('should throw an error if the storage API returns a non 200 status code and has no body', async () => {
-                const apiClientMock = getApiClientMockInvalidJson('', 400);
-                const globalStorage = getStorage(apiClientMock);
-                const response = globalStorage.deleteEntity('testEntityKey', 'testEntityKey');
-                expect(apiClientMock).toHaveBeenCalled();
-                await expect(response).rejects.toThrow(errors_1.APIError.forStatus(400));
-            });
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            const where = [
+                {
+                    field: 'key',
+                    condition: 'STARTS_WITH',
+                    value: 'test'
+                }
+            ];
+            const response = await globalStorage.list({ where });
+            expect(response).toEqual(expect.objectContaining({
+                results: [],
+                nextCursor: undefined
+            }));
+            checkMetricsFired(metricMocks, { store: 'untyped', operation: 'query', encrypted: false }, true);
         });
-        describe('list', () => {
-            it('should call the storage API with the provided parameters', async () => {
-                const apiClientMock = getApiClientMock({
-                    data: {
-                        appStoredEntities: {
-                            edges: [
-                                { node: { key: 'key1', value: 'testValue' }, cursor: 'cursor1' },
-                                { node: { key: 'key2', value: 'testValue' }, cursor: 'cursor2' }
-                            ]
-                        }
-                    }
-                });
-                const globalStorage = getStorage(apiClientMock);
-                const where = [
-                    {
-                        field: 'key',
-                        condition: 'STARTS_WITH',
-                        value: 'test'
-                    }
-                ];
-                const cursor = 'cursor';
-                const limit = 10;
-                const response = await globalStorage.list({ where, cursor, limit });
-                verifyApiClientCalledWith(apiClientMock, {
-                    contextAri,
-                    where,
-                    cursor,
-                    limit
-                }, gql_queries_1.UntypedQueries.listQuery(contextAri, {}).query);
-                expect(response).toEqual(expect.objectContaining({
-                    results: [
-                        { key: 'key1', value: 'testValue' },
-                        { key: 'key2', value: 'testValue' }
-                    ],
-                    nextCursor: 'cursor2'
-                }));
+        it('should throw an error if the storage API returns an error', async () => {
+            const apiClientMock = getApiClientMock({
+                errors: [INVALID_CURSOR_ERROR]
             });
-            it('should query the appStoredEntitiesForCleanup endpoint given process.env.IS_CLEANUP_FUNCTION is set to true', async () => {
-                process.env.IS_CLEANUP_FUNCTION = 'true';
-                const apiClientMock = getApiClientMock({
-                    data: {
-                        appStoredEntitiesForCleanup: {
-                            edges: [
-                                { node: { key: 'key1', value: 'testValue' }, cursor: 'cursor1' },
-                                { node: { key: 'key2', value: 'testValue' }, cursor: 'cursor2' }
-                            ]
-                        }
-                    }
-                });
-                const globalStorage = getStorage(apiClientMock);
-                const where = [
-                    {
-                        field: 'key',
-                        condition: 'STARTS_WITH',
-                        value: 'test'
-                    }
-                ];
-                const cursor = 'cursor';
-                const limit = 10;
-                const response = await globalStorage.list({ where, cursor, limit });
-                verifyApiClientCalledWith(apiClientMock, {
-                    contextAri,
-                    where,
-                    cursor,
-                    limit
-                }, gql_queries_1.UntypedQueries.listQueryForCleanup(contextAri, {}).query);
-                expect(response).toEqual(expect.objectContaining({
-                    results: [
-                        { key: 'key1', value: 'testValue' },
-                        { key: 'key2', value: 'testValue' }
-                    ],
-                    nextCursor: 'cursor2'
-                }));
-                process.env.IS_CLEANUP_FUNCTION = '';
-            });
-            it('should use default values', async () => {
-                const apiClientMock = getApiClientMock({
-                    data: {
-                        appStoredEntities: {
-                            edges: []
-                        }
-                    }
-                });
-                const globalStorage = getStorage(apiClientMock);
-                await globalStorage.list({});
-                verifyApiClientCalledWith(apiClientMock, {
-                    contextAri,
-                    where: null,
-                    cursor: null,
-                    limit: null
-                }, gql_queries_1.UntypedQueries.listQuery(contextAri, {}).query);
-            });
-            it('should handle an empty result set', async () => {
-                const apiClientMock = getApiClientMock({
-                    data: {
-                        appStoredEntities: {
-                            edges: []
-                        }
-                    }
-                });
-                const globalStorage = getStorage(apiClientMock);
-                const where = [
-                    {
-                        field: 'key',
-                        condition: 'STARTS_WITH',
-                        value: 'test'
-                    }
-                ];
-                const response = await globalStorage.list({ where });
-                expect(response).toEqual(expect.objectContaining({
-                    results: [],
-                    nextCursor: undefined
-                }));
-            });
-            it('should throw an error if the storage API returns an error', async () => {
-                const apiClientMock = getApiClientMock({
-                    errors: [INVALID_CURSOR_ERROR]
-                });
-                const globalStorage = getStorage(apiClientMock);
-                const response = globalStorage.list({});
-                expect(apiClientMock).toHaveBeenCalled();
-                await expect(response).rejects.toThrow(errors_1.APIError.forErrorCode('CURSOR_INVALID', 'error message'));
-            });
-            it('should throw an error if the storage API returns a non 200 status code and has no body', async () => {
-                const apiClientMock = getApiClientMockInvalidJson('', 400);
-                const globalStorage = getStorage(apiClientMock);
-                const response = globalStorage.list({});
-                expect(apiClientMock).toHaveBeenCalled();
-                await expect(response).rejects.toThrow(errors_1.APIError.forStatus(400));
-            });
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            const response = globalStorage.list({});
+            expect(apiClientMock).toHaveBeenCalled();
+            await expect(response).rejects.toThrow(errors_1.APIError.forErrorCode('CURSOR_INVALID', 'error message'));
+            checkMetricsFired(metricMocks, { store: 'untyped', operation: 'query', encrypted: false }, false);
         });
+        it('should throw an error if the storage API returns a non 200 status code and has no body', async () => {
+            const apiClientMock = getApiClientMockInvalidJson('', 400);
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            const response = globalStorage.list({});
+            expect(apiClientMock).toHaveBeenCalled();
+            await expect(response).rejects.toThrow(errors_1.APIError.forStatus(400));
+            checkMetricsFired(metricMocks, { store: 'untyped', operation: 'query', encrypted: false }, false);
+        });
     });
     describe('listCustomEntities', () => {
         it('should use default values', async () => {
             const apiClientMock = getApiClientMock({
@@ -735,17 +761,19 @@
                         edges: []
                     }
                 }
             });
-            const globalStorage = getStorage(apiClientMock);
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
             const response = await globalStorage.listCustomEntities({});
             expect(response).toMatchObject({
                 results: [],
                 nextCursor: null
             });
             verifyApiClientCalledWith(apiClientMock, {
                 contextAri
             }, gql_queries_1.CustomEntityQueries.listQuery(contextAri, {}).query);
+            checkMetricsFired(metricMocks, { store: 'typed', operation: 'query', encrypted: false }, true);
         });
         it('should return cursor when results are not present', async () => {
             const apiClientMock = getApiClientMock({
                 data: {
@@ -754,16 +782,38 @@
                         cursor: 'DUMMY_CURSOR'
                     }
                 }
             });
-            const globalStorage = getStorage(apiClientMock);
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
             const response = await globalStorage.listCustomEntities({});
             expect(response).toMatchObject({
                 results: [],
                 nextCursor: 'DUMMY_CURSOR'
             });
             verifyApiClientCalledWith(apiClientMock, {
                 contextAri
             }, gql_queries_1.CustomEntityQueries.listQuery(contextAri, {}).query);
+            checkMetricsFired(metricMocks, { store: 'typed', operation: 'query', encrypted: false }, true);
         });
+        it('should throw an error if the storage API returns an error', async () => {
+            const apiClientMock = getApiClientMock({
+                errors: [INVALID_CURSOR_ERROR]
+            });
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            const response = globalStorage.listCustomEntities({});
+            expect(apiClientMock).toHaveBeenCalled();
+            await expect(response).rejects.toThrow(errors_1.APIError.forErrorCode('CURSOR_INVALID', 'error message'));
+            checkMetricsFired(metricMocks, { store: 'typed', operation: 'query', encrypted: false }, false);
+        });
+        it('should throw an error if the storage API returns a non 200 status code and has no body', async () => {
+            const apiClientMock = getApiClientMockInvalidJson('', 400);
+            const metricMocks = getMetricMock();
+            const globalStorage = getStorage(apiClientMock, metricMocks.mockMetrics);
+            const response = globalStorage.listCustomEntities({});
+            expect(apiClientMock).toHaveBeenCalled();
+            await expect(response).rejects.toThrow(errors_1.APIError.forStatus(400));
+            checkMetricsFired(metricMocks, { store: 'typed', operation: 'query', encrypted: false }, false);
+        });
     });
 });