cds-caching 1.2.0 → 1.3.0

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.
Files changed (79) hide show
  1. package/README.md +195 -1114
  2. package/app/dashboard/Component-dbg.js +59 -0
  3. package/app/dashboard/Component-dbg.js.map +1 -0
  4. package/app/dashboard/Component.js +2 -0
  5. package/app/dashboard/Component.js.map +1 -0
  6. package/app/dashboard/Component.ts +59 -0
  7. package/app/dashboard/controller/App-dbg.controller.js +132 -0
  8. package/app/dashboard/controller/App-dbg.controller.js.map +1 -0
  9. package/app/dashboard/controller/App.controller.js +2 -0
  10. package/app/dashboard/controller/App.controller.js.map +1 -0
  11. package/app/dashboard/controller/App.controller.ts +147 -0
  12. package/app/dashboard/controller/BaseController-dbg.js +75 -0
  13. package/app/dashboard/controller/BaseController-dbg.js.map +1 -0
  14. package/app/dashboard/controller/BaseController.js +2 -0
  15. package/app/dashboard/controller/BaseController.js.map +1 -0
  16. package/app/dashboard/controller/BaseController.ts +88 -0
  17. package/app/dashboard/controller/Cache-dbg.controller.js +421 -0
  18. package/app/dashboard/controller/Cache-dbg.controller.js.map +1 -0
  19. package/app/dashboard/controller/Cache.controller.js +2 -0
  20. package/app/dashboard/controller/Cache.controller.js.map +1 -0
  21. package/app/dashboard/controller/Cache.controller.ts +490 -0
  22. package/app/dashboard/controller/Main-dbg.controller.js +32 -0
  23. package/app/dashboard/controller/Main-dbg.controller.js.map +1 -0
  24. package/app/dashboard/controller/Main.controller.js +2 -0
  25. package/app/dashboard/controller/Main.controller.js.map +1 -0
  26. package/app/dashboard/controller/Main.controller.ts +31 -0
  27. package/app/dashboard/controller/SingleMetric-dbg.controller.js +306 -0
  28. package/app/dashboard/controller/SingleMetric-dbg.controller.js.map +1 -0
  29. package/app/dashboard/controller/SingleMetric.controller.js +2 -0
  30. package/app/dashboard/controller/SingleMetric.controller.js.map +1 -0
  31. package/app/dashboard/controller/SingleMetric.controller.ts +335 -0
  32. package/app/dashboard/i18n/i18n.properties +61 -0
  33. package/app/dashboard/i18n/i18n_de.properties +3 -0
  34. package/app/dashboard/i18n/i18n_en.properties +3 -0
  35. package/app/dashboard/index-cdn.html +28 -0
  36. package/app/dashboard/index.html +19 -0
  37. package/app/dashboard/manifest.json +145 -0
  38. package/app/dashboard/model/formatter-dbg.js +253 -0
  39. package/app/dashboard/model/formatter-dbg.js.map +1 -0
  40. package/app/dashboard/model/formatter.js +2 -0
  41. package/app/dashboard/model/formatter.js.map +1 -0
  42. package/app/dashboard/model/formatter.ts +275 -0
  43. package/app/dashboard/model/models-dbg.js +13 -0
  44. package/app/dashboard/model/models-dbg.js.map +1 -0
  45. package/app/dashboard/model/models.js +2 -0
  46. package/app/dashboard/model/models.js.map +1 -0
  47. package/app/dashboard/model/models.ts +13 -0
  48. package/app/dashboard/resources/sap-ui-custom-dbg.js +4695 -0
  49. package/app/dashboard/resources/sap-ui-custom-dbg.js.map +1 -0
  50. package/app/dashboard/resources/sap-ui-custom.js +5794 -0
  51. package/app/dashboard/resources/sap-ui-custom.js.map +1 -0
  52. package/app/dashboard/service/CacheStatisticsService-dbg.js +267 -0
  53. package/app/dashboard/service/CacheStatisticsService-dbg.js.map +1 -0
  54. package/app/dashboard/service/CacheStatisticsService.js +2 -0
  55. package/app/dashboard/service/CacheStatisticsService.js.map +1 -0
  56. package/app/dashboard/service/CacheStatisticsService.ts +397 -0
  57. package/app/dashboard/view/App.view.xml +18 -0
  58. package/app/dashboard/view/Cache.view.xml +777 -0
  59. package/app/dashboard/view/Main.view.xml +57 -0
  60. package/app/dashboard/view/SingleMetric.view.xml +337 -0
  61. package/cds-plugin.js +52 -0
  62. package/db/cache-store.cds +12 -0
  63. package/db/statistics.cds +128 -0
  64. package/index.cds +2 -128
  65. package/lib/CachingService.js +13 -0
  66. package/lib/add.js +17 -0
  67. package/lib/operations/AsyncOperations.js +162 -111
  68. package/lib/operations/BasicOperations.js +35 -0
  69. package/lib/operations/CapOperations.js +92 -40
  70. package/lib/support/CacheStatisticsHandler.js +35 -10
  71. package/lib/support/CacheStoreManager.js +29 -0
  72. package/lib/support/KeyvCDS.js +149 -0
  73. package/lib/support/MultitenancyDetector.js +25 -0
  74. package/lib/support/RuntimeConfigurationManager.js +69 -37
  75. package/lib/support/StatisticsPersistenceManager.js +18 -2
  76. package/lib/support/Telemetry.js +137 -0
  77. package/lib/util.js +29 -11
  78. package/package.json +44 -12
  79. package/srv/caching-api-service.js +47 -2
@@ -0,0 +1,267 @@
1
+ sap.ui.define(["sap/m/MessageBox", "sap/ui/model/odata/v4/ODataModel"], function (MessageBox, ODataModel) {
2
+ "use strict";
3
+
4
+ /**
5
+ * Service class for interacting with the Cache Statistics API using OData V4
6
+ */
7
+ class CacheStatisticsService {
8
+ constructor(model) {
9
+ this.model = model || new ODataModel({
10
+ serviceUrl: "/odata/v4/caching/",
11
+ autoExpandSelect: true,
12
+ groupId: "$auto"
13
+ });
14
+ }
15
+
16
+ /**
17
+ * Get the OData model instance
18
+ */
19
+ getModel() {
20
+ return this.model;
21
+ }
22
+
23
+ /**
24
+ * Get current cache metrics using entity set
25
+ */
26
+ async getCurrentMetrics(cacheName) {
27
+ try {
28
+ const binding = this.model.bindList("/Metrics", undefined, undefined, undefined, {
29
+ $filter: `period eq 'hourly' and cache eq '${cacheName}'`,
30
+ $orderby: "timestamp desc"
31
+ });
32
+ const data = await binding.requestContexts();
33
+ const results = data.map(item => item.getObject());
34
+ if (results && results.length > 0) {
35
+ return this.transformStatistics(results[0]);
36
+ } else {
37
+ return null;
38
+ }
39
+ } catch (error) {
40
+ console.error("Error fetching current metrics:", error);
41
+ MessageBox.error("Failed to load current metrics");
42
+ return null;
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Get historical metrics using entity set
48
+ */
49
+ async getHistoricalMetrics(cacheName, period = "hourly", from, to) {
50
+ try {
51
+ let filter = `period eq '${period}' and cache eq '${cacheName}'`;
52
+ if (from) {
53
+ filter += ` and timestamp ge ${from}`;
54
+ }
55
+ if (to) {
56
+ filter += ` and timestamp le ${to}`;
57
+ }
58
+ const binding = this.model.bindList("/Metrics", undefined, undefined, undefined, {
59
+ $filter: filter,
60
+ $orderby: "timestamp desc"
61
+ });
62
+ const data = await binding.requestContexts();
63
+ return data.map(item => item.getObject());
64
+ } catch (error) {
65
+ console.error("Error fetching historical metrics:", error);
66
+ MessageBox.error("Failed to load historical metrics");
67
+ return [];
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Get top accessed keys using entity set
73
+ */
74
+ async getTopKeys(cacheName, limit = 10) {
75
+ try {
76
+ const binding = this.model.bindList("/KeyMetrics", undefined, undefined, undefined, {
77
+ $filter: `period eq 'current' and cache eq '${cacheName}'`,
78
+ $orderby: "totalRequests desc"
79
+ });
80
+ const data = await binding.requestContexts();
81
+ return data.map(item => item.getObject());
82
+ } catch (error) {
83
+ console.error("Error fetching top keys:", error);
84
+ MessageBox.error("Failed to load top keys");
85
+ return [];
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Get cold keys using entity set
91
+ */
92
+ async getColdKeys(cacheName, limit = 10) {
93
+ try {
94
+ const binding = this.model.bindList("/KeyMetrics", undefined, undefined, undefined, {
95
+ $filter: `period eq 'current' and cache eq '${cacheName}'`,
96
+ $orderby: "lastAccess asc"
97
+ });
98
+ const data = await binding.requestContexts();
99
+ return data.map(item => item.getObject());
100
+ } catch (error) {
101
+ console.error("Error fetching cold keys:", error);
102
+ MessageBox.error("Failed to load cold keys");
103
+ return [];
104
+ }
105
+ }
106
+
107
+ /**
108
+ * Persist statistics using action
109
+ */
110
+ async persistStatistics(cacheName) {
111
+ try {
112
+ // For actions, we'll use a simple approach with the model's submitBatch
113
+ const context = this.model.bindContext("/persistStatistics(...)");
114
+ return new Promise((resolve, reject) => {
115
+ // Execute the action
116
+ context.execute().then(() => {
117
+ resolve(true);
118
+ }).catch(error => {
119
+ console.error("Error persisting statistics:", error);
120
+ MessageBox.error("Failed to persist statistics");
121
+ reject(error);
122
+ });
123
+ });
124
+ } catch (error) {
125
+ console.error("Error persisting statistics:", error);
126
+ MessageBox.error("Failed to persist statistics");
127
+ return false;
128
+ }
129
+ }
130
+
131
+ /**
132
+ * Transform statistics data from API format to internal format
133
+ */
134
+ transformStatistics(data) {
135
+ return {
136
+ hits: data.hits || 0,
137
+ misses: data.misses || 0,
138
+ sets: data.sets || 0,
139
+ deletes: data.deletes || 0,
140
+ errors: data.errors || 0,
141
+ // Overall latency metrics
142
+ avgLatency: data.avgLatency || 0,
143
+ p95Latency: data.p95Latency || 0,
144
+ p99Latency: data.p99Latency || 0,
145
+ minLatency: data.minLatency || 0,
146
+ maxLatency: data.maxLatency || 0,
147
+ // Hit-specific latency metrics
148
+ avgHitLatency: data.avgHitLatency || 0,
149
+ p95HitLatency: data.p95HitLatency || 0,
150
+ p99HitLatency: data.p99HitLatency || 0,
151
+ minHitLatency: data.minHitLatency || 0,
152
+ maxHitLatency: data.maxHitLatency || 0,
153
+ // Miss-specific latency metrics
154
+ avgMissLatency: data.avgMissLatency || 0,
155
+ p95MissLatency: data.p95MissLatency || 0,
156
+ p99MissLatency: data.p99MissLatency || 0,
157
+ minMissLatency: data.minMissLatency || 0,
158
+ maxMissLatency: data.maxMissLatency || 0,
159
+ // Set/Delete latency metrics
160
+ avgSetLatency: data.avgSetLatency || 0,
161
+ avgDeleteLatency: data.avgDeleteLatency || 0,
162
+ // Performance metrics
163
+ memoryUsage: data.memoryUsage || 0,
164
+ itemCount: data.itemCount || 0,
165
+ hitRatio: data.hitRatio || 0,
166
+ throughput: data.throughput || 0,
167
+ errorRate: data.errorRate || 0,
168
+ cacheEfficiency: data.cacheEfficiency || 0,
169
+ uptimeMs: data.uptimeMs || 0,
170
+ uniqueKeys: 0,
171
+ topKeys: [],
172
+ coldKeys: [],
173
+ lastPersisted: data.lastPersisted || new Date().toISOString()
174
+ };
175
+ }
176
+
177
+ /**
178
+ * Get all available metrics for a cache
179
+ */
180
+ async getAvailableMetrics(cacheName) {
181
+ try {
182
+ const binding = this.model.bindList("/Metrics", undefined, undefined, undefined, {
183
+ $filter: `cache eq '${cacheName}'`,
184
+ $orderby: "timestamp desc"
185
+ });
186
+ const data = await binding.requestContexts();
187
+ return data.map(item => item.getObject());
188
+ } catch (error) {
189
+ console.error("Error fetching available metrics:", error);
190
+ MessageBox.error("Failed to load available metrics");
191
+ return [];
192
+ }
193
+ }
194
+
195
+ /**
196
+ * Get a specific metric by ID
197
+ */
198
+ async getMetricById(cacheName, metricId) {
199
+ try {
200
+ const binding = this.model.bindList("/Metrics", undefined, undefined, undefined, {
201
+ $filter: `ID eq '${metricId}' and cache eq '${cacheName}'`
202
+ });
203
+ const data = await binding.requestContexts();
204
+ const results = data.map(item => item.getObject());
205
+ if (results && results.length > 0) {
206
+ return this.transformStatistics(results[0]);
207
+ } else {
208
+ return null;
209
+ }
210
+ } catch (error) {
211
+ console.error("Error fetching metric by ID:", error);
212
+ MessageBox.error("Failed to load metric");
213
+ return null;
214
+ }
215
+ }
216
+
217
+ /**
218
+ * Set metrics enabled/disabled
219
+ */
220
+ async setMetricsEnabled(cacheName, enabled) {
221
+ try {
222
+ const context = this.model.bindContext(`/setMetricsEnabled(...)`);
223
+ context.setParameter("cache", cacheName);
224
+ context.setParameter("enabled", enabled);
225
+ return new Promise((resolve, reject) => {
226
+ context.execute().then(() => {
227
+ resolve(true);
228
+ }).catch(error => {
229
+ console.error("Error setting metrics enabled:", error);
230
+ MessageBox.error("Failed to update metrics configuration");
231
+ reject(error);
232
+ });
233
+ });
234
+ } catch (error) {
235
+ console.error("Error setting metrics enabled:", error);
236
+ MessageBox.error("Failed to update metrics configuration");
237
+ return false;
238
+ }
239
+ }
240
+
241
+ /**
242
+ * Set key metrics enabled/disabled
243
+ */
244
+ async setKeyMetricsEnabled(cacheName, enabled) {
245
+ try {
246
+ const context = this.model.bindContext(`/setKeyMetricsEnabled(...)`);
247
+ context.setParameter("cache", cacheName);
248
+ context.setParameter("enabled", enabled);
249
+ return new Promise((resolve, reject) => {
250
+ context.execute().then(() => {
251
+ resolve(true);
252
+ }).catch(error => {
253
+ console.error("Error setting key metrics enabled:", error);
254
+ MessageBox.error("Failed to update key metrics configuration");
255
+ reject(error);
256
+ });
257
+ });
258
+ } catch (error) {
259
+ console.error("Error setting key metrics enabled:", error);
260
+ MessageBox.error("Failed to update key metrics configuration");
261
+ return false;
262
+ }
263
+ }
264
+ }
265
+ return CacheStatisticsService;
266
+ });
267
+ //# sourceMappingURL=CacheStatisticsService-dbg.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CacheStatisticsService-dbg.js","names":["CacheStatisticsService","constructor","model","ODataModel","serviceUrl","autoExpandSelect","groupId","getModel","getCurrentMetrics","cacheName","binding","bindList","undefined","$filter","$orderby","data","requestContexts","results","map","item","getObject","length","transformStatistics","error","console","MessageBox","getHistoricalMetrics","period","from","to","filter","getTopKeys","limit","getColdKeys","persistStatistics","context","bindContext","Promise","resolve","reject","execute","then","catch","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\";\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 // Read-through metrics (high value with latencies)\n hits: number;\n misses: number;\n sets: number;\n deletes: number;\n errors: number;\n totalRequests: number;\n\n // Read-through latency metrics\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 // Read-through performance metrics\n hitRatio: number;\n throughput: number;\n errorRate: number;\n cacheEfficiency: number;\n\n // Native function metrics (basic counts only)\n nativeSets: number;\n nativeGets: number;\n nativeDeletes: number;\n nativeClears: number;\n nativeDeleteByTags: number;\n nativeErrors: number;\n totalNativeOperations: number;\n\n // Native function performance metrics\n nativeThroughput: number;\n nativeErrorRate: number;\n\n // Common metrics\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 /**\n * Get the OData model instance\n */\n getModel(): ODataModel {\n return this.model;\n }\n\n /**\n * Get current cache metrics using entity set\n */\n async getCurrentMetrics(cacheName: string): Promise<CacheStatistics | null> {\n try {\n const binding = this.model.bindList(\"/Metrics\", undefined, undefined, undefined, {\n $filter: `period eq 'hourly' and cache eq '${cacheName}'`,\n $orderby: \"timestamp desc\"\n });\n\n const data = await binding.requestContexts();\n const results = data.map((item: any) => item.getObject());\n\n if (results && results.length > 0) {\n return this.transformStatistics(results[0]);\n } else {\n return null;\n }\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 /**\n * Get historical metrics using entity set\n */\n async getHistoricalMetrics(cacheName: string, period: string = \"hourly\", from?: string, to?: string): Promise<HistoricalStatistics[]> {\n try {\n let filter = `period eq '${period}' and cache eq '${cacheName}'`;\n if (from) {\n filter += ` and timestamp ge ${from}`;\n }\n if (to) {\n filter += ` and timestamp le ${to}`;\n }\n\n const binding = this.model.bindList(\"/Metrics\", undefined, undefined, undefined, {\n $filter: filter,\n $orderby: \"timestamp desc\"\n });\n\n const data = await binding.requestContexts();\n return data.map((item: any) => 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 /**\n * Get top accessed keys using entity set\n */\n async getTopKeys(cacheName: string, limit: number = 10): Promise<KeyAccess[]> {\n try {\n const binding = this.model.bindList(\"/KeyMetrics\", undefined, undefined, undefined, {\n $filter: `period eq 'current' and cache eq '${cacheName}'`,\n $orderby: \"totalRequests desc\"\n });\n\n const data = await binding.requestContexts();\n return data.map((item: any) => 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 /**\n * Get cold keys using entity set\n */\n async getColdKeys(cacheName: string, limit: number = 10): Promise<KeyAccess[]> {\n try {\n const binding = this.model.bindList(\"/KeyMetrics\", undefined, undefined, undefined, {\n $filter: `period eq 'current' and cache eq '${cacheName}'`,\n $orderby: \"lastAccess asc\"\n });\n\n const data = await binding.requestContexts();\n return data.map((item: any) => 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 /**\n * Persist statistics using action\n */\n async persistStatistics(cacheName: string): Promise<boolean> {\n try {\n // For actions, we'll use a simple approach with the model's submitBatch\n const context = this.model.bindContext(\"/persistStatistics(...)\");\n\n return new Promise((resolve, reject) => {\n // Execute the action\n context.execute().then(() => {\n resolve(true);\n }).catch((error: any) => {\n console.error(\"Error persisting statistics:\", error);\n MessageBox.error(\"Failed to persist statistics\");\n reject(error);\n });\n });\n } catch (error) {\n console.error(\"Error persisting statistics:\", error);\n MessageBox.error(\"Failed to persist statistics\");\n return false;\n }\n }\n\n /**\n * Transform statistics data from API format to internal format\n */\n private transformStatistics(data: any): CacheStatistics {\n return {\n hits: data.hits || 0,\n misses: data.misses || 0,\n sets: data.sets || 0,\n deletes: data.deletes || 0,\n errors: data.errors || 0,\n\n // Overall latency metrics\n avgLatency: data.avgLatency || 0,\n p95Latency: data.p95Latency || 0,\n p99Latency: data.p99Latency || 0,\n minLatency: data.minLatency || 0,\n maxLatency: data.maxLatency || 0,\n\n // Hit-specific latency metrics\n avgHitLatency: data.avgHitLatency || 0,\n p95HitLatency: data.p95HitLatency || 0,\n p99HitLatency: data.p99HitLatency || 0,\n minHitLatency: data.minHitLatency || 0,\n maxHitLatency: data.maxHitLatency || 0,\n\n // Miss-specific latency metrics\n avgMissLatency: data.avgMissLatency || 0,\n p95MissLatency: data.p95MissLatency || 0,\n p99MissLatency: data.p99MissLatency || 0,\n minMissLatency: data.minMissLatency || 0,\n maxMissLatency: data.maxMissLatency || 0,\n\n // Set/Delete latency metrics\n avgSetLatency: data.avgSetLatency || 0,\n avgDeleteLatency: data.avgDeleteLatency || 0,\n\n // Performance metrics\n memoryUsage: data.memoryUsage || 0,\n itemCount: data.itemCount || 0,\n hitRatio: data.hitRatio || 0,\n throughput: data.throughput || 0,\n errorRate: data.errorRate || 0,\n cacheEfficiency: data.cacheEfficiency || 0,\n uptimeMs: data.uptimeMs || 0,\n uniqueKeys: 0,\n topKeys: [],\n coldKeys: [],\n lastPersisted: data.lastPersisted || new Date().toISOString()\n };\n }\n\n /**\n * Get all available metrics for a cache\n */\n async getAvailableMetrics(cacheName: string): Promise<any[]> {\n try {\n const binding = this.model.bindList(\"/Metrics\", undefined, undefined, undefined, {\n $filter: `cache eq '${cacheName}'`,\n $orderby: \"timestamp desc\"\n });\n\n const data = await binding.requestContexts();\n return data.map((item: any) => 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 /**\n * Get a specific metric by ID\n */\n async getMetricById(cacheName: string, metricId: string): Promise<CacheStatistics | null> {\n try {\n const binding = this.model.bindList(\"/Metrics\", undefined, undefined, undefined, {\n $filter: `ID eq '${metricId}' and cache eq '${cacheName}'`\n });\n\n const data = await binding.requestContexts();\n const results = data.map((item: any) => item.getObject());\n\n if (results && results.length > 0) {\n return this.transformStatistics(results[0]);\n } else {\n return null;\n }\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 /**\n * Set metrics enabled/disabled\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 \n return new Promise((resolve, reject) => {\n context.execute().then(() => {\n resolve(true);\n }).catch((error: any) => {\n console.error(\"Error setting metrics enabled:\", error);\n MessageBox.error(\"Failed to update metrics configuration\");\n reject(error);\n });\n });\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 /**\n * Set key metrics enabled/disabled\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 \n return new Promise((resolve, reject) => {\n context.execute().then(() => {\n resolve(true);\n }).catch((error: any) => {\n console.error(\"Error setting key metrics enabled:\", error);\n MessageBox.error(\"Failed to update key metrics configuration\");\n reject(error);\n });\n });\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} "],"mappings":";;;EAqHA;AACA;AACA;EACe,MAAMA,sBAAsB,CAAC;IAGxCC,WAAWA,CAACC,KAAkB,EAAE;MAC5B,IAAI,CAACA,KAAK,GAAGA,KAAK,IAAI,IAAIC,UAAU,CAAC;QACjCC,UAAU,EAAE,oBAAoB;QAChCC,gBAAgB,EAAE,IAAI;QACtBC,OAAO,EAAE;MACb,CAAC,CAAC;IACN;;IAEA;AACJ;AACA;IACIC,QAAQA,CAAA,EAAe;MACnB,OAAO,IAAI,CAACL,KAAK;IACrB;;IAEA;AACJ;AACA;IACI,MAAMM,iBAAiBA,CAACC,SAAiB,EAAmC;MACxE,IAAI;QACA,MAAMC,OAAO,GAAG,IAAI,CAACR,KAAK,CAACS,QAAQ,CAAC,UAAU,EAAEC,SAAS,EAAEA,SAAS,EAAEA,SAAS,EAAE;UAC7EC,OAAO,EAAE,oCAAoCJ,SAAS,GAAG;UACzDK,QAAQ,EAAE;QACd,CAAC,CAAC;QAEF,MAAMC,IAAI,GAAG,MAAML,OAAO,CAACM,eAAe,CAAC,CAAC;QAC5C,MAAMC,OAAO,GAAGF,IAAI,CAACG,GAAG,CAAEC,IAAS,IAAKA,IAAI,CAACC,SAAS,CAAC,CAAC,CAAC;QAEzD,IAAIH,OAAO,IAAIA,OAAO,CAACI,MAAM,GAAG,CAAC,EAAE;UAC/B,OAAO,IAAI,CAACC,mBAAmB,CAACL,OAAO,CAAC,CAAC,CAAC,CAAC;QAC/C,CAAC,MAAM;UACH,OAAO,IAAI;QACf;MACJ,CAAC,CAAC,OAAOM,KAAK,EAAE;QACZC,OAAO,CAACD,KAAK,CAAC,iCAAiC,EAAEA,KAAK,CAAC;QACvDE,UAAU,CAACF,KAAK,CAAC,gCAAgC,CAAC;QAClD,OAAO,IAAI;MACf;IACJ;;IAEA;AACJ;AACA;IACI,MAAMG,oBAAoBA,CAACjB,SAAiB,EAAEkB,MAAc,GAAG,QAAQ,EAAEC,IAAa,EAAEC,EAAW,EAAmC;MAClI,IAAI;QACA,IAAIC,MAAM,GAAG,cAAcH,MAAM,mBAAmBlB,SAAS,GAAG;QAChE,IAAImB,IAAI,EAAE;UACNE,MAAM,IAAI,qBAAqBF,IAAI,EAAE;QACzC;QACA,IAAIC,EAAE,EAAE;UACJC,MAAM,IAAI,qBAAqBD,EAAE,EAAE;QACvC;QAEA,MAAMnB,OAAO,GAAG,IAAI,CAACR,KAAK,CAACS,QAAQ,CAAC,UAAU,EAAEC,SAAS,EAAEA,SAAS,EAAEA,SAAS,EAAE;UAC7EC,OAAO,EAAEiB,MAAM;UACfhB,QAAQ,EAAE;QACd,CAAC,CAAC;QAEF,MAAMC,IAAI,GAAG,MAAML,OAAO,CAACM,eAAe,CAAC,CAAC;QAC5C,OAAOD,IAAI,CAACG,GAAG,CAAEC,IAAS,IAAKA,IAAI,CAACC,SAAS,CAAC,CAAC,CAAC;MACpD,CAAC,CAAC,OAAOG,KAAK,EAAE;QACZC,OAAO,CAACD,KAAK,CAAC,oCAAoC,EAAEA,KAAK,CAAC;QAC1DE,UAAU,CAACF,KAAK,CAAC,mCAAmC,CAAC;QACrD,OAAO,EAAE;MACb;IACJ;;IAEA;AACJ;AACA;IACI,MAAMQ,UAAUA,CAACtB,SAAiB,EAAEuB,KAAa,GAAG,EAAE,EAAwB;MAC1E,IAAI;QACA,MAAMtB,OAAO,GAAG,IAAI,CAACR,KAAK,CAACS,QAAQ,CAAC,aAAa,EAAEC,SAAS,EAAEA,SAAS,EAAEA,SAAS,EAAE;UAChFC,OAAO,EAAE,qCAAqCJ,SAAS,GAAG;UAC1DK,QAAQ,EAAE;QACd,CAAC,CAAC;QAEF,MAAMC,IAAI,GAAG,MAAML,OAAO,CAACM,eAAe,CAAC,CAAC;QAC5C,OAAOD,IAAI,CAACG,GAAG,CAAEC,IAAS,IAAKA,IAAI,CAACC,SAAS,CAAC,CAAC,CAAC;MACpD,CAAC,CAAC,OAAOG,KAAK,EAAE;QACZC,OAAO,CAACD,KAAK,CAAC,0BAA0B,EAAEA,KAAK,CAAC;QAChDE,UAAU,CAACF,KAAK,CAAC,yBAAyB,CAAC;QAC3C,OAAO,EAAE;MACb;IACJ;;IAEA;AACJ;AACA;IACI,MAAMU,WAAWA,CAACxB,SAAiB,EAAEuB,KAAa,GAAG,EAAE,EAAwB;MAC3E,IAAI;QACA,MAAMtB,OAAO,GAAG,IAAI,CAACR,KAAK,CAACS,QAAQ,CAAC,aAAa,EAAEC,SAAS,EAAEA,SAAS,EAAEA,SAAS,EAAE;UAChFC,OAAO,EAAE,qCAAqCJ,SAAS,GAAG;UAC1DK,QAAQ,EAAE;QACd,CAAC,CAAC;QAEF,MAAMC,IAAI,GAAG,MAAML,OAAO,CAACM,eAAe,CAAC,CAAC;QAC5C,OAAOD,IAAI,CAACG,GAAG,CAAEC,IAAS,IAAKA,IAAI,CAACC,SAAS,CAAC,CAAC,CAAC;MACpD,CAAC,CAAC,OAAOG,KAAK,EAAE;QACZC,OAAO,CAACD,KAAK,CAAC,2BAA2B,EAAEA,KAAK,CAAC;QACjDE,UAAU,CAACF,KAAK,CAAC,0BAA0B,CAAC;QAC5C,OAAO,EAAE;MACb;IACJ;;IAEA;AACJ;AACA;IACI,MAAMW,iBAAiBA,CAACzB,SAAiB,EAAoB;MACzD,IAAI;QACA;QACA,MAAM0B,OAAO,GAAG,IAAI,CAACjC,KAAK,CAACkC,WAAW,CAAC,yBAAyB,CAAC;QAEjE,OAAO,IAAIC,OAAO,CAAC,CAACC,OAAO,EAAEC,MAAM,KAAK;UACpC;UACAJ,OAAO,CAACK,OAAO,CAAC,CAAC,CAACC,IAAI,CAAC,MAAM;YACzBH,OAAO,CAAC,IAAI,CAAC;UACjB,CAAC,CAAC,CAACI,KAAK,CAAEnB,KAAU,IAAK;YACrBC,OAAO,CAACD,KAAK,CAAC,8BAA8B,EAAEA,KAAK,CAAC;YACpDE,UAAU,CAACF,KAAK,CAAC,8BAA8B,CAAC;YAChDgB,MAAM,CAAChB,KAAK,CAAC;UACjB,CAAC,CAAC;QACN,CAAC,CAAC;MACN,CAAC,CAAC,OAAOA,KAAK,EAAE;QACZC,OAAO,CAACD,KAAK,CAAC,8BAA8B,EAAEA,KAAK,CAAC;QACpDE,UAAU,CAACF,KAAK,CAAC,8BAA8B,CAAC;QAChD,OAAO,KAAK;MAChB;IACJ;;IAEA;AACJ;AACA;IACYD,mBAAmBA,CAACP,IAAS,EAAmB;MACpD,OAAO;QACH4B,IAAI,EAAE5B,IAAI,CAAC4B,IAAI,IAAI,CAAC;QACpBC,MAAM,EAAE7B,IAAI,CAAC6B,MAAM,IAAI,CAAC;QACxBC,IAAI,EAAE9B,IAAI,CAAC8B,IAAI,IAAI,CAAC;QACpBC,OAAO,EAAE/B,IAAI,CAAC+B,OAAO,IAAI,CAAC;QAC1BC,MAAM,EAAEhC,IAAI,CAACgC,MAAM,IAAI,CAAC;QAExB;QACAC,UAAU,EAAEjC,IAAI,CAACiC,UAAU,IAAI,CAAC;QAChCC,UAAU,EAAElC,IAAI,CAACkC,UAAU,IAAI,CAAC;QAChCC,UAAU,EAAEnC,IAAI,CAACmC,UAAU,IAAI,CAAC;QAChCC,UAAU,EAAEpC,IAAI,CAACoC,UAAU,IAAI,CAAC;QAChCC,UAAU,EAAErC,IAAI,CAACqC,UAAU,IAAI,CAAC;QAEhC;QACAC,aAAa,EAAEtC,IAAI,CAACsC,aAAa,IAAI,CAAC;QACtCC,aAAa,EAAEvC,IAAI,CAACuC,aAAa,IAAI,CAAC;QACtCC,aAAa,EAAExC,IAAI,CAACwC,aAAa,IAAI,CAAC;QACtCC,aAAa,EAAEzC,IAAI,CAACyC,aAAa,IAAI,CAAC;QACtCC,aAAa,EAAE1C,IAAI,CAAC0C,aAAa,IAAI,CAAC;QAEtC;QACAC,cAAc,EAAE3C,IAAI,CAAC2C,cAAc,IAAI,CAAC;QACxCC,cAAc,EAAE5C,IAAI,CAAC4C,cAAc,IAAI,CAAC;QACxCC,cAAc,EAAE7C,IAAI,CAAC6C,cAAc,IAAI,CAAC;QACxCC,cAAc,EAAE9C,IAAI,CAAC8C,cAAc,IAAI,CAAC;QACxCC,cAAc,EAAE/C,IAAI,CAAC+C,cAAc,IAAI,CAAC;QAExC;QACAC,aAAa,EAAEhD,IAAI,CAACgD,aAAa,IAAI,CAAC;QACtCC,gBAAgB,EAAEjD,IAAI,CAACiD,gBAAgB,IAAI,CAAC;QAE5C;QACAC,WAAW,EAAElD,IAAI,CAACkD,WAAW,IAAI,CAAC;QAClCC,SAAS,EAAEnD,IAAI,CAACmD,SAAS,IAAI,CAAC;QAC9BC,QAAQ,EAAEpD,IAAI,CAACoD,QAAQ,IAAI,CAAC;QAC5BC,UAAU,EAAErD,IAAI,CAACqD,UAAU,IAAI,CAAC;QAChCC,SAAS,EAAEtD,IAAI,CAACsD,SAAS,IAAI,CAAC;QAC9BC,eAAe,EAAEvD,IAAI,CAACuD,eAAe,IAAI,CAAC;QAC1CC,QAAQ,EAAExD,IAAI,CAACwD,QAAQ,IAAI,CAAC;QAC5BC,UAAU,EAAE,CAAC;QACbC,OAAO,EAAE,EAAE;QACXC,QAAQ,EAAE,EAAE;QACZC,aAAa,EAAE5D,IAAI,CAAC4D,aAAa,IAAI,IAAIC,IAAI,CAAC,CAAC,CAACC,WAAW,CAAC;MAChE,CAAC;IACL;;IAEA;AACJ;AACA;IACI,MAAMC,mBAAmBA,CAACrE,SAAiB,EAAkB;MACzD,IAAI;QACA,MAAMC,OAAO,GAAG,IAAI,CAACR,KAAK,CAACS,QAAQ,CAAC,UAAU,EAAEC,SAAS,EAAEA,SAAS,EAAEA,SAAS,EAAE;UAC7EC,OAAO,EAAE,aAAaJ,SAAS,GAAG;UAClCK,QAAQ,EAAE;QACd,CAAC,CAAC;QAEF,MAAMC,IAAI,GAAG,MAAML,OAAO,CAACM,eAAe,CAAC,CAAC;QAC5C,OAAOD,IAAI,CAACG,GAAG,CAAEC,IAAS,IAAKA,IAAI,CAACC,SAAS,CAAC,CAAC,CAAC;MACpD,CAAC,CAAC,OAAOG,KAAK,EAAE;QACZC,OAAO,CAACD,KAAK,CAAC,mCAAmC,EAAEA,KAAK,CAAC;QACzDE,UAAU,CAACF,KAAK,CAAC,kCAAkC,CAAC;QACpD,OAAO,EAAE;MACb;IACJ;;IAEA;AACJ;AACA;IACI,MAAMwD,aAAaA,CAACtE,SAAiB,EAAEuE,QAAgB,EAAmC;MACtF,IAAI;QACA,MAAMtE,OAAO,GAAG,IAAI,CAACR,KAAK,CAACS,QAAQ,CAAC,UAAU,EAAEC,SAAS,EAAEA,SAAS,EAAEA,SAAS,EAAE;UAC7EC,OAAO,EAAE,UAAUmE,QAAQ,mBAAmBvE,SAAS;QAC3D,CAAC,CAAC;QAEF,MAAMM,IAAI,GAAG,MAAML,OAAO,CAACM,eAAe,CAAC,CAAC;QAC5C,MAAMC,OAAO,GAAGF,IAAI,CAACG,GAAG,CAAEC,IAAS,IAAKA,IAAI,CAACC,SAAS,CAAC,CAAC,CAAC;QAEzD,IAAIH,OAAO,IAAIA,OAAO,CAACI,MAAM,GAAG,CAAC,EAAE;UAC/B,OAAO,IAAI,CAACC,mBAAmB,CAACL,OAAO,CAAC,CAAC,CAAC,CAAC;QAC/C,CAAC,MAAM;UACH,OAAO,IAAI;QACf;MACJ,CAAC,CAAC,OAAOM,KAAK,EAAE;QACZC,OAAO,CAACD,KAAK,CAAC,8BAA8B,EAAEA,KAAK,CAAC;QACpDE,UAAU,CAACF,KAAK,CAAC,uBAAuB,CAAC;QACzC,OAAO,IAAI;MACf;IACJ;;IAEA;AACJ;AACA;IACI,MAAM0D,iBAAiBA,CAACxE,SAAiB,EAAEyE,OAAgB,EAAoB;MAC3E,IAAI;QACA,MAAM/C,OAAO,GAAG,IAAI,CAACjC,KAAK,CAACkC,WAAW,CAAC,yBAAyB,CAAC;QACjED,OAAO,CAACgD,YAAY,CAAC,OAAO,EAAE1E,SAAS,CAAC;QACxC0B,OAAO,CAACgD,YAAY,CAAC,SAAS,EAAED,OAAO,CAAC;QAExC,OAAO,IAAI7C,OAAO,CAAC,CAACC,OAAO,EAAEC,MAAM,KAAK;UACpCJ,OAAO,CAACK,OAAO,CAAC,CAAC,CAACC,IAAI,CAAC,MAAM;YACzBH,OAAO,CAAC,IAAI,CAAC;UACjB,CAAC,CAAC,CAACI,KAAK,CAAEnB,KAAU,IAAK;YACrBC,OAAO,CAACD,KAAK,CAAC,gCAAgC,EAAEA,KAAK,CAAC;YACtDE,UAAU,CAACF,KAAK,CAAC,wCAAwC,CAAC;YAC1DgB,MAAM,CAAChB,KAAK,CAAC;UACjB,CAAC,CAAC;QACN,CAAC,CAAC;MACN,CAAC,CAAC,OAAOA,KAAK,EAAE;QACZC,OAAO,CAACD,KAAK,CAAC,gCAAgC,EAAEA,KAAK,CAAC;QACtDE,UAAU,CAACF,KAAK,CAAC,wCAAwC,CAAC;QAC1D,OAAO,KAAK;MAChB;IACJ;;IAEA;AACJ;AACA;IACI,MAAM6D,oBAAoBA,CAAC3E,SAAiB,EAAEyE,OAAgB,EAAoB;MAC9E,IAAI;QACA,MAAM/C,OAAO,GAAG,IAAI,CAACjC,KAAK,CAACkC,WAAW,CAAC,4BAA4B,CAAC;QACpED,OAAO,CAACgD,YAAY,CAAC,OAAO,EAAE1E,SAAS,CAAC;QACxC0B,OAAO,CAACgD,YAAY,CAAC,SAAS,EAAED,OAAO,CAAC;QAExC,OAAO,IAAI7C,OAAO,CAAC,CAACC,OAAO,EAAEC,MAAM,KAAK;UACpCJ,OAAO,CAACK,OAAO,CAAC,CAAC,CAACC,IAAI,CAAC,MAAM;YACzBH,OAAO,CAAC,IAAI,CAAC;UACjB,CAAC,CAAC,CAACI,KAAK,CAAEnB,KAAU,IAAK;YACrBC,OAAO,CAACD,KAAK,CAAC,oCAAoC,EAAEA,KAAK,CAAC;YAC1DE,UAAU,CAACF,KAAK,CAAC,4CAA4C,CAAC;YAC9DgB,MAAM,CAAChB,KAAK,CAAC;UACjB,CAAC,CAAC;QACN,CAAC,CAAC;MACN,CAAC,CAAC,OAAOA,KAAK,EAAE;QACZC,OAAO,CAACD,KAAK,CAAC,oCAAoC,EAAEA,KAAK,CAAC;QAC1DE,UAAU,CAACF,KAAK,CAAC,4CAA4C,CAAC;QAC9D,OAAO,KAAK;MAChB;IACJ;EACJ;EAAC,OAAAvB,sBAAA;AAAA","ignoreList":[]}
@@ -0,0 +1,2 @@
1
+ sap.ui.define(["sap/m/MessageBox","sap/ui/model/odata/v4/ODataModel"],function(e,t){"use strict";class r{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,undefined,undefined,{$filter:`period eq 'hourly' and cache eq '${t}'`,$orderby:"timestamp desc"});const r=await e.requestContexts();const s=r.map(e=>e.getObject());if(s&&s.length>0){return this.transformStatistics(s[0])}else{return null}}catch(t){console.error("Error fetching current metrics:",t);e.error("Failed to load current metrics");return null}}async getHistoricalMetrics(t,r="hourly",s,n){try{let e=`period eq '${r}' and cache eq '${t}'`;if(s){e+=` and timestamp ge ${s}`}if(n){e+=` and timestamp le ${n}`}const i=this.model.bindList("/Metrics",undefined,undefined,undefined,{$filter:e,$orderby:"timestamp desc"});const a=await i.requestContexts();return a.map(e=>e.getObject())}catch(t){console.error("Error fetching historical metrics:",t);e.error("Failed to load historical metrics");return[]}}async getTopKeys(t,r=10){try{const e=this.model.bindList("/KeyMetrics",undefined,undefined,undefined,{$filter:`period eq 'current' and cache eq '${t}'`,$orderby:"totalRequests desc"});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,r=10){try{const e=this.model.bindList("/KeyMetrics",undefined,undefined,undefined,{$filter:`period eq 'current' and cache eq '${t}'`,$orderby:"lastAccess asc"});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(t){try{const t=this.model.bindContext("/persistStatistics(...)");return new Promise((r,s)=>{t.execute().then(()=>{r(true)}).catch(t=>{console.error("Error persisting statistics:",t);e.error("Failed to persist statistics");s(t)})})}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,undefined,undefined,{$filter:`cache eq '${t}'`,$orderby:"timestamp desc"});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,undefined,{$filter:`ID eq '${r}' and cache eq '${t}'`});const s=await e.requestContexts();const n=s.map(e=>e.getObject());if(n&&n.length>0){return this.transformStatistics(n[0])}else{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 s=this.model.bindContext(`/setMetricsEnabled(...)`);s.setParameter("cache",t);s.setParameter("enabled",r);return new Promise((t,r)=>{s.execute().then(()=>{t(true)}).catch(t=>{console.error("Error setting metrics enabled:",t);e.error("Failed to update metrics configuration");r(t)})})}catch(t){console.error("Error setting metrics enabled:",t);e.error("Failed to update metrics configuration");return false}}async setKeyMetricsEnabled(t,r){try{const s=this.model.bindContext(`/setKeyMetricsEnabled(...)`);s.setParameter("cache",t);s.setParameter("enabled",r);return new Promise((t,r)=>{s.execute().then(()=>{t(true)}).catch(t=>{console.error("Error setting key metrics enabled:",t);e.error("Failed to update key metrics configuration");r(t)})})}catch(t){console.error("Error setting key metrics enabled:",t);e.error("Failed to update key metrics configuration");return false}}}return r});
2
+ //# sourceMappingURL=CacheStatisticsService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CacheStatisticsService.js","names":["CacheStatisticsService","constructor","model","this","ODataModel","serviceUrl","autoExpandSelect","groupId","getModel","getCurrentMetrics","cacheName","binding","bindList","undefined","$filter","$orderby","data","requestContexts","results","map","item","getObject","length","transformStatistics","error","console","MessageBox","getHistoricalMetrics","period","from","to","filter","getTopKeys","limit","getColdKeys","persistStatistics","context","bindContext","Promise","resolve","reject","execute","then","catch","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\";\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 // Read-through metrics (high value with latencies)\n hits: number;\n misses: number;\n sets: number;\n deletes: number;\n errors: number;\n totalRequests: number;\n\n // Read-through latency metrics\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 // Read-through performance metrics\n hitRatio: number;\n throughput: number;\n errorRate: number;\n cacheEfficiency: number;\n\n // Native function metrics (basic counts only)\n nativeSets: number;\n nativeGets: number;\n nativeDeletes: number;\n nativeClears: number;\n nativeDeleteByTags: number;\n nativeErrors: number;\n totalNativeOperations: number;\n\n // Native function performance metrics\n nativeThroughput: number;\n nativeErrorRate: number;\n\n // Common metrics\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 /**\n * Get the OData model instance\n */\n getModel(): ODataModel {\n return this.model;\n }\n\n /**\n * Get current cache metrics using entity set\n */\n async getCurrentMetrics(cacheName: string): Promise<CacheStatistics | null> {\n try {\n const binding = this.model.bindList(\"/Metrics\", undefined, undefined, undefined, {\n $filter: `period eq 'hourly' and cache eq '${cacheName}'`,\n $orderby: \"timestamp desc\"\n });\n\n const data = await binding.requestContexts();\n const results = data.map((item: any) => item.getObject());\n\n if (results && results.length > 0) {\n return this.transformStatistics(results[0]);\n } else {\n return null;\n }\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 /**\n * Get historical metrics using entity set\n */\n async getHistoricalMetrics(cacheName: string, period: string = \"hourly\", from?: string, to?: string): Promise<HistoricalStatistics[]> {\n try {\n let filter = `period eq '${period}' and cache eq '${cacheName}'`;\n if (from) {\n filter += ` and timestamp ge ${from}`;\n }\n if (to) {\n filter += ` and timestamp le ${to}`;\n }\n\n const binding = this.model.bindList(\"/Metrics\", undefined, undefined, undefined, {\n $filter: filter,\n $orderby: \"timestamp desc\"\n });\n\n const data = await binding.requestContexts();\n return data.map((item: any) => 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 /**\n * Get top accessed keys using entity set\n */\n async getTopKeys(cacheName: string, limit: number = 10): Promise<KeyAccess[]> {\n try {\n const binding = this.model.bindList(\"/KeyMetrics\", undefined, undefined, undefined, {\n $filter: `period eq 'current' and cache eq '${cacheName}'`,\n $orderby: \"totalRequests desc\"\n });\n\n const data = await binding.requestContexts();\n return data.map((item: any) => 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 /**\n * Get cold keys using entity set\n */\n async getColdKeys(cacheName: string, limit: number = 10): Promise<KeyAccess[]> {\n try {\n const binding = this.model.bindList(\"/KeyMetrics\", undefined, undefined, undefined, {\n $filter: `period eq 'current' and cache eq '${cacheName}'`,\n $orderby: \"lastAccess asc\"\n });\n\n const data = await binding.requestContexts();\n return data.map((item: any) => 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 /**\n * Persist statistics using action\n */\n async persistStatistics(cacheName: string): Promise<boolean> {\n try {\n // For actions, we'll use a simple approach with the model's submitBatch\n const context = this.model.bindContext(\"/persistStatistics(...)\");\n\n return new Promise((resolve, reject) => {\n // Execute the action\n context.execute().then(() => {\n resolve(true);\n }).catch((error: any) => {\n console.error(\"Error persisting statistics:\", error);\n MessageBox.error(\"Failed to persist statistics\");\n reject(error);\n });\n });\n } catch (error) {\n console.error(\"Error persisting statistics:\", error);\n MessageBox.error(\"Failed to persist statistics\");\n return false;\n }\n }\n\n /**\n * Transform statistics data from API format to internal format\n */\n private transformStatistics(data: any): CacheStatistics {\n return {\n hits: data.hits || 0,\n misses: data.misses || 0,\n sets: data.sets || 0,\n deletes: data.deletes || 0,\n errors: data.errors || 0,\n\n // Overall latency metrics\n avgLatency: data.avgLatency || 0,\n p95Latency: data.p95Latency || 0,\n p99Latency: data.p99Latency || 0,\n minLatency: data.minLatency || 0,\n maxLatency: data.maxLatency || 0,\n\n // Hit-specific latency metrics\n avgHitLatency: data.avgHitLatency || 0,\n p95HitLatency: data.p95HitLatency || 0,\n p99HitLatency: data.p99HitLatency || 0,\n minHitLatency: data.minHitLatency || 0,\n maxHitLatency: data.maxHitLatency || 0,\n\n // Miss-specific latency metrics\n avgMissLatency: data.avgMissLatency || 0,\n p95MissLatency: data.p95MissLatency || 0,\n p99MissLatency: data.p99MissLatency || 0,\n minMissLatency: data.minMissLatency || 0,\n maxMissLatency: data.maxMissLatency || 0,\n\n // Set/Delete latency metrics\n avgSetLatency: data.avgSetLatency || 0,\n avgDeleteLatency: data.avgDeleteLatency || 0,\n\n // Performance metrics\n memoryUsage: data.memoryUsage || 0,\n itemCount: data.itemCount || 0,\n hitRatio: data.hitRatio || 0,\n throughput: data.throughput || 0,\n errorRate: data.errorRate || 0,\n cacheEfficiency: data.cacheEfficiency || 0,\n uptimeMs: data.uptimeMs || 0,\n uniqueKeys: 0,\n topKeys: [],\n coldKeys: [],\n lastPersisted: data.lastPersisted || new Date().toISOString()\n };\n }\n\n /**\n * Get all available metrics for a cache\n */\n async getAvailableMetrics(cacheName: string): Promise<any[]> {\n try {\n const binding = this.model.bindList(\"/Metrics\", undefined, undefined, undefined, {\n $filter: `cache eq '${cacheName}'`,\n $orderby: \"timestamp desc\"\n });\n\n const data = await binding.requestContexts();\n return data.map((item: any) => 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 /**\n * Get a specific metric by ID\n */\n async getMetricById(cacheName: string, metricId: string): Promise<CacheStatistics | null> {\n try {\n const binding = this.model.bindList(\"/Metrics\", undefined, undefined, undefined, {\n $filter: `ID eq '${metricId}' and cache eq '${cacheName}'`\n });\n\n const data = await binding.requestContexts();\n const results = data.map((item: any) => item.getObject());\n\n if (results && results.length > 0) {\n return this.transformStatistics(results[0]);\n } else {\n return null;\n }\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 /**\n * Set metrics enabled/disabled\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 \n return new Promise((resolve, reject) => {\n context.execute().then(() => {\n resolve(true);\n }).catch((error: any) => {\n console.error(\"Error setting metrics enabled:\", error);\n MessageBox.error(\"Failed to update metrics configuration\");\n reject(error);\n });\n });\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 /**\n * Set key metrics enabled/disabled\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 \n return new Promise((resolve, reject) => {\n context.execute().then(() => {\n resolve(true);\n }).catch((error: any) => {\n console.error(\"Error setting key metrics enabled:\", error);\n MessageBox.error(\"Failed to update key metrics configuration\");\n reject(error);\n });\n });\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} "],"mappings":"iGAwHe,MAAMA,EAGjBC,YAAYC,GACRC,KAAKD,MAAQA,GAAS,IAAIE,EAAW,CACjCC,WAAY,qBACZC,iBAAkB,KAClBC,QAAS,SAEjB,CAKAC,WACI,OAAOL,KAAKD,KAChB,CAKA,uBAAMO,CAAkBC,GACpB,IACI,MAAMC,EAAUR,KAAKD,MAAMU,SAAS,WAAYC,UAAWA,UAAWA,UAAW,CAC7EC,QAAS,oCAAoCJ,KAC7CK,SAAU,mBAGd,MAAMC,QAAaL,EAAQM,kBAC3B,MAAMC,EAAUF,EAAKG,IAAKC,GAAcA,EAAKC,aAE7C,GAAIH,GAAWA,EAAQI,OAAS,EAAG,CAC/B,OAAOnB,KAAKoB,oBAAoBL,EAAQ,GAC5C,KAAO,CACH,OAAO,IACX,CACJ,CAAE,MAAOM,GACLC,QAAQD,MAAM,kCAAmCA,GACjDE,EAAWF,MAAM,kCACjB,OAAO,IACX,CACJ,CAKA,0BAAMG,CAAqBjB,EAAmBkB,EAAiB,SAAUC,EAAeC,GACpF,IACI,IAAIC,EAAS,cAAcH,oBAAyBlB,KACpD,GAAImB,EAAM,CACNE,GAAU,qBAAqBF,GACnC,CACA,GAAIC,EAAI,CACJC,GAAU,qBAAqBD,GACnC,CAEA,MAAMnB,EAAUR,KAAKD,MAAMU,SAAS,WAAYC,UAAWA,UAAWA,UAAW,CAC7EC,QAASiB,EACThB,SAAU,mBAGd,MAAMC,QAAaL,EAAQM,kBAC3B,OAAOD,EAAKG,IAAKC,GAAcA,EAAKC,YACxC,CAAE,MAAOG,GACLC,QAAQD,MAAM,qCAAsCA,GACpDE,EAAWF,MAAM,qCACjB,MAAO,EACX,CACJ,CAKA,gBAAMQ,CAAWtB,EAAmBuB,EAAgB,IAChD,IACI,MAAMtB,EAAUR,KAAKD,MAAMU,SAAS,cAAeC,UAAWA,UAAWA,UAAW,CAChFC,QAAS,qCAAqCJ,KAC9CK,SAAU,uBAGd,MAAMC,QAAaL,EAAQM,kBAC3B,OAAOD,EAAKG,IAAKC,GAAcA,EAAKC,YACxC,CAAE,MAAOG,GACLC,QAAQD,MAAM,2BAA4BA,GAC1CE,EAAWF,MAAM,2BACjB,MAAO,EACX,CACJ,CAKA,iBAAMU,CAAYxB,EAAmBuB,EAAgB,IACjD,IACI,MAAMtB,EAAUR,KAAKD,MAAMU,SAAS,cAAeC,UAAWA,UAAWA,UAAW,CAChFC,QAAS,qCAAqCJ,KAC9CK,SAAU,mBAGd,MAAMC,QAAaL,EAAQM,kBAC3B,OAAOD,EAAKG,IAAKC,GAAcA,EAAKC,YACxC,CAAE,MAAOG,GACLC,QAAQD,MAAM,4BAA6BA,GAC3CE,EAAWF,MAAM,4BACjB,MAAO,EACX,CACJ,CAKA,uBAAMW,CAAkBzB,GACpB,IAEI,MAAM0B,EAAUjC,KAAKD,MAAMmC,YAAY,2BAEvC,OAAO,IAAIC,QAAQ,CAACC,EAASC,KAEzBJ,EAAQK,UAAUC,KAAK,KACnBH,EAAQ,QACTI,MAAOnB,IACNC,QAAQD,MAAM,+BAAgCA,GAC9CE,EAAWF,MAAM,gCACjBgB,EAAOhB,MAGnB,CAAE,MAAOA,GACLC,QAAQD,MAAM,+BAAgCA,GAC9CE,EAAWF,MAAM,gCACjB,OAAO,KACX,CACJ,CAKQD,oBAAoBP,GACxB,MAAO,CACH4B,KAAM5B,EAAK4B,MAAQ,EACnBC,OAAQ7B,EAAK6B,QAAU,EACvBC,KAAM9B,EAAK8B,MAAQ,EACnBC,QAAS/B,EAAK+B,SAAW,EACzBC,OAAQhC,EAAKgC,QAAU,EAGvBC,WAAYjC,EAAKiC,YAAc,EAC/BC,WAAYlC,EAAKkC,YAAc,EAC/BC,WAAYnC,EAAKmC,YAAc,EAC/BC,WAAYpC,EAAKoC,YAAc,EAC/BC,WAAYrC,EAAKqC,YAAc,EAG/BC,cAAetC,EAAKsC,eAAiB,EACrCC,cAAevC,EAAKuC,eAAiB,EACrCC,cAAexC,EAAKwC,eAAiB,EACrCC,cAAezC,EAAKyC,eAAiB,EACrCC,cAAe1C,EAAK0C,eAAiB,EAGrCC,eAAgB3C,EAAK2C,gBAAkB,EACvCC,eAAgB5C,EAAK4C,gBAAkB,EACvCC,eAAgB7C,EAAK6C,gBAAkB,EACvCC,eAAgB9C,EAAK8C,gBAAkB,EACvCC,eAAgB/C,EAAK+C,gBAAkB,EAGvCC,cAAehD,EAAKgD,eAAiB,EACrCC,iBAAkBjD,EAAKiD,kBAAoB,EAG3CC,YAAalD,EAAKkD,aAAe,EACjCC,UAAWnD,EAAKmD,WAAa,EAC7BC,SAAUpD,EAAKoD,UAAY,EAC3BC,WAAYrD,EAAKqD,YAAc,EAC/BC,UAAWtD,EAAKsD,WAAa,EAC7BC,gBAAiBvD,EAAKuD,iBAAmB,EACzCC,SAAUxD,EAAKwD,UAAY,EAC3BC,WAAY,EACZC,QAAS,GACTC,SAAU,GACVC,cAAe5D,EAAK4D,gBAAiB,IAAIC,MAAOC,cAExD,CAKA,yBAAMC,CAAoBrE,GACtB,IACI,MAAMC,EAAUR,KAAKD,MAAMU,SAAS,WAAYC,UAAWA,UAAWA,UAAW,CAC7EC,QAAS,aAAaJ,KACtBK,SAAU,mBAGd,MAAMC,QAAaL,EAAQM,kBAC3B,OAAOD,EAAKG,IAAKC,GAAcA,EAAKC,YACxC,CAAE,MAAOG,GACLC,QAAQD,MAAM,oCAAqCA,GACnDE,EAAWF,MAAM,oCACjB,MAAO,EACX,CACJ,CAKA,mBAAMwD,CAActE,EAAmBuE,GACnC,IACI,MAAMtE,EAAUR,KAAKD,MAAMU,SAAS,WAAYC,UAAWA,UAAWA,UAAW,CAC7EC,QAAS,UAAUmE,oBAA2BvE,OAGlD,MAAMM,QAAaL,EAAQM,kBAC3B,MAAMC,EAAUF,EAAKG,IAAKC,GAAcA,EAAKC,aAE7C,GAAIH,GAAWA,EAAQI,OAAS,EAAG,CAC/B,OAAOnB,KAAKoB,oBAAoBL,EAAQ,GAC5C,KAAO,CACH,OAAO,IACX,CACJ,CAAE,MAAOM,GACLC,QAAQD,MAAM,+BAAgCA,GAC9CE,EAAWF,MAAM,yBACjB,OAAO,IACX,CACJ,CAKA,uBAAM0D,CAAkBxE,EAAmByE,GACvC,IACI,MAAM/C,EAAUjC,KAAKD,MAAMmC,YAAY,2BACvCD,EAAQgD,aAAa,QAAS1E,GAC9B0B,EAAQgD,aAAa,UAAWD,GAEhC,OAAO,IAAI7C,QAAQ,CAACC,EAASC,KACzBJ,EAAQK,UAAUC,KAAK,KACnBH,EAAQ,QACTI,MAAOnB,IACNC,QAAQD,MAAM,iCAAkCA,GAChDE,EAAWF,MAAM,0CACjBgB,EAAOhB,MAGnB,CAAE,MAAOA,GACLC,QAAQD,MAAM,iCAAkCA,GAChDE,EAAWF,MAAM,0CACjB,OAAO,KACX,CACJ,CAKA,0BAAM6D,CAAqB3E,EAAmByE,GAC1C,IACI,MAAM/C,EAAUjC,KAAKD,MAAMmC,YAAY,8BACvCD,EAAQgD,aAAa,QAAS1E,GAC9B0B,EAAQgD,aAAa,UAAWD,GAEhC,OAAO,IAAI7C,QAAQ,CAACC,EAASC,KACzBJ,EAAQK,UAAUC,KAAK,KACnBH,EAAQ,QACTI,MAAOnB,IACNC,QAAQD,MAAM,qCAAsCA,GACpDE,EAAWF,MAAM,8CACjBgB,EAAOhB,MAGnB,CAAE,MAAOA,GACLC,QAAQD,MAAM,qCAAsCA,GACpDE,EAAWF,MAAM,8CACjB,OAAO,KACX,CACJ,EACH,OAAAxB,CAAA","ignoreList":[]}