@fluidframework/container-runtime 2.0.0-dev.7.2.0.204906 → 2.0.0-dev.7.3.0.206769
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/CHANGELOG.md +4 -0
- package/api-report/container-runtime.api.md +4 -7
- package/dist/blobManager.d.ts +5 -5
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +36 -43
- package/dist/blobManager.js.map +1 -1
- package/dist/containerRuntime.d.ts +12 -8
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +24 -12
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStoreContext.d.ts +8 -1
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +46 -31
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStores.d.ts +0 -14
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +0 -43
- package/dist/dataStores.js.map +1 -1
- package/dist/deltaManagerProxyBase.d.ts +1 -1
- package/dist/deltaManagerProxyBase.d.ts.map +1 -1
- package/dist/deltaManagerProxyBase.js +2 -2
- package/dist/deltaManagerProxyBase.js.map +1 -1
- package/dist/gc/garbageCollection.d.ts +6 -3
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js +27 -17
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcDefinitions.d.ts +7 -3
- package/dist/gc/gcDefinitions.d.ts.map +1 -1
- package/dist/gc/gcDefinitions.js.map +1 -1
- package/dist/gc/gcTelemetry.d.ts +11 -4
- package/dist/gc/gcTelemetry.d.ts.map +1 -1
- package/dist/gc/gcTelemetry.js +72 -39
- package/dist/gc/gcTelemetry.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/lib/blobManager.d.ts +5 -5
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +37 -44
- package/lib/blobManager.js.map +1 -1
- package/lib/containerRuntime.d.ts +12 -8
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +24 -12
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStoreContext.d.ts +8 -1
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +46 -31
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStores.d.ts +0 -14
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +1 -44
- package/lib/dataStores.js.map +1 -1
- package/lib/deltaManagerProxyBase.d.ts +1 -1
- package/lib/deltaManagerProxyBase.d.ts.map +1 -1
- package/lib/deltaManagerProxyBase.js +2 -2
- package/lib/deltaManagerProxyBase.js.map +1 -1
- package/lib/gc/garbageCollection.d.ts +6 -3
- package/lib/gc/garbageCollection.d.ts.map +1 -1
- package/lib/gc/garbageCollection.js +28 -18
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/gc/gcDefinitions.d.ts +7 -3
- package/lib/gc/gcDefinitions.d.ts.map +1 -1
- package/lib/gc/gcDefinitions.js.map +1 -1
- package/lib/gc/gcTelemetry.d.ts +11 -4
- package/lib/gc/gcTelemetry.d.ts.map +1 -1
- package/lib/gc/gcTelemetry.js +72 -39
- package/lib/gc/gcTelemetry.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/package.json +19 -19
- package/src/blobManager.ts +43 -53
- package/src/containerRuntime.ts +41 -19
- package/src/dataStoreContext.ts +23 -4
- package/src/dataStores.ts +1 -67
- package/src/deltaManagerProxyBase.ts +2 -2
- package/src/gc/garbageCollection.ts +39 -25
- package/src/gc/gcDefinitions.ts +8 -3
- package/src/gc/gcTelemetry.ts +102 -54
- package/src/packageVersion.ts +1 -1
- package/dist/container-runtime-alpha.d.ts +0 -1744
- package/dist/container-runtime-beta.d.ts +0 -1744
- package/dist/container-runtime-public.d.ts +0 -1744
- package/dist/container-runtime-untrimmed.d.ts +0 -1805
package/src/gc/gcTelemetry.ts
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
MonitoringContext,
|
|
12
12
|
tagCodeArtifacts,
|
|
13
13
|
} from "@fluidframework/telemetry-utils";
|
|
14
|
+
import { RuntimeHeaderData } from "../containerRuntime";
|
|
14
15
|
import { ICreateContainerMetadata } from "../summary";
|
|
15
16
|
import {
|
|
16
17
|
disableSweepLogKey,
|
|
@@ -32,7 +33,7 @@ interface ICommonProps {
|
|
|
32
33
|
completedGCRuns: number;
|
|
33
34
|
isTombstoned: boolean;
|
|
34
35
|
lastSummaryTime?: number;
|
|
35
|
-
|
|
36
|
+
headers?: RuntimeHeaderData;
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
/** The event that is logged when unreferenced node is used after a certain time. */
|
|
@@ -80,7 +81,11 @@ export class GCTelemetryTracker {
|
|
|
80
81
|
private readonly mc: MonitoringContext,
|
|
81
82
|
private readonly configs: Pick<
|
|
82
83
|
IGarbageCollectorConfigs,
|
|
83
|
-
|
|
84
|
+
| "inactiveTimeoutMs"
|
|
85
|
+
| "sweepTimeoutMs"
|
|
86
|
+
| "tombstoneEnforcementAllowed"
|
|
87
|
+
| "throwOnTombstoneLoad"
|
|
88
|
+
| "throwOnTombstoneUsage"
|
|
84
89
|
>,
|
|
85
90
|
private readonly isSummarizerClient: boolean,
|
|
86
91
|
private readonly createContainerMetadata: ICreateContainerMetadata,
|
|
@@ -94,12 +99,12 @@ export class GCTelemetryTracker {
|
|
|
94
99
|
) {}
|
|
95
100
|
|
|
96
101
|
/**
|
|
97
|
-
* Returns whether an event should be logged for a node that isn't active anymore.
|
|
102
|
+
* Returns whether an event should be logged for a node that isn't active anymore. This does not apply to
|
|
103
|
+
* tombstoned nodes for which an event is always logged. Some scenarios where we won't log:
|
|
98
104
|
* 1. When a DDS is changed. The corresponding data store's event will be logged instead.
|
|
99
105
|
* 2. An event is logged only once per container instance per event per node.
|
|
100
106
|
*/
|
|
101
107
|
private shouldLogNonActiveEvent(
|
|
102
|
-
nodeId: string,
|
|
103
108
|
nodeType: GCNodeType,
|
|
104
109
|
usageType: NodeUsageType,
|
|
105
110
|
nodeStateTracker: UnreferencedStateTracker,
|
|
@@ -119,6 +124,8 @@ export class GCTelemetryTracker {
|
|
|
119
124
|
return false;
|
|
120
125
|
}
|
|
121
126
|
|
|
127
|
+
// Non-tombstone events are logged once per event per node. A unique id is generated by joining
|
|
128
|
+
// node state (inactive / sweep ready), node's id and usage (loaded / changed / revived).
|
|
122
129
|
if (this.loggedUnreferencedEvents.has(uniqueEventId)) {
|
|
123
130
|
return false;
|
|
124
131
|
}
|
|
@@ -126,24 +133,61 @@ export class GCTelemetryTracker {
|
|
|
126
133
|
}
|
|
127
134
|
|
|
128
135
|
/**
|
|
129
|
-
* Called when a node is used. If the node is not active, log
|
|
136
|
+
* Called when a node is used. If the node is not active or tombstoned, log telemetry indicating object is used
|
|
137
|
+
* when it should not have been.
|
|
130
138
|
*/
|
|
131
139
|
public nodeUsed(nodeUsageProps: INodeUsageProps) {
|
|
132
140
|
// If there is no reference timestamp to work with, no ops have been processed after creation. If so, skip
|
|
133
141
|
// logging as nothing interesting would have happened worth logging.
|
|
134
|
-
|
|
135
|
-
const nodeStateTracker = this.getNodeStateTracker(nodeUsageProps.id);
|
|
136
|
-
if (!nodeStateTracker || nodeUsageProps.currentReferenceTimestampMs === undefined) {
|
|
142
|
+
if (nodeUsageProps.currentReferenceTimestampMs === undefined) {
|
|
137
143
|
return;
|
|
138
144
|
}
|
|
139
145
|
|
|
140
|
-
|
|
141
|
-
// node's id and usage (loaded / changed / revived).
|
|
142
|
-
const uniqueEventId = `${nodeStateTracker.state}-${nodeUsageProps.id}-${nodeUsageProps.usageType}`;
|
|
146
|
+
const nodeStateTracker = this.getNodeStateTracker(nodeUsageProps.id);
|
|
143
147
|
const nodeType = this.getNodeType(nodeUsageProps.id);
|
|
148
|
+
const {
|
|
149
|
+
usageType,
|
|
150
|
+
currentReferenceTimestampMs,
|
|
151
|
+
packagePath,
|
|
152
|
+
id: untaggedId,
|
|
153
|
+
fromId: untaggedFromId,
|
|
154
|
+
...propsToLog
|
|
155
|
+
} = nodeUsageProps;
|
|
156
|
+
const unrefEventProps: Omit<IUnreferencedEventProps, "state" | "usageType"> = {
|
|
157
|
+
type: nodeType,
|
|
158
|
+
unrefTime: nodeStateTracker?.unreferencedTimestampMs ?? -1,
|
|
159
|
+
age:
|
|
160
|
+
nodeStateTracker !== undefined
|
|
161
|
+
? nodeUsageProps.currentReferenceTimestampMs -
|
|
162
|
+
nodeStateTracker.unreferencedTimestampMs
|
|
163
|
+
: -1,
|
|
164
|
+
timeout:
|
|
165
|
+
nodeStateTracker?.state === UnreferencedState.Inactive
|
|
166
|
+
? this.configs.inactiveTimeoutMs
|
|
167
|
+
: this.configs.sweepTimeoutMs,
|
|
168
|
+
...tagCodeArtifacts({ id: untaggedId, fromId: untaggedFromId }),
|
|
169
|
+
...propsToLog,
|
|
170
|
+
...this.createContainerMetadata,
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
// If the node that is used is tombstoned, log a tombstone telemetry.
|
|
174
|
+
// Note that this is done before checking if "nodeStateTracker" is undefined below because unreferenced
|
|
175
|
+
// tracking may not have yet been enabled. That happens only after the client transitions to write mode.
|
|
176
|
+
if (nodeUsageProps.isTombstoned) {
|
|
177
|
+
this.logTombstoneUsageTelemetry(nodeUsageProps, unrefEventProps, nodeType, usageType);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// After logging tombstone telemetry, if the node's unreferenced state is not tracked, there is nothing
|
|
181
|
+
// else to log.
|
|
182
|
+
if (nodeStateTracker === undefined) {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const state = nodeStateTracker.state;
|
|
187
|
+
const uniqueEventId = `${state}-${nodeUsageProps.id}-${nodeUsageProps.usageType}`;
|
|
188
|
+
|
|
144
189
|
if (
|
|
145
190
|
!this.shouldLogNonActiveEvent(
|
|
146
|
-
nodeUsageProps.id,
|
|
147
191
|
nodeType,
|
|
148
192
|
nodeUsageProps.usageType,
|
|
149
193
|
nodeStateTracker,
|
|
@@ -153,42 +197,9 @@ export class GCTelemetryTracker {
|
|
|
153
197
|
return;
|
|
154
198
|
}
|
|
155
199
|
|
|
156
|
-
// Add the unique event id so that we don't generate a log for this event again in this session
|
|
200
|
+
// Add the unique event id so that we don't generate a log for this event again in this session.
|
|
157
201
|
this.loggedUnreferencedEvents.add(uniqueEventId);
|
|
158
202
|
|
|
159
|
-
const state = nodeStateTracker.state;
|
|
160
|
-
const { usageType, currentReferenceTimestampMs, packagePath, id, fromId, ...propsToLog } =
|
|
161
|
-
nodeUsageProps;
|
|
162
|
-
const eventProps: Omit<IUnreferencedEventProps, "state" | "usageType"> = {
|
|
163
|
-
type: nodeType,
|
|
164
|
-
unrefTime: nodeStateTracker.unreferencedTimestampMs,
|
|
165
|
-
age:
|
|
166
|
-
nodeUsageProps.currentReferenceTimestampMs -
|
|
167
|
-
nodeStateTracker.unreferencedTimestampMs,
|
|
168
|
-
timeout:
|
|
169
|
-
state === UnreferencedState.Inactive
|
|
170
|
-
? this.configs.inactiveTimeoutMs
|
|
171
|
-
: this.configs.sweepTimeoutMs,
|
|
172
|
-
...tagCodeArtifacts({ id, fromId }),
|
|
173
|
-
...propsToLog,
|
|
174
|
-
...this.createContainerMetadata,
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
// This will log the following events:
|
|
178
|
-
// GC_Tombstone_DataStore_Revived, GC_Tombstone_SubDataStore_Revived, GC_Tombstone_Blob_Revived
|
|
179
|
-
if (nodeUsageProps.usageType === "Revived" && nodeUsageProps.isTombstoned) {
|
|
180
|
-
sendGCUnexpectedUsageEvent(
|
|
181
|
-
this.mc,
|
|
182
|
-
{
|
|
183
|
-
eventName: `GC_Tombstone_${nodeType}_Revived`,
|
|
184
|
-
category: "generic",
|
|
185
|
-
...tagCodeArtifacts({ url: id }),
|
|
186
|
-
gcTombstoneEnforcementAllowed: this.configs.tombstoneEnforcementAllowed,
|
|
187
|
-
},
|
|
188
|
-
undefined /* packagePath */,
|
|
189
|
-
);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
203
|
// For summarizer client, queue the event so it is logged the next time GC runs if the event is still valid.
|
|
193
204
|
// For non-summarizer client, log the event now since GC won't run on it. This may result in false positives
|
|
194
205
|
// but it's a good signal nonetheless and we can consume it with a grain of salt.
|
|
@@ -196,7 +207,7 @@ export class GCTelemetryTracker {
|
|
|
196
207
|
// SweepReady errors are usages of Objects that will be deleted by GC Sweep!
|
|
197
208
|
if (this.isSummarizerClient) {
|
|
198
209
|
this.pendingEventsQueue.push({
|
|
199
|
-
...
|
|
210
|
+
...unrefEventProps,
|
|
200
211
|
usageType: nodeUsageProps.usageType,
|
|
201
212
|
state,
|
|
202
213
|
});
|
|
@@ -206,16 +217,15 @@ export class GCTelemetryTracker {
|
|
|
206
217
|
// Events generated:
|
|
207
218
|
// InactiveObject_Loaded, SweepReadyObject_Loaded
|
|
208
219
|
if (nodeUsageProps.usageType === "Loaded") {
|
|
209
|
-
const { id
|
|
220
|
+
const { id, fromId, headers, ...detailedProps } = unrefEventProps;
|
|
210
221
|
const event = {
|
|
211
222
|
eventName: `${state}Object_${nodeUsageProps.usageType}`,
|
|
212
|
-
|
|
223
|
+
...tagCodeArtifacts({ pkg: nodeUsageProps.packagePath?.join("/") }),
|
|
213
224
|
stack: generateStack(),
|
|
214
|
-
id
|
|
215
|
-
fromId
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
}),
|
|
225
|
+
id,
|
|
226
|
+
fromId,
|
|
227
|
+
headers: { ...headers },
|
|
228
|
+
details: detailedProps,
|
|
219
229
|
};
|
|
220
230
|
|
|
221
231
|
// Do not log the inactive object x events as error events as they are not the best signal for
|
|
@@ -229,6 +239,44 @@ export class GCTelemetryTracker {
|
|
|
229
239
|
}
|
|
230
240
|
}
|
|
231
241
|
|
|
242
|
+
/**
|
|
243
|
+
* Logs telemetry when a tombstoned object is changed, revived or loaded.
|
|
244
|
+
*/
|
|
245
|
+
private logTombstoneUsageTelemetry(
|
|
246
|
+
nodeUsageProps: INodeUsageProps,
|
|
247
|
+
unrefEventProps: Omit<IUnreferencedEventProps, "state" | "usageType">,
|
|
248
|
+
nodeType: GCNodeType,
|
|
249
|
+
usageType: NodeUsageType,
|
|
250
|
+
) {
|
|
251
|
+
// This will log the following events:
|
|
252
|
+
// GC_Tombstone_DataStore_Requested, GC_Tombstone_DataStore_Changed, GC_Tombstone_DataStore_Revived
|
|
253
|
+
// GC_Tombstone_SubDataStore_Requested, GC_Tombstone_SubDataStore_Changed, GC_Tombstone_SubDataStore_Revived
|
|
254
|
+
// GC_Tombstone_Blob_Requested, GC_Tombstone_Blob_Changed, GC_Tombstone_Blob_Revived
|
|
255
|
+
const { id, fromId, headers, ...detailedProps } = unrefEventProps;
|
|
256
|
+
const eventUsageName = usageType === "Loaded" ? "Requested" : usageType;
|
|
257
|
+
const event = {
|
|
258
|
+
eventName: `GC_Tombstone_${nodeType}_${eventUsageName}`,
|
|
259
|
+
pkg: tagCodeArtifacts({ pkg: nodeUsageProps.packagePath?.join("/") }).pkg,
|
|
260
|
+
stack: generateStack(),
|
|
261
|
+
id,
|
|
262
|
+
fromId,
|
|
263
|
+
headers: { ...headers },
|
|
264
|
+
details: detailedProps,
|
|
265
|
+
gcTombstoneEnforcementAllowed: this.configs.tombstoneEnforcementAllowed,
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
if (
|
|
269
|
+
(usageType === "Loaded" &&
|
|
270
|
+
this.configs.throwOnTombstoneLoad &&
|
|
271
|
+
!headers?.allowTombstone) ||
|
|
272
|
+
(usageType === "Changed" && this.configs.throwOnTombstoneUsage)
|
|
273
|
+
) {
|
|
274
|
+
this.mc.logger.sendErrorEvent(event);
|
|
275
|
+
} else {
|
|
276
|
+
this.mc.logger.sendTelemetryEvent(event);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
232
280
|
/**
|
|
233
281
|
* Log all new references or outbound routes in the current graph that haven't been explicitly notified to GC.
|
|
234
282
|
* The principle is that every new reference or outbound route must be notified to GC via the
|
package/src/packageVersion.ts
CHANGED