@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.
@@ -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
+ }
@@ -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 logger_1 = require("@microsoft/agents-activity/logger");
49
- const logger = (0, logger_1.debug)('agents:blob-storage');
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
- z.object({ keys: z.array(z.string()) }).parse({ keys });
105
- await this._initialize();
106
- const results = await Promise.all(keys.map(async (key) => {
107
- const result = { key, value: undefined };
108
- const blob = await (0, ignoreError_1.ignoreError)(this._containerClient.getBlobClient((0, blobsTranscriptStore_1.sanitizeBlobKey)(key)).download(), (0, ignoreError_1.isStatusCodeError)(404));
109
- if (!blob) {
110
- return result;
111
- }
112
- const { etag: eTag, readableStreamBody } = blob;
113
- if (!readableStreamBody) {
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
- const parsed = (await consumers_1.default.json(readableStreamBody));
117
- result.value = { ...parsed, eTag };
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
- z.record(z.unknown()).parse(changes);
132
- await this._initialize();
133
- await Promise.all(Object.entries(changes).map(async ([key, { eTag = '', ...change }]) => {
134
- try {
135
- const blob = this._containerClient.getBlockBlobClient((0, blobsTranscriptStore_1.sanitizeBlobKey)(key));
136
- const serialized = JSON.stringify(change);
137
- logger.debug(`Writing blob: ${key}, eTag: ${eTag}, size: ${serialized.length}`);
138
- return await blob.upload(serialized, serialized.length, {
139
- conditions: typeof eTag === 'string' && eTag !== '*' ? { ifMatch: eTag } : {},
140
- blobHTTPHeaders: { blobContentType: 'application/json' },
141
- });
142
- }
143
- catch (err) {
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
- else {
148
- throw err;
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
- z.object({ keys: z.array(z.string()) }).parse({ keys });
162
- await this._initialize();
163
- await Promise.all(keys.map((key) => (0, ignoreError_1.ignoreError)(this._containerClient.deleteBlob((0, blobsTranscriptStore_1.sanitizeBlobKey)(key)), (0, ignoreError_1.isStatusCodeError)(404))));
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":"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"}
1
+ {"version":3,"file":"blobsStorage.js","sourceRoot":"","sources":["../../src/blobsStorage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export * from './metrics';
2
+ export * from './traces';
@@ -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,3 @@
1
+ export declare const BlobsStorageMetrics: {
2
+ storageOperationDuration: import("@opentelemetry/api").Histogram<import("@opentelemetry/api").Attributes>;
3
+ };
@@ -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.0-beta.6.ga236d9a19c",
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": "^1.10.1",
20
- "@azure/storage-blob": "^12.31.0",
21
- "@microsoft/agents-hosting": "1.5.0-beta.6.ga236d9a19c",
22
- "@microsoft/agents-activity": "1.5.0-beta.6.ga236d9a19c",
23
- "zod": "^3.25.75"
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": [
@@ -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-activity/logger'
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
- z.object({ keys: z.array(z.string()) }).parse({ keys })
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
- await this._initialize()
107
+ await this._initialize()
105
108
 
106
- const results = await Promise.all(keys.map(async (key) => {
107
- const result = { key, value: undefined }
109
+ const results = await Promise.all(keys.map(async (key) => {
110
+ const result = { key, value: undefined }
108
111
 
109
- const blob = await ignoreError(
110
- this._containerClient.getBlobClient(sanitizeBlobKey(key)).download(),
111
- isStatusCodeError(404)
112
- )
112
+ const blob = await ignoreError(
113
+ this._containerClient.getBlobClient(sanitizeBlobKey(key)).download(),
114
+ isStatusCodeError(404)
115
+ )
113
116
 
114
- if (!blob) {
115
- return result
116
- }
117
+ if (!blob) {
118
+ return result
119
+ }
117
120
 
118
- const { etag: eTag, readableStreamBody } = blob
119
- if (!readableStreamBody) {
120
- return result
121
- }
121
+ const { etag: eTag, readableStreamBody } = blob
122
+ if (!readableStreamBody) {
123
+ return result
124
+ }
122
125
 
123
- const parsed = (await StreamConsumers.json(readableStreamBody)) as any
124
- result.value = { ...parsed, eTag }
125
- logger.debug(`Read blob: ${key}, eTag: ${eTag}`)
126
- return result
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
- return results.reduce((acc, { key, value }) => (value ? { ...acc, [key]: value } : acc), {})
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
- z.record(z.unknown()).parse(changes)
141
-
142
- await this._initialize()
143
-
144
- await Promise.all(
145
- Object.entries(changes).map(async ([key, { eTag = '', ...change }]) => {
146
- try {
147
- const blob = this._containerClient.getBlockBlobClient(sanitizeBlobKey(key))
148
- const serialized = JSON.stringify(change)
149
- logger.debug(`Writing blob: ${key}, eTag: ${eTag}, size: ${serialized.length}`)
150
- return await blob.upload(serialized, serialized.length, {
151
- conditions: typeof eTag === 'string' && eTag !== '*' ? { ifMatch: eTag } : {},
152
- blobHTTPHeaders: { blobContentType: 'application/json' },
153
- })
154
- } catch (err: any) {
155
- if (err.statusCode === 412) {
156
- throw ExceptionHelper.generateException(Error, Errors.ETagConflict)
157
- } else {
158
- throw err
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
- z.object({ keys: z.array(z.string()) }).parse({ keys })
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
- await this._initialize()
184
+ await this._initialize()
176
185
 
177
- await Promise.all(
178
- keys.map((key) => ignoreError(this._containerClient.deleteBlob(sanitizeBlobKey(key)), isStatusCodeError(404)))
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,5 @@
1
+ // Copyright (c) Microsoft Corporation. All rights reserved.
2
+ // Licensed under the MIT License.
3
+
4
+ export * from './metrics'
5
+ export * from './traces'
@@ -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
+ }