cds-caching 3.0.1 → 3.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"CacheStatisticsService-dbg.js","names":["cacheAndIdFilter","___model_filters","cacheNameFilter","periodFilter","CacheStatisticsService","constructor","model","ODataModel","serviceUrl","autoExpandSelect","groupId","getModel","getCurrentMetrics","cacheName","binding","bindList","undefined","Sorter","path","descending","data","requestContexts","results","map","item","getObject","length","transformStatistics","error","console","MessageBox","getHistoricalMetrics","period","from","to","filters","push","Filter","operator","FilterOperator","GE","value1","LE","getTopKeys","getColdKeys","persistStatistics","context","bindContext","invoke","hits","misses","sets","deletes","errors","avgLatency","p95Latency","p99Latency","minLatency","maxLatency","avgHitLatency","p95HitLatency","p99HitLatency","minHitLatency","maxHitLatency","avgMissLatency","p95MissLatency","p99MissLatency","minMissLatency","maxMissLatency","avgSetLatency","avgDeleteLatency","memoryUsage","itemCount","hitRatio","throughput","errorRate","cacheEfficiency","uptimeMs","uniqueKeys","topKeys","coldKeys","lastPersisted","Date","toISOString","getAvailableMetrics","getMetricById","metricId","setMetricsEnabled","enabled","setParameter","setKeyMetricsEnabled"],"sources":["CacheStatisticsService.ts"],"sourcesContent":["import MessageBox from \"sap/m/MessageBox\";\nimport ODataModel from \"sap/ui/model/odata/v4/ODataModel\";\nimport Filter from \"sap/ui/model/Filter\";\nimport FilterOperator from \"sap/ui/model/FilterOperator\";\nimport Sorter from \"sap/ui/model/Sorter\";\nimport Context from \"sap/ui/model/odata/v4/Context\";\nimport { cacheAndIdFilter, cacheNameFilter, periodFilter } from \"../model/filters\";\n\nexport interface CacheStatistics {\n hits: number;\n misses: number;\n sets: number;\n deletes: number;\n errors: number;\n\n // Overall latency metrics\n avgLatency: number;\n p95Latency: number;\n p99Latency: number;\n minLatency: number;\n maxLatency: number;\n\n // Hit-specific latency metrics\n avgHitLatency: number;\n p95HitLatency: number;\n p99HitLatency: number;\n minHitLatency: number;\n maxHitLatency: number;\n\n // Miss-specific latency metrics\n avgMissLatency: number;\n p95MissLatency: number;\n p99MissLatency: number;\n minMissLatency: number;\n maxMissLatency: number;\n\n // Set/Delete latency metrics\n avgSetLatency: number;\n avgDeleteLatency: number;\n\n // Performance metrics\n memoryUsage: number;\n itemCount: number;\n hitRatio: number;\n throughput: number;\n errorRate: number;\n cacheEfficiency: number;\n uptimeMs: number;\n uniqueKeys: number;\n topKeys: KeyAccess[];\n coldKeys: KeyAccess[];\n lastPersisted: string;\n}\n\nexport interface KeyAccess {\n keyName: string;\n hits: number;\n misses: number;\n sets: number;\n deletes: number;\n total: number;\n lastAccess: string;\n dataType: string;\n serviceName: string;\n entityName: string;\n operation: string;\n metadata: string;\n}\n\nexport interface HistoricalStatistics {\n ID: string;\n cache: string;\n timestamp: string;\n period: string;\n\n hits: number;\n misses: number;\n sets: number;\n deletes: number;\n errors: number;\n totalRequests: number;\n\n avgHitLatency: number;\n p95HitLatency: number;\n p99HitLatency: number;\n minHitLatency: number;\n maxHitLatency: number;\n avgMissLatency: number;\n p95MissLatency: number;\n p99MissLatency: number;\n minMissLatency: number;\n maxMissLatency: number;\n avgSetLatency: number;\n avgDeleteLatency: number;\n\n hitRatio: number;\n throughput: number;\n errorRate: number;\n cacheEfficiency: number;\n\n nativeSets: number;\n nativeGets: number;\n nativeDeletes: number;\n nativeClears: number;\n nativeDeleteByTags: number;\n nativeErrors: number;\n totalNativeOperations: number;\n\n nativeThroughput: number;\n nativeErrorRate: number;\n\n memoryUsage: number;\n itemCount: number;\n uptimeMs: number;\n}\n\n/**\n * Service class for interacting with the Cache Statistics API using OData V4\n */\nexport default class CacheStatisticsService {\n private model: ODataModel;\n\n constructor(model?: ODataModel) {\n this.model = model || new ODataModel({\n serviceUrl: \"/odata/v4/caching/\",\n autoExpandSelect: true,\n groupId: \"$auto\"\n });\n }\n\n getModel(): ODataModel {\n return this.model;\n }\n\n async getCurrentMetrics(cacheName: string): Promise<CacheStatistics | null> {\n try {\n const binding = this.model.bindList(\n \"/Metrics\",\n undefined,\n [new Sorter({ path: \"timestamp\", descending: true })],\n [periodFilter(\"hourly\"), cacheNameFilter(cacheName)]\n );\n\n const data = await binding.requestContexts();\n const results = data.map((item: Context) => item.getObject());\n\n if (results.length > 0) {\n return this.transformStatistics(results[0]);\n }\n return null;\n } catch (error) {\n console.error(\"Error fetching current metrics:\", error);\n MessageBox.error(\"Failed to load current metrics\");\n return null;\n }\n }\n\n async getHistoricalMetrics(cacheName: string, period: string = \"hourly\", from?: string, to?: string): Promise<HistoricalStatistics[]> {\n try {\n const filters: Filter[] = [periodFilter(period), cacheNameFilter(cacheName)];\n if (from) {\n filters.push(new Filter({ path: \"timestamp\", operator: FilterOperator.GE, value1: from }));\n }\n if (to) {\n filters.push(new Filter({ path: \"timestamp\", operator: FilterOperator.LE, value1: to }));\n }\n\n const binding = this.model.bindList(\n \"/Metrics\",\n undefined,\n [new Sorter({ path: \"timestamp\", descending: true })],\n filters\n );\n\n const data = await binding.requestContexts();\n return data.map((item: Context) => item.getObject());\n } catch (error) {\n console.error(\"Error fetching historical metrics:\", error);\n MessageBox.error(\"Failed to load historical metrics\");\n return [];\n }\n }\n\n async getTopKeys(cacheName: string): Promise<KeyAccess[]> {\n try {\n const binding = this.model.bindList(\n \"/KeyMetrics\",\n undefined,\n [new Sorter({ path: \"totalRequests\", descending: true })],\n [periodFilter(\"current\"), cacheNameFilter(cacheName)]\n );\n\n const data = await binding.requestContexts();\n return data.map((item: Context) => item.getObject());\n } catch (error) {\n console.error(\"Error fetching top keys:\", error);\n MessageBox.error(\"Failed to load top keys\");\n return [];\n }\n }\n\n async getColdKeys(cacheName: string): Promise<KeyAccess[]> {\n try {\n const binding = this.model.bindList(\n \"/KeyMetrics\",\n undefined,\n [new Sorter({ path: \"lastAccess\", descending: false })],\n [periodFilter(\"current\"), cacheNameFilter(cacheName)]\n );\n\n const data = await binding.requestContexts();\n return data.map((item: Context) => item.getObject());\n } catch (error) {\n console.error(\"Error fetching cold keys:\", error);\n MessageBox.error(\"Failed to load cold keys\");\n return [];\n }\n }\n\n async persistStatistics(): Promise<boolean> {\n try {\n const context = this.model.bindContext(\"/persistStatistics(...)\");\n await context.invoke();\n return true;\n } catch (error) {\n console.error(\"Error persisting statistics:\", error);\n MessageBox.error(\"Failed to persist statistics\");\n return false;\n }\n }\n\n private transformStatistics(data: Record<string, unknown>): CacheStatistics {\n return {\n hits: (data.hits as number) || 0,\n misses: (data.misses as number) || 0,\n sets: (data.sets as number) || 0,\n deletes: (data.deletes as number) || 0,\n errors: (data.errors as number) || 0,\n\n avgLatency: (data.avgLatency as number) || 0,\n p95Latency: (data.p95Latency as number) || 0,\n p99Latency: (data.p99Latency as number) || 0,\n minLatency: (data.minLatency as number) || 0,\n maxLatency: (data.maxLatency as number) || 0,\n\n avgHitLatency: (data.avgHitLatency as number) || 0,\n p95HitLatency: (data.p95HitLatency as number) || 0,\n p99HitLatency: (data.p99HitLatency as number) || 0,\n minHitLatency: (data.minHitLatency as number) || 0,\n maxHitLatency: (data.maxHitLatency as number) || 0,\n\n avgMissLatency: (data.avgMissLatency as number) || 0,\n p95MissLatency: (data.p95MissLatency as number) || 0,\n p99MissLatency: (data.p99MissLatency as number) || 0,\n minMissLatency: (data.minMissLatency as number) || 0,\n maxMissLatency: (data.maxMissLatency as number) || 0,\n\n avgSetLatency: (data.avgSetLatency as number) || 0,\n avgDeleteLatency: (data.avgDeleteLatency as number) || 0,\n\n memoryUsage: (data.memoryUsage as number) || 0,\n itemCount: (data.itemCount as number) || 0,\n hitRatio: (data.hitRatio as number) || 0,\n throughput: (data.throughput as number) || 0,\n errorRate: (data.errorRate as number) || 0,\n cacheEfficiency: (data.cacheEfficiency as number) || 0,\n uptimeMs: (data.uptimeMs as number) || 0,\n uniqueKeys: 0,\n topKeys: [],\n coldKeys: [],\n lastPersisted: (data.lastPersisted as string) || new Date().toISOString()\n };\n }\n\n async getAvailableMetrics(cacheName: string): Promise<Record<string, unknown>[]> {\n try {\n const binding = this.model.bindList(\n \"/Metrics\",\n undefined,\n [new Sorter({ path: \"timestamp\", descending: true })],\n [cacheNameFilter(cacheName)]\n );\n\n const data = await binding.requestContexts();\n return data.map((item: Context) => item.getObject());\n } catch (error) {\n console.error(\"Error fetching available metrics:\", error);\n MessageBox.error(\"Failed to load available metrics\");\n return [];\n }\n }\n\n async getMetricById(cacheName: string, metricId: string): Promise<CacheStatistics | null> {\n try {\n const binding = this.model.bindList(\n \"/Metrics\",\n undefined,\n undefined,\n cacheAndIdFilter(cacheName, metricId)\n );\n\n const data = await binding.requestContexts();\n const results = data.map((item: Context) => item.getObject());\n\n if (results.length > 0) {\n return this.transformStatistics(results[0]);\n }\n return null;\n } catch (error) {\n console.error(\"Error fetching metric by ID:\", error);\n MessageBox.error(\"Failed to load metric\");\n return null;\n }\n }\n\n async setMetricsEnabled(cacheName: string, enabled: boolean): Promise<boolean> {\n try {\n const context = this.model.bindContext(\"/setMetricsEnabled(...)\");\n context.setParameter(\"cache\", cacheName);\n context.setParameter(\"enabled\", enabled);\n await context.invoke();\n return true;\n } catch (error) {\n console.error(\"Error setting metrics enabled:\", error);\n MessageBox.error(\"Failed to update metrics configuration\");\n return false;\n }\n }\n\n async setKeyMetricsEnabled(cacheName: string, enabled: boolean): Promise<boolean> {\n try {\n const context = this.model.bindContext(\"/setKeyMetricsEnabled(...)\");\n context.setParameter(\"cache\", cacheName);\n context.setParameter(\"enabled\", enabled);\n await context.invoke();\n return true;\n } catch (error) {\n console.error(\"Error setting key metrics enabled:\", error);\n MessageBox.error(\"Failed to update key metrics configuration\");\n return false;\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"CacheStatisticsService-dbg.js","names":["cacheAndIdFilter","___model_filters","cacheNameFilter","periodFilter","CacheStatisticsService","constructor","model","ODataModel","serviceUrl","autoExpandSelect","groupId","getModel","getCurrentMetrics","cacheName","binding","bindList","undefined","Sorter","path","descending","data","requestContexts","results","map","item","getObject","length","transformStatistics","error","console","MessageBox","getHistoricalMetrics","period","from","to","filters","push","Filter","operator","FilterOperator","GE","value1","LE","getTopKeys","getColdKeys","persistStatistics","context","bindContext","invoke","hits","misses","sets","deletes","errors","avgLatency","p95Latency","p99Latency","minLatency","maxLatency","avgHitLatency","p95HitLatency","p99HitLatency","minHitLatency","maxHitLatency","avgMissLatency","p95MissLatency","p99MissLatency","minMissLatency","maxMissLatency","avgSetLatency","avgDeleteLatency","memoryUsage","itemCount","hitRatio","throughput","errorRate","cacheEfficiency","uptimeMs","uniqueKeys","topKeys","coldKeys","lastPersisted","Date","toISOString","getAvailableMetrics","getMetricById","metricId","setMetricsEnabled","enabled","setParameter","setKeyMetricsEnabled"],"sources":["CacheStatisticsService.ts"],"sourcesContent":["import MessageBox from \"sap/m/MessageBox\";\nimport ODataModel from \"sap/ui/model/odata/v4/ODataModel\";\nimport Filter from \"sap/ui/model/Filter\";\nimport FilterOperator from \"sap/ui/model/FilterOperator\";\nimport Sorter from \"sap/ui/model/Sorter\";\nimport Context from \"sap/ui/model/odata/v4/Context\";\nimport { cacheAndIdFilter, cacheNameFilter, periodFilter } from \"../model/filters\";\n\nexport interface CacheStatistics {\n hits: number;\n misses: number;\n sets: number;\n deletes: number;\n errors: number;\n\n // Overall latency metrics\n avgLatency: number;\n p95Latency: number;\n p99Latency: number;\n minLatency: number;\n maxLatency: number;\n\n // Hit-specific latency metrics\n avgHitLatency: number;\n p95HitLatency: number;\n p99HitLatency: number;\n minHitLatency: number;\n maxHitLatency: number;\n\n // Miss-specific latency metrics\n avgMissLatency: number;\n p95MissLatency: number;\n p99MissLatency: number;\n minMissLatency: number;\n maxMissLatency: number;\n\n // Set/Delete latency metrics\n avgSetLatency: number;\n avgDeleteLatency: number;\n\n // Performance metrics\n memoryUsage: number;\n itemCount: number;\n hitRatio: number;\n throughput: number;\n errorRate: number;\n cacheEfficiency: number;\n uptimeMs: number;\n uniqueKeys: number;\n topKeys: KeyAccess[];\n coldKeys: KeyAccess[];\n lastPersisted: string;\n}\n\nexport interface KeyAccess {\n keyName: string;\n hits: number;\n misses: number;\n sets: number;\n deletes: number;\n total: number;\n lastAccess: string;\n dataType: string;\n serviceName: string;\n entityName: string;\n operation: string;\n metadata: string;\n}\n\nexport interface HistoricalStatistics {\n ID: string;\n cache: string;\n timestamp: string;\n period: string;\n\n hits: number;\n misses: number;\n sets: number;\n deletes: number;\n errors: number;\n totalRequests: number;\n\n avgHitLatency: number;\n p95HitLatency: number;\n p99HitLatency: number;\n minHitLatency: number;\n maxHitLatency: number;\n avgMissLatency: number;\n p95MissLatency: number;\n p99MissLatency: number;\n minMissLatency: number;\n maxMissLatency: number;\n avgSetLatency: number;\n avgDeleteLatency: number;\n\n hitRatio: number;\n throughput: number;\n errorRate: number;\n cacheEfficiency: number;\n\n nativeSets: number;\n nativeGets: number;\n nativeDeletes: number;\n nativeClears: number;\n nativeDeleteByTags: number;\n nativeErrors: number;\n totalNativeOperations: number;\n\n nativeThroughput: number;\n nativeErrorRate: number;\n\n memoryUsage: number;\n itemCount: number;\n uptimeMs: number;\n}\n\n/**\n * Service class for interacting with the Cache Statistics API using OData V4\n */\nexport default class CacheStatisticsService {\n private model: ODataModel;\n\n constructor(model?: ODataModel) {\n this.model = model || new ODataModel({\n serviceUrl: \"/odata/v4/caching-api/\",\n autoExpandSelect: true,\n groupId: \"$auto\"\n });\n }\n\n getModel(): ODataModel {\n return this.model;\n }\n\n async getCurrentMetrics(cacheName: string): Promise<CacheStatistics | null> {\n try {\n const binding = this.model.bindList(\n \"/Metrics\",\n undefined,\n [new Sorter({ path: \"timestamp\", descending: true })],\n [periodFilter(\"hourly\"), cacheNameFilter(cacheName)]\n );\n\n const data = await binding.requestContexts();\n const results = data.map((item: Context) => item.getObject());\n\n if (results.length > 0) {\n return this.transformStatistics(results[0]);\n }\n return null;\n } catch (error) {\n console.error(\"Error fetching current metrics:\", error);\n MessageBox.error(\"Failed to load current metrics\");\n return null;\n }\n }\n\n async getHistoricalMetrics(cacheName: string, period: string = \"hourly\", from?: string, to?: string): Promise<HistoricalStatistics[]> {\n try {\n const filters: Filter[] = [periodFilter(period), cacheNameFilter(cacheName)];\n if (from) {\n filters.push(new Filter({ path: \"timestamp\", operator: FilterOperator.GE, value1: from }));\n }\n if (to) {\n filters.push(new Filter({ path: \"timestamp\", operator: FilterOperator.LE, value1: to }));\n }\n\n const binding = this.model.bindList(\n \"/Metrics\",\n undefined,\n [new Sorter({ path: \"timestamp\", descending: true })],\n filters\n );\n\n const data = await binding.requestContexts();\n return data.map((item: Context) => item.getObject());\n } catch (error) {\n console.error(\"Error fetching historical metrics:\", error);\n MessageBox.error(\"Failed to load historical metrics\");\n return [];\n }\n }\n\n async getTopKeys(cacheName: string): Promise<KeyAccess[]> {\n try {\n const binding = this.model.bindList(\n \"/KeyMetrics\",\n undefined,\n [new Sorter({ path: \"totalRequests\", descending: true })],\n [periodFilter(\"current\"), cacheNameFilter(cacheName)]\n );\n\n const data = await binding.requestContexts();\n return data.map((item: Context) => item.getObject());\n } catch (error) {\n console.error(\"Error fetching top keys:\", error);\n MessageBox.error(\"Failed to load top keys\");\n return [];\n }\n }\n\n async getColdKeys(cacheName: string): Promise<KeyAccess[]> {\n try {\n const binding = this.model.bindList(\n \"/KeyMetrics\",\n undefined,\n [new Sorter({ path: \"lastAccess\", descending: false })],\n [periodFilter(\"current\"), cacheNameFilter(cacheName)]\n );\n\n const data = await binding.requestContexts();\n return data.map((item: Context) => item.getObject());\n } catch (error) {\n console.error(\"Error fetching cold keys:\", error);\n MessageBox.error(\"Failed to load cold keys\");\n return [];\n }\n }\n\n async persistStatistics(): Promise<boolean> {\n try {\n const context = this.model.bindContext(\"/persistStatistics(...)\");\n await context.invoke();\n return true;\n } catch (error) {\n console.error(\"Error persisting statistics:\", error);\n MessageBox.error(\"Failed to persist statistics\");\n return false;\n }\n }\n\n private transformStatistics(data: Record<string, unknown>): CacheStatistics {\n return {\n hits: (data.hits as number) || 0,\n misses: (data.misses as number) || 0,\n sets: (data.sets as number) || 0,\n deletes: (data.deletes as number) || 0,\n errors: (data.errors as number) || 0,\n\n avgLatency: (data.avgLatency as number) || 0,\n p95Latency: (data.p95Latency as number) || 0,\n p99Latency: (data.p99Latency as number) || 0,\n minLatency: (data.minLatency as number) || 0,\n maxLatency: (data.maxLatency as number) || 0,\n\n avgHitLatency: (data.avgHitLatency as number) || 0,\n p95HitLatency: (data.p95HitLatency as number) || 0,\n p99HitLatency: (data.p99HitLatency as number) || 0,\n minHitLatency: (data.minHitLatency as number) || 0,\n maxHitLatency: (data.maxHitLatency as number) || 0,\n\n avgMissLatency: (data.avgMissLatency as number) || 0,\n p95MissLatency: (data.p95MissLatency as number) || 0,\n p99MissLatency: (data.p99MissLatency as number) || 0,\n minMissLatency: (data.minMissLatency as number) || 0,\n maxMissLatency: (data.maxMissLatency as number) || 0,\n\n avgSetLatency: (data.avgSetLatency as number) || 0,\n avgDeleteLatency: (data.avgDeleteLatency as number) || 0,\n\n memoryUsage: (data.memoryUsage as number) || 0,\n itemCount: (data.itemCount as number) || 0,\n hitRatio: (data.hitRatio as number) || 0,\n throughput: (data.throughput as number) || 0,\n errorRate: (data.errorRate as number) || 0,\n cacheEfficiency: (data.cacheEfficiency as number) || 0,\n uptimeMs: (data.uptimeMs as number) || 0,\n uniqueKeys: 0,\n topKeys: [],\n coldKeys: [],\n lastPersisted: (data.lastPersisted as string) || new Date().toISOString()\n };\n }\n\n async getAvailableMetrics(cacheName: string): Promise<Record<string, unknown>[]> {\n try {\n const binding = this.model.bindList(\n \"/Metrics\",\n undefined,\n [new Sorter({ path: \"timestamp\", descending: true })],\n [cacheNameFilter(cacheName)]\n );\n\n const data = await binding.requestContexts();\n return data.map((item: Context) => item.getObject());\n } catch (error) {\n console.error(\"Error fetching available metrics:\", error);\n MessageBox.error(\"Failed to load available metrics\");\n return [];\n }\n }\n\n async getMetricById(cacheName: string, metricId: string): Promise<CacheStatistics | null> {\n try {\n const binding = this.model.bindList(\n \"/Metrics\",\n undefined,\n undefined,\n cacheAndIdFilter(cacheName, metricId)\n );\n\n const data = await binding.requestContexts();\n const results = data.map((item: Context) => item.getObject());\n\n if (results.length > 0) {\n return this.transformStatistics(results[0]);\n }\n return null;\n } catch (error) {\n console.error(\"Error fetching metric by ID:\", error);\n MessageBox.error(\"Failed to load metric\");\n return null;\n }\n }\n\n async setMetricsEnabled(cacheName: string, enabled: boolean): Promise<boolean> {\n try {\n const context = this.model.bindContext(\"/setMetricsEnabled(...)\");\n context.setParameter(\"cache\", cacheName);\n context.setParameter(\"enabled\", enabled);\n await context.invoke();\n return true;\n } catch (error) {\n console.error(\"Error setting metrics enabled:\", error);\n MessageBox.error(\"Failed to update metrics configuration\");\n return false;\n }\n }\n\n async setKeyMetricsEnabled(cacheName: string, enabled: boolean): Promise<boolean> {\n try {\n const context = this.model.bindContext(\"/setKeyMetricsEnabled(...)\");\n context.setParameter(\"cache\", cacheName);\n context.setParameter(\"enabled\", enabled);\n await context.invoke();\n return true;\n } catch (error) {\n console.error(\"Error setting key metrics enabled:\", error);\n MessageBox.error(\"Failed to update key metrics configuration\");\n return false;\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1,2 +1,2 @@
1
- sap.ui.define(["sap/m/MessageBox","sap/ui/model/odata/v4/ODataModel","sap/ui/model/Filter","sap/ui/model/FilterOperator","sap/ui/model/Sorter","../model/filters"],function(e,t,r,s,a,n){"use strict";const i=n["cacheAndIdFilter"];const c=n["cacheNameFilter"];const o=n["periodFilter"];class l{constructor(e){this.model=e||new t({serviceUrl:"/odata/v4/caching/",autoExpandSelect:true,groupId:"$auto"})}getModel(){return this.model}async getCurrentMetrics(t){try{const e=this.model.bindList("/Metrics",undefined,[new a({path:"timestamp",descending:true})],[o("hourly"),c(t)]);const r=await e.requestContexts();const s=r.map(e=>e.getObject());if(s.length>0){return this.transformStatistics(s[0])}return null}catch(t){console.error("Error fetching current metrics:",t);e.error("Failed to load current metrics");return null}}async getHistoricalMetrics(t,n="hourly",i,l){try{const e=[o(n),c(t)];if(i){e.push(new r({path:"timestamp",operator:s.GE,value1:i}))}if(l){e.push(new r({path:"timestamp",operator:s.LE,value1:l}))}const d=this.model.bindList("/Metrics",undefined,[new a({path:"timestamp",descending:true})],e);const u=await d.requestContexts();return u.map(e=>e.getObject())}catch(t){console.error("Error fetching historical metrics:",t);e.error("Failed to load historical metrics");return[]}}async getTopKeys(t){try{const e=this.model.bindList("/KeyMetrics",undefined,[new a({path:"totalRequests",descending:true})],[o("current"),c(t)]);const r=await e.requestContexts();return r.map(e=>e.getObject())}catch(t){console.error("Error fetching top keys:",t);e.error("Failed to load top keys");return[]}}async getColdKeys(t){try{const e=this.model.bindList("/KeyMetrics",undefined,[new a({path:"lastAccess",descending:false})],[o("current"),c(t)]);const r=await e.requestContexts();return r.map(e=>e.getObject())}catch(t){console.error("Error fetching cold keys:",t);e.error("Failed to load cold keys");return[]}}async persistStatistics(){try{const e=this.model.bindContext("/persistStatistics(...)");await e.invoke();return true}catch(t){console.error("Error persisting statistics:",t);e.error("Failed to persist statistics");return false}}transformStatistics(e){return{hits:e.hits||0,misses:e.misses||0,sets:e.sets||0,deletes:e.deletes||0,errors:e.errors||0,avgLatency:e.avgLatency||0,p95Latency:e.p95Latency||0,p99Latency:e.p99Latency||0,minLatency:e.minLatency||0,maxLatency:e.maxLatency||0,avgHitLatency:e.avgHitLatency||0,p95HitLatency:e.p95HitLatency||0,p99HitLatency:e.p99HitLatency||0,minHitLatency:e.minHitLatency||0,maxHitLatency:e.maxHitLatency||0,avgMissLatency:e.avgMissLatency||0,p95MissLatency:e.p95MissLatency||0,p99MissLatency:e.p99MissLatency||0,minMissLatency:e.minMissLatency||0,maxMissLatency:e.maxMissLatency||0,avgSetLatency:e.avgSetLatency||0,avgDeleteLatency:e.avgDeleteLatency||0,memoryUsage:e.memoryUsage||0,itemCount:e.itemCount||0,hitRatio:e.hitRatio||0,throughput:e.throughput||0,errorRate:e.errorRate||0,cacheEfficiency:e.cacheEfficiency||0,uptimeMs:e.uptimeMs||0,uniqueKeys:0,topKeys:[],coldKeys:[],lastPersisted:e.lastPersisted||(new Date).toISOString()}}async getAvailableMetrics(t){try{const e=this.model.bindList("/Metrics",undefined,[new a({path:"timestamp",descending:true})],[c(t)]);const r=await e.requestContexts();return r.map(e=>e.getObject())}catch(t){console.error("Error fetching available metrics:",t);e.error("Failed to load available metrics");return[]}}async getMetricById(t,r){try{const e=this.model.bindList("/Metrics",undefined,undefined,i(t,r));const s=await e.requestContexts();const a=s.map(e=>e.getObject());if(a.length>0){return this.transformStatistics(a[0])}return null}catch(t){console.error("Error fetching metric by ID:",t);e.error("Failed to load metric");return null}}async setMetricsEnabled(t,r){try{const e=this.model.bindContext("/setMetricsEnabled(...)");e.setParameter("cache",t);e.setParameter("enabled",r);await e.invoke();return true}catch(t){console.error("Error setting metrics enabled:",t);e.error("Failed to update metrics configuration");return false}}async setKeyMetricsEnabled(t,r){try{const e=this.model.bindContext("/setKeyMetricsEnabled(...)");e.setParameter("cache",t);e.setParameter("enabled",r);await e.invoke();return true}catch(t){console.error("Error setting key metrics enabled:",t);e.error("Failed to update key metrics configuration");return false}}}return l});
1
+ sap.ui.define(["sap/m/MessageBox","sap/ui/model/odata/v4/ODataModel","sap/ui/model/Filter","sap/ui/model/FilterOperator","sap/ui/model/Sorter","../model/filters"],function(e,t,r,s,a,n){"use strict";const i=n["cacheAndIdFilter"];const c=n["cacheNameFilter"];const o=n["periodFilter"];class l{constructor(e){this.model=e||new t({serviceUrl:"/odata/v4/caching-api/",autoExpandSelect:true,groupId:"$auto"})}getModel(){return this.model}async getCurrentMetrics(t){try{const e=this.model.bindList("/Metrics",undefined,[new a({path:"timestamp",descending:true})],[o("hourly"),c(t)]);const r=await e.requestContexts();const s=r.map(e=>e.getObject());if(s.length>0){return this.transformStatistics(s[0])}return null}catch(t){console.error("Error fetching current metrics:",t);e.error("Failed to load current metrics");return null}}async getHistoricalMetrics(t,n="hourly",i,l){try{const e=[o(n),c(t)];if(i){e.push(new r({path:"timestamp",operator:s.GE,value1:i}))}if(l){e.push(new r({path:"timestamp",operator:s.LE,value1:l}))}const d=this.model.bindList("/Metrics",undefined,[new a({path:"timestamp",descending:true})],e);const u=await d.requestContexts();return u.map(e=>e.getObject())}catch(t){console.error("Error fetching historical metrics:",t);e.error("Failed to load historical metrics");return[]}}async getTopKeys(t){try{const e=this.model.bindList("/KeyMetrics",undefined,[new a({path:"totalRequests",descending:true})],[o("current"),c(t)]);const r=await e.requestContexts();return r.map(e=>e.getObject())}catch(t){console.error("Error fetching top keys:",t);e.error("Failed to load top keys");return[]}}async getColdKeys(t){try{const e=this.model.bindList("/KeyMetrics",undefined,[new a({path:"lastAccess",descending:false})],[o("current"),c(t)]);const r=await e.requestContexts();return r.map(e=>e.getObject())}catch(t){console.error("Error fetching cold keys:",t);e.error("Failed to load cold keys");return[]}}async persistStatistics(){try{const e=this.model.bindContext("/persistStatistics(...)");await e.invoke();return true}catch(t){console.error("Error persisting statistics:",t);e.error("Failed to persist statistics");return false}}transformStatistics(e){return{hits:e.hits||0,misses:e.misses||0,sets:e.sets||0,deletes:e.deletes||0,errors:e.errors||0,avgLatency:e.avgLatency||0,p95Latency:e.p95Latency||0,p99Latency:e.p99Latency||0,minLatency:e.minLatency||0,maxLatency:e.maxLatency||0,avgHitLatency:e.avgHitLatency||0,p95HitLatency:e.p95HitLatency||0,p99HitLatency:e.p99HitLatency||0,minHitLatency:e.minHitLatency||0,maxHitLatency:e.maxHitLatency||0,avgMissLatency:e.avgMissLatency||0,p95MissLatency:e.p95MissLatency||0,p99MissLatency:e.p99MissLatency||0,minMissLatency:e.minMissLatency||0,maxMissLatency:e.maxMissLatency||0,avgSetLatency:e.avgSetLatency||0,avgDeleteLatency:e.avgDeleteLatency||0,memoryUsage:e.memoryUsage||0,itemCount:e.itemCount||0,hitRatio:e.hitRatio||0,throughput:e.throughput||0,errorRate:e.errorRate||0,cacheEfficiency:e.cacheEfficiency||0,uptimeMs:e.uptimeMs||0,uniqueKeys:0,topKeys:[],coldKeys:[],lastPersisted:e.lastPersisted||(new Date).toISOString()}}async getAvailableMetrics(t){try{const e=this.model.bindList("/Metrics",undefined,[new a({path:"timestamp",descending:true})],[c(t)]);const r=await e.requestContexts();return r.map(e=>e.getObject())}catch(t){console.error("Error fetching available metrics:",t);e.error("Failed to load available metrics");return[]}}async getMetricById(t,r){try{const e=this.model.bindList("/Metrics",undefined,undefined,i(t,r));const s=await e.requestContexts();const a=s.map(e=>e.getObject());if(a.length>0){return this.transformStatistics(a[0])}return null}catch(t){console.error("Error fetching metric by ID:",t);e.error("Failed to load metric");return null}}async setMetricsEnabled(t,r){try{const e=this.model.bindContext("/setMetricsEnabled(...)");e.setParameter("cache",t);e.setParameter("enabled",r);await e.invoke();return true}catch(t){console.error("Error setting metrics enabled:",t);e.error("Failed to update metrics configuration");return false}}async setKeyMetricsEnabled(t,r){try{const e=this.model.bindContext("/setKeyMetricsEnabled(...)");e.setParameter("cache",t);e.setParameter("enabled",r);await e.invoke();return true}catch(t){console.error("Error setting key metrics enabled:",t);e.error("Failed to update key metrics configuration");return false}}}return l});
2
2
  //# sourceMappingURL=CacheStatisticsService.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CacheStatisticsService.js","names":["cacheAndIdFilter","___model_filters","cacheNameFilter","periodFilter","CacheStatisticsService","constructor","model","this","ODataModel","serviceUrl","autoExpandSelect","groupId","getModel","getCurrentMetrics","cacheName","binding","bindList","undefined","Sorter","path","descending","data","requestContexts","results","map","item","getObject","length","transformStatistics","error","console","MessageBox","getHistoricalMetrics","period","from","to","filters","push","Filter","operator","FilterOperator","GE","value1","LE","getTopKeys","getColdKeys","persistStatistics","context","bindContext","invoke","hits","misses","sets","deletes","errors","avgLatency","p95Latency","p99Latency","minLatency","maxLatency","avgHitLatency","p95HitLatency","p99HitLatency","minHitLatency","maxHitLatency","avgMissLatency","p95MissLatency","p99MissLatency","minMissLatency","maxMissLatency","avgSetLatency","avgDeleteLatency","memoryUsage","itemCount","hitRatio","throughput","errorRate","cacheEfficiency","uptimeMs","uniqueKeys","topKeys","coldKeys","lastPersisted","Date","toISOString","getAvailableMetrics","getMetricById","metricId","setMetricsEnabled","enabled","setParameter","setKeyMetricsEnabled"],"sources":["CacheStatisticsService.ts"],"sourcesContent":["import MessageBox from \"sap/m/MessageBox\";\nimport ODataModel from \"sap/ui/model/odata/v4/ODataModel\";\nimport Filter from \"sap/ui/model/Filter\";\nimport FilterOperator from \"sap/ui/model/FilterOperator\";\nimport Sorter from \"sap/ui/model/Sorter\";\nimport Context from \"sap/ui/model/odata/v4/Context\";\nimport { cacheAndIdFilter, cacheNameFilter, periodFilter } from \"../model/filters\";\n\nexport interface CacheStatistics {\n hits: number;\n misses: number;\n sets: number;\n deletes: number;\n errors: number;\n\n // Overall latency metrics\n avgLatency: number;\n p95Latency: number;\n p99Latency: number;\n minLatency: number;\n maxLatency: number;\n\n // Hit-specific latency metrics\n avgHitLatency: number;\n p95HitLatency: number;\n p99HitLatency: number;\n minHitLatency: number;\n maxHitLatency: number;\n\n // Miss-specific latency metrics\n avgMissLatency: number;\n p95MissLatency: number;\n p99MissLatency: number;\n minMissLatency: number;\n maxMissLatency: number;\n\n // Set/Delete latency metrics\n avgSetLatency: number;\n avgDeleteLatency: number;\n\n // Performance metrics\n memoryUsage: number;\n itemCount: number;\n hitRatio: number;\n throughput: number;\n errorRate: number;\n cacheEfficiency: number;\n uptimeMs: number;\n uniqueKeys: number;\n topKeys: KeyAccess[];\n coldKeys: KeyAccess[];\n lastPersisted: string;\n}\n\nexport interface KeyAccess {\n keyName: string;\n hits: number;\n misses: number;\n sets: number;\n deletes: number;\n total: number;\n lastAccess: string;\n dataType: string;\n serviceName: string;\n entityName: string;\n operation: string;\n metadata: string;\n}\n\nexport interface HistoricalStatistics {\n ID: string;\n cache: string;\n timestamp: string;\n period: string;\n\n hits: number;\n misses: number;\n sets: number;\n deletes: number;\n errors: number;\n totalRequests: number;\n\n avgHitLatency: number;\n p95HitLatency: number;\n p99HitLatency: number;\n minHitLatency: number;\n maxHitLatency: number;\n avgMissLatency: number;\n p95MissLatency: number;\n p99MissLatency: number;\n minMissLatency: number;\n maxMissLatency: number;\n avgSetLatency: number;\n avgDeleteLatency: number;\n\n hitRatio: number;\n throughput: number;\n errorRate: number;\n cacheEfficiency: number;\n\n nativeSets: number;\n nativeGets: number;\n nativeDeletes: number;\n nativeClears: number;\n nativeDeleteByTags: number;\n nativeErrors: number;\n totalNativeOperations: number;\n\n nativeThroughput: number;\n nativeErrorRate: number;\n\n memoryUsage: number;\n itemCount: number;\n uptimeMs: number;\n}\n\n/**\n * Service class for interacting with the Cache Statistics API using OData V4\n */\nexport default class CacheStatisticsService {\n private model: ODataModel;\n\n constructor(model?: ODataModel) {\n this.model = model || new ODataModel({\n serviceUrl: \"/odata/v4/caching/\",\n autoExpandSelect: true,\n groupId: \"$auto\"\n });\n }\n\n getModel(): ODataModel {\n return this.model;\n }\n\n async getCurrentMetrics(cacheName: string): Promise<CacheStatistics | null> {\n try {\n const binding = this.model.bindList(\n \"/Metrics\",\n undefined,\n [new Sorter({ path: \"timestamp\", descending: true })],\n [periodFilter(\"hourly\"), cacheNameFilter(cacheName)]\n );\n\n const data = await binding.requestContexts();\n const results = data.map((item: Context) => item.getObject());\n\n if (results.length > 0) {\n return this.transformStatistics(results[0]);\n }\n return null;\n } catch (error) {\n console.error(\"Error fetching current metrics:\", error);\n MessageBox.error(\"Failed to load current metrics\");\n return null;\n }\n }\n\n async getHistoricalMetrics(cacheName: string, period: string = \"hourly\", from?: string, to?: string): Promise<HistoricalStatistics[]> {\n try {\n const filters: Filter[] = [periodFilter(period), cacheNameFilter(cacheName)];\n if (from) {\n filters.push(new Filter({ path: \"timestamp\", operator: FilterOperator.GE, value1: from }));\n }\n if (to) {\n filters.push(new Filter({ path: \"timestamp\", operator: FilterOperator.LE, value1: to }));\n }\n\n const binding = this.model.bindList(\n \"/Metrics\",\n undefined,\n [new Sorter({ path: \"timestamp\", descending: true })],\n filters\n );\n\n const data = await binding.requestContexts();\n return data.map((item: Context) => item.getObject());\n } catch (error) {\n console.error(\"Error fetching historical metrics:\", error);\n MessageBox.error(\"Failed to load historical metrics\");\n return [];\n }\n }\n\n async getTopKeys(cacheName: string): Promise<KeyAccess[]> {\n try {\n const binding = this.model.bindList(\n \"/KeyMetrics\",\n undefined,\n [new Sorter({ path: \"totalRequests\", descending: true })],\n [periodFilter(\"current\"), cacheNameFilter(cacheName)]\n );\n\n const data = await binding.requestContexts();\n return data.map((item: Context) => item.getObject());\n } catch (error) {\n console.error(\"Error fetching top keys:\", error);\n MessageBox.error(\"Failed to load top keys\");\n return [];\n }\n }\n\n async getColdKeys(cacheName: string): Promise<KeyAccess[]> {\n try {\n const binding = this.model.bindList(\n \"/KeyMetrics\",\n undefined,\n [new Sorter({ path: \"lastAccess\", descending: false })],\n [periodFilter(\"current\"), cacheNameFilter(cacheName)]\n );\n\n const data = await binding.requestContexts();\n return data.map((item: Context) => item.getObject());\n } catch (error) {\n console.error(\"Error fetching cold keys:\", error);\n MessageBox.error(\"Failed to load cold keys\");\n return [];\n }\n }\n\n async persistStatistics(): Promise<boolean> {\n try {\n const context = this.model.bindContext(\"/persistStatistics(...)\");\n await context.invoke();\n return true;\n } catch (error) {\n console.error(\"Error persisting statistics:\", error);\n MessageBox.error(\"Failed to persist statistics\");\n return false;\n }\n }\n\n private transformStatistics(data: Record<string, unknown>): CacheStatistics {\n return {\n hits: (data.hits as number) || 0,\n misses: (data.misses as number) || 0,\n sets: (data.sets as number) || 0,\n deletes: (data.deletes as number) || 0,\n errors: (data.errors as number) || 0,\n\n avgLatency: (data.avgLatency as number) || 0,\n p95Latency: (data.p95Latency as number) || 0,\n p99Latency: (data.p99Latency as number) || 0,\n minLatency: (data.minLatency as number) || 0,\n maxLatency: (data.maxLatency as number) || 0,\n\n avgHitLatency: (data.avgHitLatency as number) || 0,\n p95HitLatency: (data.p95HitLatency as number) || 0,\n p99HitLatency: (data.p99HitLatency as number) || 0,\n minHitLatency: (data.minHitLatency as number) || 0,\n maxHitLatency: (data.maxHitLatency as number) || 0,\n\n avgMissLatency: (data.avgMissLatency as number) || 0,\n p95MissLatency: (data.p95MissLatency as number) || 0,\n p99MissLatency: (data.p99MissLatency as number) || 0,\n minMissLatency: (data.minMissLatency as number) || 0,\n maxMissLatency: (data.maxMissLatency as number) || 0,\n\n avgSetLatency: (data.avgSetLatency as number) || 0,\n avgDeleteLatency: (data.avgDeleteLatency as number) || 0,\n\n memoryUsage: (data.memoryUsage as number) || 0,\n itemCount: (data.itemCount as number) || 0,\n hitRatio: (data.hitRatio as number) || 0,\n throughput: (data.throughput as number) || 0,\n errorRate: (data.errorRate as number) || 0,\n cacheEfficiency: (data.cacheEfficiency as number) || 0,\n uptimeMs: (data.uptimeMs as number) || 0,\n uniqueKeys: 0,\n topKeys: [],\n coldKeys: [],\n lastPersisted: (data.lastPersisted as string) || new Date().toISOString()\n };\n }\n\n async getAvailableMetrics(cacheName: string): Promise<Record<string, unknown>[]> {\n try {\n const binding = this.model.bindList(\n \"/Metrics\",\n undefined,\n [new Sorter({ path: \"timestamp\", descending: true })],\n [cacheNameFilter(cacheName)]\n );\n\n const data = await binding.requestContexts();\n return data.map((item: Context) => item.getObject());\n } catch (error) {\n console.error(\"Error fetching available metrics:\", error);\n MessageBox.error(\"Failed to load available metrics\");\n return [];\n }\n }\n\n async getMetricById(cacheName: string, metricId: string): Promise<CacheStatistics | null> {\n try {\n const binding = this.model.bindList(\n \"/Metrics\",\n undefined,\n undefined,\n cacheAndIdFilter(cacheName, metricId)\n );\n\n const data = await binding.requestContexts();\n const results = data.map((item: Context) => item.getObject());\n\n if (results.length > 0) {\n return this.transformStatistics(results[0]);\n }\n return null;\n } catch (error) {\n console.error(\"Error fetching metric by ID:\", error);\n MessageBox.error(\"Failed to load metric\");\n return null;\n }\n }\n\n async setMetricsEnabled(cacheName: string, enabled: boolean): Promise<boolean> {\n try {\n const context = this.model.bindContext(\"/setMetricsEnabled(...)\");\n context.setParameter(\"cache\", cacheName);\n context.setParameter(\"enabled\", enabled);\n await context.invoke();\n return true;\n } catch (error) {\n console.error(\"Error setting metrics enabled:\", error);\n MessageBox.error(\"Failed to update metrics configuration\");\n return false;\n }\n }\n\n async setKeyMetricsEnabled(cacheName: string, enabled: boolean): Promise<boolean> {\n try {\n const context = this.model.bindContext(\"/setKeyMetricsEnabled(...)\");\n context.setParameter(\"cache\", cacheName);\n context.setParameter(\"enabled\", enabled);\n await context.invoke();\n return true;\n } catch (error) {\n console.error(\"Error setting key metrics enabled:\", error);\n MessageBox.error(\"Failed to update key metrics configuration\");\n return false;\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"CacheStatisticsService.js","names":["cacheAndIdFilter","___model_filters","cacheNameFilter","periodFilter","CacheStatisticsService","constructor","model","this","ODataModel","serviceUrl","autoExpandSelect","groupId","getModel","getCurrentMetrics","cacheName","binding","bindList","undefined","Sorter","path","descending","data","requestContexts","results","map","item","getObject","length","transformStatistics","error","console","MessageBox","getHistoricalMetrics","period","from","to","filters","push","Filter","operator","FilterOperator","GE","value1","LE","getTopKeys","getColdKeys","persistStatistics","context","bindContext","invoke","hits","misses","sets","deletes","errors","avgLatency","p95Latency","p99Latency","minLatency","maxLatency","avgHitLatency","p95HitLatency","p99HitLatency","minHitLatency","maxHitLatency","avgMissLatency","p95MissLatency","p99MissLatency","minMissLatency","maxMissLatency","avgSetLatency","avgDeleteLatency","memoryUsage","itemCount","hitRatio","throughput","errorRate","cacheEfficiency","uptimeMs","uniqueKeys","topKeys","coldKeys","lastPersisted","Date","toISOString","getAvailableMetrics","getMetricById","metricId","setMetricsEnabled","enabled","setParameter","setKeyMetricsEnabled"],"sources":["CacheStatisticsService.ts"],"sourcesContent":["import MessageBox from \"sap/m/MessageBox\";\nimport ODataModel from \"sap/ui/model/odata/v4/ODataModel\";\nimport Filter from \"sap/ui/model/Filter\";\nimport FilterOperator from \"sap/ui/model/FilterOperator\";\nimport Sorter from \"sap/ui/model/Sorter\";\nimport Context from \"sap/ui/model/odata/v4/Context\";\nimport { cacheAndIdFilter, cacheNameFilter, periodFilter } from \"../model/filters\";\n\nexport interface CacheStatistics {\n hits: number;\n misses: number;\n sets: number;\n deletes: number;\n errors: number;\n\n // Overall latency metrics\n avgLatency: number;\n p95Latency: number;\n p99Latency: number;\n minLatency: number;\n maxLatency: number;\n\n // Hit-specific latency metrics\n avgHitLatency: number;\n p95HitLatency: number;\n p99HitLatency: number;\n minHitLatency: number;\n maxHitLatency: number;\n\n // Miss-specific latency metrics\n avgMissLatency: number;\n p95MissLatency: number;\n p99MissLatency: number;\n minMissLatency: number;\n maxMissLatency: number;\n\n // Set/Delete latency metrics\n avgSetLatency: number;\n avgDeleteLatency: number;\n\n // Performance metrics\n memoryUsage: number;\n itemCount: number;\n hitRatio: number;\n throughput: number;\n errorRate: number;\n cacheEfficiency: number;\n uptimeMs: number;\n uniqueKeys: number;\n topKeys: KeyAccess[];\n coldKeys: KeyAccess[];\n lastPersisted: string;\n}\n\nexport interface KeyAccess {\n keyName: string;\n hits: number;\n misses: number;\n sets: number;\n deletes: number;\n total: number;\n lastAccess: string;\n dataType: string;\n serviceName: string;\n entityName: string;\n operation: string;\n metadata: string;\n}\n\nexport interface HistoricalStatistics {\n ID: string;\n cache: string;\n timestamp: string;\n period: string;\n\n hits: number;\n misses: number;\n sets: number;\n deletes: number;\n errors: number;\n totalRequests: number;\n\n avgHitLatency: number;\n p95HitLatency: number;\n p99HitLatency: number;\n minHitLatency: number;\n maxHitLatency: number;\n avgMissLatency: number;\n p95MissLatency: number;\n p99MissLatency: number;\n minMissLatency: number;\n maxMissLatency: number;\n avgSetLatency: number;\n avgDeleteLatency: number;\n\n hitRatio: number;\n throughput: number;\n errorRate: number;\n cacheEfficiency: number;\n\n nativeSets: number;\n nativeGets: number;\n nativeDeletes: number;\n nativeClears: number;\n nativeDeleteByTags: number;\n nativeErrors: number;\n totalNativeOperations: number;\n\n nativeThroughput: number;\n nativeErrorRate: number;\n\n memoryUsage: number;\n itemCount: number;\n uptimeMs: number;\n}\n\n/**\n * Service class for interacting with the Cache Statistics API using OData V4\n */\nexport default class CacheStatisticsService {\n private model: ODataModel;\n\n constructor(model?: ODataModel) {\n this.model = model || new ODataModel({\n serviceUrl: \"/odata/v4/caching-api/\",\n autoExpandSelect: true,\n groupId: \"$auto\"\n });\n }\n\n getModel(): ODataModel {\n return this.model;\n }\n\n async getCurrentMetrics(cacheName: string): Promise<CacheStatistics | null> {\n try {\n const binding = this.model.bindList(\n \"/Metrics\",\n undefined,\n [new Sorter({ path: \"timestamp\", descending: true })],\n [periodFilter(\"hourly\"), cacheNameFilter(cacheName)]\n );\n\n const data = await binding.requestContexts();\n const results = data.map((item: Context) => item.getObject());\n\n if (results.length > 0) {\n return this.transformStatistics(results[0]);\n }\n return null;\n } catch (error) {\n console.error(\"Error fetching current metrics:\", error);\n MessageBox.error(\"Failed to load current metrics\");\n return null;\n }\n }\n\n async getHistoricalMetrics(cacheName: string, period: string = \"hourly\", from?: string, to?: string): Promise<HistoricalStatistics[]> {\n try {\n const filters: Filter[] = [periodFilter(period), cacheNameFilter(cacheName)];\n if (from) {\n filters.push(new Filter({ path: \"timestamp\", operator: FilterOperator.GE, value1: from }));\n }\n if (to) {\n filters.push(new Filter({ path: \"timestamp\", operator: FilterOperator.LE, value1: to }));\n }\n\n const binding = this.model.bindList(\n \"/Metrics\",\n undefined,\n [new Sorter({ path: \"timestamp\", descending: true })],\n filters\n );\n\n const data = await binding.requestContexts();\n return data.map((item: Context) => item.getObject());\n } catch (error) {\n console.error(\"Error fetching historical metrics:\", error);\n MessageBox.error(\"Failed to load historical metrics\");\n return [];\n }\n }\n\n async getTopKeys(cacheName: string): Promise<KeyAccess[]> {\n try {\n const binding = this.model.bindList(\n \"/KeyMetrics\",\n undefined,\n [new Sorter({ path: \"totalRequests\", descending: true })],\n [periodFilter(\"current\"), cacheNameFilter(cacheName)]\n );\n\n const data = await binding.requestContexts();\n return data.map((item: Context) => item.getObject());\n } catch (error) {\n console.error(\"Error fetching top keys:\", error);\n MessageBox.error(\"Failed to load top keys\");\n return [];\n }\n }\n\n async getColdKeys(cacheName: string): Promise<KeyAccess[]> {\n try {\n const binding = this.model.bindList(\n \"/KeyMetrics\",\n undefined,\n [new Sorter({ path: \"lastAccess\", descending: false })],\n [periodFilter(\"current\"), cacheNameFilter(cacheName)]\n );\n\n const data = await binding.requestContexts();\n return data.map((item: Context) => item.getObject());\n } catch (error) {\n console.error(\"Error fetching cold keys:\", error);\n MessageBox.error(\"Failed to load cold keys\");\n return [];\n }\n }\n\n async persistStatistics(): Promise<boolean> {\n try {\n const context = this.model.bindContext(\"/persistStatistics(...)\");\n await context.invoke();\n return true;\n } catch (error) {\n console.error(\"Error persisting statistics:\", error);\n MessageBox.error(\"Failed to persist statistics\");\n return false;\n }\n }\n\n private transformStatistics(data: Record<string, unknown>): CacheStatistics {\n return {\n hits: (data.hits as number) || 0,\n misses: (data.misses as number) || 0,\n sets: (data.sets as number) || 0,\n deletes: (data.deletes as number) || 0,\n errors: (data.errors as number) || 0,\n\n avgLatency: (data.avgLatency as number) || 0,\n p95Latency: (data.p95Latency as number) || 0,\n p99Latency: (data.p99Latency as number) || 0,\n minLatency: (data.minLatency as number) || 0,\n maxLatency: (data.maxLatency as number) || 0,\n\n avgHitLatency: (data.avgHitLatency as number) || 0,\n p95HitLatency: (data.p95HitLatency as number) || 0,\n p99HitLatency: (data.p99HitLatency as number) || 0,\n minHitLatency: (data.minHitLatency as number) || 0,\n maxHitLatency: (data.maxHitLatency as number) || 0,\n\n avgMissLatency: (data.avgMissLatency as number) || 0,\n p95MissLatency: (data.p95MissLatency as number) || 0,\n p99MissLatency: (data.p99MissLatency as number) || 0,\n minMissLatency: (data.minMissLatency as number) || 0,\n maxMissLatency: (data.maxMissLatency as number) || 0,\n\n avgSetLatency: (data.avgSetLatency as number) || 0,\n avgDeleteLatency: (data.avgDeleteLatency as number) || 0,\n\n memoryUsage: (data.memoryUsage as number) || 0,\n itemCount: (data.itemCount as number) || 0,\n hitRatio: (data.hitRatio as number) || 0,\n throughput: (data.throughput as number) || 0,\n errorRate: (data.errorRate as number) || 0,\n cacheEfficiency: (data.cacheEfficiency as number) || 0,\n uptimeMs: (data.uptimeMs as number) || 0,\n uniqueKeys: 0,\n topKeys: [],\n coldKeys: [],\n lastPersisted: (data.lastPersisted as string) || new Date().toISOString()\n };\n }\n\n async getAvailableMetrics(cacheName: string): Promise<Record<string, unknown>[]> {\n try {\n const binding = this.model.bindList(\n \"/Metrics\",\n undefined,\n [new Sorter({ path: \"timestamp\", descending: true })],\n [cacheNameFilter(cacheName)]\n );\n\n const data = await binding.requestContexts();\n return data.map((item: Context) => item.getObject());\n } catch (error) {\n console.error(\"Error fetching available metrics:\", error);\n MessageBox.error(\"Failed to load available metrics\");\n return [];\n }\n }\n\n async getMetricById(cacheName: string, metricId: string): Promise<CacheStatistics | null> {\n try {\n const binding = this.model.bindList(\n \"/Metrics\",\n undefined,\n undefined,\n cacheAndIdFilter(cacheName, metricId)\n );\n\n const data = await binding.requestContexts();\n const results = data.map((item: Context) => item.getObject());\n\n if (results.length > 0) {\n return this.transformStatistics(results[0]);\n }\n return null;\n } catch (error) {\n console.error(\"Error fetching metric by ID:\", error);\n MessageBox.error(\"Failed to load metric\");\n return null;\n }\n }\n\n async setMetricsEnabled(cacheName: string, enabled: boolean): Promise<boolean> {\n try {\n const context = this.model.bindContext(\"/setMetricsEnabled(...)\");\n context.setParameter(\"cache\", cacheName);\n context.setParameter(\"enabled\", enabled);\n await context.invoke();\n return true;\n } catch (error) {\n console.error(\"Error setting metrics enabled:\", error);\n MessageBox.error(\"Failed to update metrics configuration\");\n return false;\n }\n }\n\n async setKeyMetricsEnabled(cacheName: string, enabled: boolean): Promise<boolean> {\n try {\n const context = this.model.bindContext(\"/setKeyMetricsEnabled(...)\");\n context.setParameter(\"cache\", cacheName);\n context.setParameter(\"enabled\", enabled);\n await context.invoke();\n return true;\n } catch (error) {\n console.error(\"Error setting key metrics enabled:\", error);\n MessageBox.error(\"Failed to update key metrics configuration\");\n return false;\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -11,7 +11,7 @@
11
11
 
12
12
  <script
13
13
  id="sap-ui-bootstrap"
14
- src="https://ui5.sap.com/1.136.1/resources/sap-ui-core.js"
14
+ src="https://ui5.sap.com/1.148.10/resources/sap-ui-core.js"
15
15
  data-sap-ui-resource-roots='{
16
16
  "cds.plugin.caching.dashboard": "./"
17
17
  }'
@@ -15,7 +15,7 @@
15
15
  },
16
16
  "dataSources": {
17
17
  "caching": {
18
- "uri": "/odata/v4/caching/",
18
+ "uri": "/odata/v4/caching-api/",
19
19
  "type": "OData",
20
20
  "settings": {
21
21
  "odataVersion": "4.0"
@@ -39,7 +39,7 @@
39
39
  "id": "app"
40
40
  },
41
41
  "dependencies": {
42
- "minUI5Version": "1.136.1",
42
+ "minUI5Version": "1.148.10",
43
43
  "libs": {
44
44
  "sap.ui.core": {},
45
45
  "sap.m": {},
@@ -75,8 +75,8 @@
75
75
  },
76
76
  "": {
77
77
  "type": "sap.ui.model.odata.v4.ODataModel",
78
+ "dataSource": "caching",
78
79
  "settings": {
79
- "serviceUrl": "/odata/v4/caching-api/",
80
80
  "operationMode": "Server",
81
81
  "autoExpandSelect": true,
82
82
  "groupId": "$auto"
@@ -122,7 +122,7 @@ export default class CacheStatisticsService {
122
122
 
123
123
  constructor(model?: ODataModel) {
124
124
  this.model = model || new ODataModel({
125
- serviceUrl: "/odata/v4/caching/",
125
+ serviceUrl: "/odata/v4/caching-api/",
126
126
  autoExpandSelect: true,
127
127
  groupId: "$auto"
128
128
  });
package/db/statistics.cds CHANGED
@@ -5,10 +5,13 @@ entity Caches {
5
5
  config : String;
6
6
  metricsEnabled : Boolean default false;
7
7
  keyMetricsEnabled : Boolean default false;
8
+ tagMetricsEnabled : Boolean default false;
8
9
  metrics : Composition of many Metrics
9
10
  on metrics.cache = $self.name;
10
11
  keyMetrics : Composition of many KeyMetrics
11
12
  on keyMetrics.cache = $self.name;
13
+ tagMetrics : Composition of many TagMetrics
14
+ on tagMetrics.cache = $self.name;
12
15
  }
13
16
 
14
17
  entity Metrics {
@@ -126,3 +129,56 @@ entity KeyMetrics {
126
129
  timestamp : DateTime; // When this key was first accessed
127
130
  cacheOptions : String; // JSON string with cache options
128
131
  }
132
+
133
+ /**
134
+ * Per-tag metrics. Opt-in via `tagMetricsEnabled` / `metrics.tagMetricsEnabled`.
135
+ *
136
+ * An entry can carry several tags, so a single hit increments every matching tag
137
+ * row. Tag totals can therefore exceed cache-level `Metrics` totals — that is
138
+ * expected, not a bug. Query by the resolved tag string (exact match), e.g.
139
+ * `tag eq 'federation:Airports'`.
140
+ */
141
+ entity TagMetrics {
142
+ key ID : String;
143
+ key cache : String;
144
+ key tag : String;
145
+ lastAccess : DateTime;
146
+ period : String enum {
147
+ current;
148
+ hourly;
149
+ daily;
150
+ };
151
+
152
+ // Read-through metrics (hits and misses only)
153
+ hits : Integer default 0;
154
+ misses : Integer default 0;
155
+ errors : Integer default 0;
156
+ totalRequests : Integer default 0;
157
+ hitRatio : Double;
158
+ cacheEfficiency : Double;
159
+
160
+ // Read-through latency metrics
161
+ avgHitLatency : Double;
162
+ minHitLatency : Double;
163
+ maxHitLatency : Double;
164
+ avgMissLatency : Double;
165
+ minMissLatency : Double;
166
+ maxMissLatency : Double;
167
+ avgReadThroughLatency : Double;
168
+
169
+ // Read-through performance metrics
170
+ throughput : Double;
171
+ errorRate : Double;
172
+
173
+ // Native function metrics (counts only)
174
+ nativeHits : Integer default 0;
175
+ nativeMisses : Integer default 0;
176
+ nativeSets : Integer default 0;
177
+ nativeDeletes : Integer default 0;
178
+ nativeErrors : Integer default 0;
179
+ totalNativeOperations : Integer default 0;
180
+ nativeThroughput : Double;
181
+ nativeErrorRate : Double;
182
+
183
+ timestamp : DateTime;
184
+ }
package/index.cds CHANGED
@@ -39,8 +39,10 @@ context plugin.cds_caching {
39
39
  action clear() returns Boolean;
40
40
  action clearMetrics() returns Boolean;
41
41
  action clearKeyMetrics() returns Boolean;
42
+ action clearTagMetrics() returns Boolean;
42
43
  action setMetricsEnabled(enabled : Boolean) returns Boolean;
43
44
  action setKeyMetricsEnabled(enabled : Boolean) returns Boolean;
45
+ action setTagMetricsEnabled(enabled : Boolean) returns Boolean;
44
46
  };
45
47
 
46
48
  @readonly
@@ -49,5 +51,8 @@ context plugin.cds_caching {
49
51
  @readonly
50
52
  entity KeyMetrics as projection on plugin.cds_caching.KeyMetrics;
51
53
 
54
+ @readonly
55
+ entity TagMetrics as projection on plugin.cds_caching.TagMetrics;
56
+
52
57
  }
53
58
  }
@@ -58,6 +58,15 @@ export interface CacheKeyMetrics {
58
58
  lastAccessed: Date;
59
59
  }
60
60
 
61
+ export interface CacheTagMetrics {
62
+ tag: string;
63
+ hits: number;
64
+ misses: number;
65
+ totalRequests: number;
66
+ hitRatio: number;
67
+ lastAccess: Date;
68
+ }
69
+
61
70
  export interface CachableFunctionOptions {
62
71
  '@cache.ttl'?: number;
63
72
  '@cache.key'?: string | object;
@@ -280,6 +289,16 @@ export declare class CachingService extends Service {
280
289
  */
281
290
  getCurrentKeyMetrics(): Promise<CacheKeyMetrics>;
282
291
 
292
+ /**
293
+ * Get tag-specific metrics for a specific period
294
+ */
295
+ getTagMetrics(tag: string, from: Date, to: Date): Promise<CacheTagMetrics>;
296
+
297
+ /**
298
+ * Get current tag metrics
299
+ */
300
+ getCurrentTagMetrics(): Promise<Map<string, CacheTagMetrics> | null>;
301
+
283
302
  /**
284
303
  * Clear all metrics
285
304
  */
@@ -290,6 +309,11 @@ export declare class CachingService extends Service {
290
309
  */
291
310
  clearKeyMetrics(): Promise<void>;
292
311
 
312
+ /**
313
+ * Clear tag metrics
314
+ */
315
+ clearTagMetrics(): Promise<void>;
316
+
293
317
  /**
294
318
  * Enable or disable statistics at runtime
295
319
  */
@@ -300,6 +324,11 @@ export declare class CachingService extends Service {
300
324
  */
301
325
  setKeyMetricsEnabled(enabled: boolean): Promise<void>;
302
326
 
327
+ /**
328
+ * Enable or disable tag tracking at runtime
329
+ */
330
+ setTagMetricsEnabled(enabled: boolean): Promise<void>;
331
+
303
332
  /**
304
333
  * Persist metrics to database
305
334
  */
@@ -129,12 +129,16 @@ class CachingService extends cds.Service {
129
129
 
130
130
  let metricsEnabled = config.metricsEnabled;
131
131
  let keyMetricsEnabled = config.keyMetricsEnabled;
132
+ let tagMetricsEnabled = config.tagMetricsEnabled;
132
133
  if (normalized.metrics?.enabled === true) {
133
134
  metricsEnabled = true;
134
135
  }
135
136
  if (normalized.metrics?.keyMetricsEnabled === true) {
136
137
  keyMetricsEnabled = true;
137
138
  }
139
+ if (normalized.metrics?.tagMetricsEnabled === true) {
140
+ tagMetricsEnabled = true;
141
+ }
138
142
 
139
143
  // Initialize statistics with runtime configuration support
140
144
  this.statistics = new CacheStatisticsHandler({
@@ -142,6 +146,7 @@ class CachingService extends cds.Service {
142
146
  ...statsOpts,
143
147
  });
144
148
  this.statistics.enableKeyMetrics(keyMetricsEnabled);
149
+ this.statistics.enableTagMetrics(tagMetricsEnabled);
145
150
  this.statistics.enableMetrics(metricsEnabled);
146
151
 
147
152
  if (normalized.metrics?.enabled === true && isPluginModelAvailable()) {
@@ -158,6 +163,13 @@ class CachingService extends cds.Service {
158
163
  this.log.warn(`Failed to persist keyMetricsEnabled from config for ${this.name}:`, error);
159
164
  }
160
165
  }
166
+ if (normalized.metrics?.tagMetricsEnabled === true && isPluginModelAvailable()) {
167
+ try {
168
+ await this.runtimeConfigManager.setTagMetricsEnabled(true);
169
+ } catch (error) {
170
+ this.log.warn(`Failed to persist tagMetricsEnabled from config for ${this.name}:`, error);
171
+ }
172
+ }
161
173
 
162
174
  // Initialize operation managers
163
175
  this.basicOperations = new BasicOperations(
@@ -402,6 +414,25 @@ class CachingService extends cds.Service {
402
414
  return this.statistics.getCurrentKeyMetrics();
403
415
  }
404
416
 
417
+ /**
418
+ * Get tag-specific metrics for a specific period
419
+ * @param {string} tag - resolved tag string
420
+ * @param {Date} from
421
+ * @param {Date} to
422
+ * @returns {Promise<object>}
423
+ */
424
+ async getTagMetrics(tag, from, to) {
425
+ return this.statistics.getTagMetrics(tag, from, to);
426
+ }
427
+
428
+ /**
429
+ * Get current tag metrics
430
+ * @returns {Promise<Map|null>}
431
+ */
432
+ async getCurrentTagMetrics() {
433
+ return this.statistics.getCurrentTagMetrics();
434
+ }
435
+
405
436
 
406
437
 
407
438
  /**
@@ -420,6 +451,14 @@ class CachingService extends cds.Service {
420
451
  return this.statistics.clearKeyMetrics();
421
452
  }
422
453
 
454
+ /**
455
+ * Clear tag metrics
456
+ * @returns {Promise<void>}
457
+ */
458
+ async clearTagMetrics() {
459
+ return this.statistics.clearTagMetrics();
460
+ }
461
+
423
462
  /**
424
463
  * Enable or disable statistics at runtime
425
464
  * @param {boolean} enabled - whether to enable statistics
@@ -440,6 +479,16 @@ class CachingService extends cds.Service {
440
479
  this.statistics.enableKeyMetrics(enabled);
441
480
  }
442
481
 
482
+ /**
483
+ * Enable or disable tag tracking at runtime
484
+ * @param {boolean} enabled - whether to enable tag tracking
485
+ * @returns {Promise<void>}
486
+ */
487
+ async setTagMetricsEnabled(enabled) {
488
+ await this.runtimeConfigManager.setTagMetricsEnabled(enabled);
489
+ this.statistics.enableTagMetrics(enabled);
490
+ }
491
+
443
492
  /**
444
493
  * Persist metrics to database
445
494
  * @returns {Promise<void>}
package/lib/add.js CHANGED
@@ -3,7 +3,7 @@ const { copy, path, write, fs } = cds.utils;
3
3
  const { join } = path;
4
4
 
5
5
  const APP_ID = "cds.plugin.caching.dashboard";
6
- const UI5_VERSION = "1.136.1";
6
+ const UI5_VERSION = "1.148.10";
7
7
 
8
8
  function resolveModuleId() {
9
9
  const project = cds.add?.readProject?.();
@@ -97,9 +97,11 @@ function getStatisticsHandlerOptions(metrics) {
97
97
  if (metrics.persistenceInterval != null) opts.persistenceInterval = metrics.persistenceInterval
98
98
  if (metrics.maxLatencies != null) opts.maxLatencies = metrics.maxLatencies
99
99
  if (metrics.maxKeyMetrics != null) opts.maxKeyMetrics = metrics.maxKeyMetrics
100
+ if (metrics.maxTagMetrics != null) opts.maxTagMetrics = metrics.maxTagMetrics
100
101
  if (metrics.maxMetricFieldLength != null) opts.maxMetricFieldLength = metrics.maxMetricFieldLength
101
102
  if (metrics.enabled === true) opts.metricsEnabled = true
102
103
  if (metrics.keyMetricsEnabled === true) opts.keyMetricsEnabled = true
104
+ if (metrics.tagMetricsEnabled === true) opts.tagMetricsEnabled = true
103
105
  return opts
104
106
  }
105
107
 
@@ -12,7 +12,7 @@ const path = require('path')
12
12
  * the runtime under a released dashboard, so a UI5 regression would surface as a
13
13
  * broken dashboard in deployments that changed nothing.
14
14
  */
15
- const DEFAULT_UI5_VERSION = '1.136.1'
15
+ const DEFAULT_UI5_VERSION = '1.148.10'
16
16
  const DEFAULT_UI5_URL = `https://ui5.sap.com/${DEFAULT_UI5_VERSION}/resources/sap-ui-core.js`
17
17
 
18
18
  /** Matches the bootstrap script tag, whatever order its attributes are in. */