@microsoft/agents-hosting-storage-blob 1.5.0-beta.6.ga236d9a19c → 1.5.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.
- package/dist/package.json +44 -0
- package/dist/src/blobsStorage.js +53 -41
- package/dist/src/blobsStorage.js.map +1 -1
- package/dist/src/observability/index.d.ts +2 -0
- package/dist/src/observability/index.js +21 -0
- package/dist/src/observability/index.js.map +1 -0
- package/dist/src/observability/metrics.d.ts +3 -0
- package/dist/src/observability/metrics.js +13 -0
- package/dist/src/observability/metrics.js.map +1 -0
- package/dist/src/observability/traces.d.ts +11 -0
- package/dist/src/observability/traces.js +55 -0
- package/dist/src/observability/traces.js.map +1 -0
- package/package.json +7 -6
- package/src/blobsStorage.ts +59 -49
- package/src/observability/index.ts +5 -0
- package/src/observability/metrics.ts +11 -0
- package/src/observability/traces.ts +53 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/package.json",
|
|
3
|
+
"name": "@microsoft/agents-hosting-storage-blob",
|
|
4
|
+
"version": "1.5.1",
|
|
5
|
+
"homepage": "https://github.com/microsoft/Agents-for-js",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/microsoft/Agents-for-js.git"
|
|
9
|
+
},
|
|
10
|
+
"author": {
|
|
11
|
+
"name": "Microsoft",
|
|
12
|
+
"email": "agentssdk@microsoft.com",
|
|
13
|
+
"url": "https://aka.ms/Agents"
|
|
14
|
+
},
|
|
15
|
+
"description": "Microsoft 365 Agents SDK State Blob Storage support.",
|
|
16
|
+
"main": "dist/index.js",
|
|
17
|
+
"types": "dist/src/index.d.ts",
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@azure/core-auth": "1.10.1",
|
|
20
|
+
"@azure/storage-blob": "12.31.0",
|
|
21
|
+
"@microsoft/agents-hosting": "1.5.1",
|
|
22
|
+
"@microsoft/agents-activity": "1.5.1",
|
|
23
|
+
"@microsoft/agents-telemetry": "1.5.1",
|
|
24
|
+
"zod": "3.25.75"
|
|
25
|
+
},
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"files": [
|
|
28
|
+
"README.md",
|
|
29
|
+
"dist/src",
|
|
30
|
+
"src",
|
|
31
|
+
"package.json"
|
|
32
|
+
],
|
|
33
|
+
"exports": {
|
|
34
|
+
".": {
|
|
35
|
+
"types": "./dist/src/index.d.ts",
|
|
36
|
+
"import": "./dist/src/index.js",
|
|
37
|
+
"require": "./dist/src/index.js"
|
|
38
|
+
},
|
|
39
|
+
"./package.json": "./package.json"
|
|
40
|
+
},
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=20.0.0"
|
|
43
|
+
}
|
|
44
|
+
}
|
package/dist/src/blobsStorage.js
CHANGED
|
@@ -45,8 +45,9 @@ const agents_activity_1 = require("@microsoft/agents-activity");
|
|
|
45
45
|
const errorHelper_1 = require("./errorHelper");
|
|
46
46
|
const blobsTranscriptStore_1 = require("./blobsTranscriptStore");
|
|
47
47
|
const ignoreError_1 = require("./ignoreError");
|
|
48
|
-
const
|
|
49
|
-
const
|
|
48
|
+
const agents_telemetry_1 = require("@microsoft/agents-telemetry");
|
|
49
|
+
const observability_1 = require("./observability");
|
|
50
|
+
const logger = (0, agents_telemetry_1.debug)('agents:blob-storage');
|
|
50
51
|
/**
|
|
51
52
|
* A class that implements the Storage interface using Azure Blob Storage.
|
|
52
53
|
* Provides persistence for bot state data using Azure's Blob Storage service.
|
|
@@ -101,24 +102,28 @@ class BlobsStorage {
|
|
|
101
102
|
* @throws Will throw if keys parameter is invalid or if there's an error reading from storage
|
|
102
103
|
*/
|
|
103
104
|
async read(keys) {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
105
|
+
return (0, agents_telemetry_1.trace)(observability_1.BlobsStorageTraceDefinitions.read, async ({ record }) => {
|
|
106
|
+
var _a;
|
|
107
|
+
record({ keyCount: (_a = keys === null || keys === void 0 ? void 0 : keys.length) !== null && _a !== void 0 ? _a : 0 });
|
|
108
|
+
z.object({ keys: z.array(z.string()) }).parse({ keys });
|
|
109
|
+
await this._initialize();
|
|
110
|
+
const results = await Promise.all(keys.map(async (key) => {
|
|
111
|
+
const result = { key, value: undefined };
|
|
112
|
+
const blob = await (0, ignoreError_1.ignoreError)(this._containerClient.getBlobClient((0, blobsTranscriptStore_1.sanitizeBlobKey)(key)).download(), (0, ignoreError_1.isStatusCodeError)(404));
|
|
113
|
+
if (!blob) {
|
|
114
|
+
return result;
|
|
115
|
+
}
|
|
116
|
+
const { etag: eTag, readableStreamBody } = blob;
|
|
117
|
+
if (!readableStreamBody) {
|
|
118
|
+
return result;
|
|
119
|
+
}
|
|
120
|
+
const parsed = (await consumers_1.default.json(readableStreamBody));
|
|
121
|
+
result.value = { ...parsed, eTag };
|
|
122
|
+
logger.debug(`Read blob: ${key}, eTag: ${eTag}`);
|
|
114
123
|
return result;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
logger.debug(`Read blob: ${key}, eTag: ${eTag}`);
|
|
119
|
-
return result;
|
|
120
|
-
}));
|
|
121
|
-
return results.reduce((acc, { key, value }) => (value ? { ...acc, [key]: value } : acc), {});
|
|
124
|
+
}));
|
|
125
|
+
return results.reduce((acc, { key, value }) => (value ? { ...acc, [key]: value } : acc), {});
|
|
126
|
+
});
|
|
122
127
|
}
|
|
123
128
|
/**
|
|
124
129
|
* Writes storage items to blob storage.
|
|
@@ -128,27 +133,30 @@ class BlobsStorage {
|
|
|
128
133
|
* @throws Will throw if there's a validation error, eTag conflict, or other storage error
|
|
129
134
|
*/
|
|
130
135
|
async write(changes) {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
if (err.statusCode === 412) {
|
|
145
|
-
throw agents_activity_1.ExceptionHelper.generateException(Error, errorHelper_1.Errors.ETagConflict);
|
|
136
|
+
return (0, agents_telemetry_1.trace)(observability_1.BlobsStorageTraceDefinitions.write, async ({ record }) => {
|
|
137
|
+
z.record(z.unknown()).parse(changes);
|
|
138
|
+
record({ keyCount: Object.keys(changes).length });
|
|
139
|
+
await this._initialize();
|
|
140
|
+
await Promise.all(Object.entries(changes).map(async ([key, { eTag = '', ...change }]) => {
|
|
141
|
+
try {
|
|
142
|
+
const blob = this._containerClient.getBlockBlobClient((0, blobsTranscriptStore_1.sanitizeBlobKey)(key));
|
|
143
|
+
const serialized = JSON.stringify(change);
|
|
144
|
+
logger.debug(`Writing blob: ${key}, eTag: ${eTag}, size: ${serialized.length}`);
|
|
145
|
+
return await blob.upload(serialized, serialized.length, {
|
|
146
|
+
conditions: typeof eTag === 'string' && eTag !== '*' ? { ifMatch: eTag } : {},
|
|
147
|
+
blobHTTPHeaders: { blobContentType: 'application/json' },
|
|
148
|
+
});
|
|
146
149
|
}
|
|
147
|
-
|
|
148
|
-
|
|
150
|
+
catch (err) {
|
|
151
|
+
if (err.statusCode === 412) {
|
|
152
|
+
throw agents_activity_1.ExceptionHelper.generateException(Error, errorHelper_1.Errors.ETagConflict);
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
throw err;
|
|
156
|
+
}
|
|
149
157
|
}
|
|
150
|
-
}
|
|
151
|
-
})
|
|
158
|
+
}));
|
|
159
|
+
});
|
|
152
160
|
}
|
|
153
161
|
/**
|
|
154
162
|
* Deletes storage items from blob storage.
|
|
@@ -158,9 +166,13 @@ class BlobsStorage {
|
|
|
158
166
|
* @throws Will throw if keys parameter is invalid
|
|
159
167
|
*/
|
|
160
168
|
async delete(keys) {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
169
|
+
return (0, agents_telemetry_1.trace)(observability_1.BlobsStorageTraceDefinitions.delete, async ({ record }) => {
|
|
170
|
+
var _a;
|
|
171
|
+
record({ keyCount: (_a = keys === null || keys === void 0 ? void 0 : keys.length) !== null && _a !== void 0 ? _a : 0 });
|
|
172
|
+
z.object({ keys: z.array(z.string()) }).parse({ keys });
|
|
173
|
+
await this._initialize();
|
|
174
|
+
await Promise.all(keys.map((key) => (0, ignoreError_1.ignoreError)(this._containerClient.deleteBlob((0, blobsTranscriptStore_1.sanitizeBlobKey)(key)), (0, ignoreError_1.isStatusCodeError)(404))));
|
|
175
|
+
});
|
|
164
176
|
}
|
|
165
177
|
}
|
|
166
178
|
exports.BlobsStorage = BlobsStorage;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blobsStorage.js","sourceRoot":"","sources":["../../src/blobsStorage.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAwB;AACxB,iEAA8C;AAC9C,gDAAqE;AACrE,sDAK4B;AAE5B,gEAA4D;AAC5D,+CAAsC;AACtC,iEAAwD;AACxD,+CAA8D;AAC9D,
|
|
1
|
+
{"version":3,"file":"blobsStorage.js","sourceRoot":"","sources":["../../src/blobsStorage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
// Licensed under the MIT License.
|
|
4
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
5
|
+
if (k2 === undefined) k2 = k;
|
|
6
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
7
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
8
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
9
|
+
}
|
|
10
|
+
Object.defineProperty(o, k2, desc);
|
|
11
|
+
}) : (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
o[k2] = m[k];
|
|
14
|
+
}));
|
|
15
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
16
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
17
|
+
};
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
__exportStar(require("./metrics"), exports);
|
|
20
|
+
__exportStar(require("./traces"), exports);
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/observability/index.ts"],"names":[],"mappings":";AAAA,4DAA4D;AAC5D,kCAAkC;;;;;;;;;;;;;;;;AAElC,4CAAyB;AACzB,2CAAwB"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
// Licensed under the MIT License.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.BlobsStorageMetrics = void 0;
|
|
6
|
+
const agents_telemetry_1 = require("@microsoft/agents-telemetry");
|
|
7
|
+
exports.BlobsStorageMetrics = {
|
|
8
|
+
storageOperationDuration: agents_telemetry_1.metric.histogram(agents_telemetry_1.MetricNames.STORAGE_OPERATION_DURATION, {
|
|
9
|
+
unit: 'ms',
|
|
10
|
+
description: 'Duration of storage operations in milliseconds'
|
|
11
|
+
})
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=metrics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../../src/observability/metrics.ts"],"names":[],"mappings":";AAAA,4DAA4D;AAC5D,kCAAkC;;;AAElC,kEAAiE;AAEpD,QAAA,mBAAmB,GAAG;IACjC,wBAAwB,EAAE,yBAAM,CAAC,SAAS,CAAC,8BAAW,CAAC,0BAA0B,EAAE;QACjF,IAAI,EAAE,IAAI;QACV,WAAW,EAAE,gDAAgD;KAC9D,CAAC;CACH,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const BlobsStorageTraceDefinitions: {
|
|
2
|
+
read: import("@microsoft/agents-telemetry").TraceDefinition<{
|
|
3
|
+
keyCount: number;
|
|
4
|
+
}, object>;
|
|
5
|
+
write: import("@microsoft/agents-telemetry").TraceDefinition<{
|
|
6
|
+
keyCount: number;
|
|
7
|
+
}, object>;
|
|
8
|
+
delete: import("@microsoft/agents-telemetry").TraceDefinition<{
|
|
9
|
+
keyCount: number;
|
|
10
|
+
}, object>;
|
|
11
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
// Licensed under the MIT License.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.BlobsStorageTraceDefinitions = void 0;
|
|
6
|
+
const agents_telemetry_1 = require("@microsoft/agents-telemetry");
|
|
7
|
+
const metrics_1 = require("./metrics");
|
|
8
|
+
exports.BlobsStorageTraceDefinitions = {
|
|
9
|
+
read: agents_telemetry_1.trace.define({
|
|
10
|
+
name: agents_telemetry_1.SpanNames.STORAGE_READ,
|
|
11
|
+
record: {
|
|
12
|
+
keyCount: 0,
|
|
13
|
+
},
|
|
14
|
+
end({ span, record, duration }) {
|
|
15
|
+
var _a;
|
|
16
|
+
const attributes = {
|
|
17
|
+
'storage.operation': 'read',
|
|
18
|
+
'storage.key.count': (_a = record.keyCount) !== null && _a !== void 0 ? _a : 0,
|
|
19
|
+
};
|
|
20
|
+
span.setAttributes(attributes);
|
|
21
|
+
metrics_1.BlobsStorageMetrics.storageOperationDuration.record(duration, attributes);
|
|
22
|
+
}
|
|
23
|
+
}),
|
|
24
|
+
write: agents_telemetry_1.trace.define({
|
|
25
|
+
name: agents_telemetry_1.SpanNames.STORAGE_WRITE,
|
|
26
|
+
record: {
|
|
27
|
+
keyCount: 0,
|
|
28
|
+
},
|
|
29
|
+
end({ span, record, duration }) {
|
|
30
|
+
var _a;
|
|
31
|
+
const attributes = {
|
|
32
|
+
'storage.operation': 'write',
|
|
33
|
+
'storage.key.count': (_a = record.keyCount) !== null && _a !== void 0 ? _a : 0,
|
|
34
|
+
};
|
|
35
|
+
span.setAttributes(attributes);
|
|
36
|
+
metrics_1.BlobsStorageMetrics.storageOperationDuration.record(duration, attributes);
|
|
37
|
+
}
|
|
38
|
+
}),
|
|
39
|
+
delete: agents_telemetry_1.trace.define({
|
|
40
|
+
name: agents_telemetry_1.SpanNames.STORAGE_DELETE,
|
|
41
|
+
record: {
|
|
42
|
+
keyCount: 0,
|
|
43
|
+
},
|
|
44
|
+
end({ span, record, duration }) {
|
|
45
|
+
var _a;
|
|
46
|
+
const attributes = {
|
|
47
|
+
'storage.operation': 'delete',
|
|
48
|
+
'storage.key.count': (_a = record.keyCount) !== null && _a !== void 0 ? _a : 0,
|
|
49
|
+
};
|
|
50
|
+
span.setAttributes(attributes);
|
|
51
|
+
metrics_1.BlobsStorageMetrics.storageOperationDuration.record(duration, attributes);
|
|
52
|
+
}
|
|
53
|
+
}),
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=traces.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"traces.js","sourceRoot":"","sources":["../../../src/observability/traces.ts"],"names":[],"mappings":";AAAA,4DAA4D;AAC5D,kCAAkC;;;AAElC,kEAA8D;AAC9D,uCAA+C;AAElC,QAAA,4BAA4B,GAAG;IAC1C,IAAI,EAAE,wBAAK,CAAC,MAAM,CAAC;QACjB,IAAI,EAAE,4BAAS,CAAC,YAAY;QAC5B,MAAM,EAAE;YACN,QAAQ,EAAE,CAAC;SACZ;QACD,GAAG,CAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE;;YAC7B,MAAM,UAAU,GAAG;gBACjB,mBAAmB,EAAE,MAAM;gBAC3B,mBAAmB,EAAE,MAAA,MAAM,CAAC,QAAQ,mCAAI,CAAC;aAC1C,CAAA;YAED,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,CAAA;YAC9B,6BAAmB,CAAC,wBAAwB,CAAC,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAA;QAC3E,CAAC;KACF,CAAC;IACF,KAAK,EAAE,wBAAK,CAAC,MAAM,CAAC;QAClB,IAAI,EAAE,4BAAS,CAAC,aAAa;QAC7B,MAAM,EAAE;YACN,QAAQ,EAAE,CAAC;SACZ;QACD,GAAG,CAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE;;YAC7B,MAAM,UAAU,GAAG;gBACjB,mBAAmB,EAAE,OAAO;gBAC5B,mBAAmB,EAAE,MAAA,MAAM,CAAC,QAAQ,mCAAI,CAAC;aAC1C,CAAA;YAED,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,CAAA;YAC9B,6BAAmB,CAAC,wBAAwB,CAAC,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAA;QAC3E,CAAC;KACF,CAAC;IACF,MAAM,EAAE,wBAAK,CAAC,MAAM,CAAC;QACnB,IAAI,EAAE,4BAAS,CAAC,cAAc;QAC9B,MAAM,EAAE;YACN,QAAQ,EAAE,CAAC;SACZ;QACD,GAAG,CAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE;;YAC7B,MAAM,UAAU,GAAG;gBACjB,mBAAmB,EAAE,QAAQ;gBAC7B,mBAAmB,EAAE,MAAA,MAAM,CAAC,QAAQ,mCAAI,CAAC;aAC1C,CAAA;YAED,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,CAAA;YAC9B,6BAAmB,CAAC,wBAAwB,CAAC,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAA;QAC3E,CAAC;KACF,CAAC;CACH,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "@microsoft/agents-hosting-storage-blob",
|
|
4
|
-
"version": "1.5.
|
|
4
|
+
"version": "1.5.1",
|
|
5
5
|
"homepage": "https://github.com/microsoft/Agents-for-js",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -16,11 +16,12 @@
|
|
|
16
16
|
"main": "dist/index.js",
|
|
17
17
|
"types": "dist/src/index.d.ts",
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@azure/core-auth": "
|
|
20
|
-
"@azure/storage-blob": "
|
|
21
|
-
"@microsoft/agents-hosting": "1.5.
|
|
22
|
-
"@microsoft/agents-activity": "1.5.
|
|
23
|
-
"
|
|
19
|
+
"@azure/core-auth": "1.10.1",
|
|
20
|
+
"@azure/storage-blob": "12.31.0",
|
|
21
|
+
"@microsoft/agents-hosting": "1.5.1",
|
|
22
|
+
"@microsoft/agents-activity": "1.5.1",
|
|
23
|
+
"@microsoft/agents-telemetry": "1.5.1",
|
|
24
|
+
"zod": "3.25.75"
|
|
24
25
|
},
|
|
25
26
|
"license": "MIT",
|
|
26
27
|
"files": [
|
package/src/blobsStorage.ts
CHANGED
|
@@ -12,7 +12,8 @@ import { ExceptionHelper } from '@microsoft/agents-activity'
|
|
|
12
12
|
import { Errors } from './errorHelper'
|
|
13
13
|
import { sanitizeBlobKey } from './blobsTranscriptStore'
|
|
14
14
|
import { ignoreError, isStatusCodeError } from './ignoreError'
|
|
15
|
-
import { debug } from '@microsoft/agents-
|
|
15
|
+
import { trace, debug } from '@microsoft/agents-telemetry'
|
|
16
|
+
import { BlobsStorageTraceDefinitions } from './observability'
|
|
16
17
|
|
|
17
18
|
const logger = debug('agents:blob-storage')
|
|
18
19
|
|
|
@@ -99,34 +100,37 @@ export class BlobsStorage implements Storage {
|
|
|
99
100
|
* @throws Will throw if keys parameter is invalid or if there's an error reading from storage
|
|
100
101
|
*/
|
|
101
102
|
async read (keys: string[]): Promise<StoreItems> {
|
|
102
|
-
|
|
103
|
+
return trace(BlobsStorageTraceDefinitions.read, async ({ record }) => {
|
|
104
|
+
record({ keyCount: keys?.length ?? 0 })
|
|
105
|
+
z.object({ keys: z.array(z.string()) }).parse({ keys })
|
|
103
106
|
|
|
104
|
-
|
|
107
|
+
await this._initialize()
|
|
105
108
|
|
|
106
|
-
|
|
107
|
-
|
|
109
|
+
const results = await Promise.all(keys.map(async (key) => {
|
|
110
|
+
const result = { key, value: undefined }
|
|
108
111
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
112
|
+
const blob = await ignoreError(
|
|
113
|
+
this._containerClient.getBlobClient(sanitizeBlobKey(key)).download(),
|
|
114
|
+
isStatusCodeError(404)
|
|
115
|
+
)
|
|
113
116
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
+
if (!blob) {
|
|
118
|
+
return result
|
|
119
|
+
}
|
|
117
120
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
121
|
+
const { etag: eTag, readableStreamBody } = blob
|
|
122
|
+
if (!readableStreamBody) {
|
|
123
|
+
return result
|
|
124
|
+
}
|
|
122
125
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
126
|
+
const parsed = (await StreamConsumers.json(readableStreamBody)) as any
|
|
127
|
+
result.value = { ...parsed, eTag }
|
|
128
|
+
logger.debug(`Read blob: ${key}, eTag: ${eTag}`)
|
|
129
|
+
return result
|
|
130
|
+
}))
|
|
128
131
|
|
|
129
|
-
|
|
132
|
+
return results.reduce((acc, { key, value }) => (value ? { ...acc, [key]: value } : acc), {})
|
|
133
|
+
})
|
|
130
134
|
}
|
|
131
135
|
|
|
132
136
|
/**
|
|
@@ -137,29 +141,32 @@ export class BlobsStorage implements Storage {
|
|
|
137
141
|
* @throws Will throw if there's a validation error, eTag conflict, or other storage error
|
|
138
142
|
*/
|
|
139
143
|
async write (changes: StoreItems): Promise<void> {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
144
|
+
return trace(BlobsStorageTraceDefinitions.write, async ({ record }) => {
|
|
145
|
+
z.record(z.unknown()).parse(changes)
|
|
146
|
+
record({ keyCount: Object.keys(changes).length })
|
|
147
|
+
|
|
148
|
+
await this._initialize()
|
|
149
|
+
|
|
150
|
+
await Promise.all(
|
|
151
|
+
Object.entries(changes).map(async ([key, { eTag = '', ...change }]) => {
|
|
152
|
+
try {
|
|
153
|
+
const blob = this._containerClient.getBlockBlobClient(sanitizeBlobKey(key))
|
|
154
|
+
const serialized = JSON.stringify(change)
|
|
155
|
+
logger.debug(`Writing blob: ${key}, eTag: ${eTag}, size: ${serialized.length}`)
|
|
156
|
+
return await blob.upload(serialized, serialized.length, {
|
|
157
|
+
conditions: typeof eTag === 'string' && eTag !== '*' ? { ifMatch: eTag } : {},
|
|
158
|
+
blobHTTPHeaders: { blobContentType: 'application/json' },
|
|
159
|
+
})
|
|
160
|
+
} catch (err: any) {
|
|
161
|
+
if (err.statusCode === 412) {
|
|
162
|
+
throw ExceptionHelper.generateException(Error, Errors.ETagConflict)
|
|
163
|
+
} else {
|
|
164
|
+
throw err
|
|
165
|
+
}
|
|
159
166
|
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
)
|
|
167
|
+
})
|
|
168
|
+
)
|
|
169
|
+
})
|
|
163
170
|
}
|
|
164
171
|
|
|
165
172
|
/**
|
|
@@ -170,12 +177,15 @@ export class BlobsStorage implements Storage {
|
|
|
170
177
|
* @throws Will throw if keys parameter is invalid
|
|
171
178
|
*/
|
|
172
179
|
async delete (keys: string[]): Promise<void> {
|
|
173
|
-
|
|
180
|
+
return trace(BlobsStorageTraceDefinitions.delete, async ({ record }) => {
|
|
181
|
+
record({ keyCount: keys?.length ?? 0 })
|
|
182
|
+
z.object({ keys: z.array(z.string()) }).parse({ keys })
|
|
174
183
|
|
|
175
|
-
|
|
184
|
+
await this._initialize()
|
|
176
185
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
186
|
+
await Promise.all(
|
|
187
|
+
keys.map((key) => ignoreError(this._containerClient.deleteBlob(sanitizeBlobKey(key)), isStatusCodeError(404)))
|
|
188
|
+
)
|
|
189
|
+
})
|
|
180
190
|
}
|
|
181
191
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
import { metric, MetricNames } from '@microsoft/agents-telemetry'
|
|
5
|
+
|
|
6
|
+
export const BlobsStorageMetrics = {
|
|
7
|
+
storageOperationDuration: metric.histogram(MetricNames.STORAGE_OPERATION_DURATION, {
|
|
8
|
+
unit: 'ms',
|
|
9
|
+
description: 'Duration of storage operations in milliseconds'
|
|
10
|
+
})
|
|
11
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
import { SpanNames, trace } from '@microsoft/agents-telemetry'
|
|
5
|
+
import { BlobsStorageMetrics } from './metrics'
|
|
6
|
+
|
|
7
|
+
export const BlobsStorageTraceDefinitions = {
|
|
8
|
+
read: trace.define({
|
|
9
|
+
name: SpanNames.STORAGE_READ,
|
|
10
|
+
record: {
|
|
11
|
+
keyCount: 0,
|
|
12
|
+
},
|
|
13
|
+
end ({ span, record, duration }) {
|
|
14
|
+
const attributes = {
|
|
15
|
+
'storage.operation': 'read',
|
|
16
|
+
'storage.key.count': record.keyCount ?? 0,
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
span.setAttributes(attributes)
|
|
20
|
+
BlobsStorageMetrics.storageOperationDuration.record(duration, attributes)
|
|
21
|
+
}
|
|
22
|
+
}),
|
|
23
|
+
write: trace.define({
|
|
24
|
+
name: SpanNames.STORAGE_WRITE,
|
|
25
|
+
record: {
|
|
26
|
+
keyCount: 0,
|
|
27
|
+
},
|
|
28
|
+
end ({ span, record, duration }) {
|
|
29
|
+
const attributes = {
|
|
30
|
+
'storage.operation': 'write',
|
|
31
|
+
'storage.key.count': record.keyCount ?? 0,
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
span.setAttributes(attributes)
|
|
35
|
+
BlobsStorageMetrics.storageOperationDuration.record(duration, attributes)
|
|
36
|
+
}
|
|
37
|
+
}),
|
|
38
|
+
delete: trace.define({
|
|
39
|
+
name: SpanNames.STORAGE_DELETE,
|
|
40
|
+
record: {
|
|
41
|
+
keyCount: 0,
|
|
42
|
+
},
|
|
43
|
+
end ({ span, record, duration }) {
|
|
44
|
+
const attributes = {
|
|
45
|
+
'storage.operation': 'delete',
|
|
46
|
+
'storage.key.count': record.keyCount ?? 0,
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
span.setAttributes(attributes)
|
|
50
|
+
BlobsStorageMetrics.storageOperationDuration.record(duration, attributes)
|
|
51
|
+
}
|
|
52
|
+
}),
|
|
53
|
+
}
|