Skip to content

Commit f9d1347

Browse files
committed
BB-721: Use real lifecycle locations for object task metrics.
Resolve delete and restored-object expiration metrics from object metadata so restored objects report their cold location. Issue: BB-721
1 parent 784ad2b commit f9d1347

3 files changed

Lines changed: 51 additions & 1 deletion

File tree

extensions/lifecycle/tasks/LifecycleDeleteObjectTask.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const { HeadObjectCommand, AbortMultipartUploadCommand, DeleteObjectCommand } =
55

66
const BackbeatTask = require('../../../lib/tasks/BackbeatTask');
77
const { LifecycleMetrics } = require('../LifecycleMetrics');
8+
const { resolveLifecycleMetricObjectLocation } = require('../util/lifecycleLocation');
89
const {
910
DeleteObjectFromExpirationCommand,
1011
attachReqUids,
@@ -195,7 +196,10 @@ class LifecycleDeleteObjectTask extends BackbeatTask {
195196

196197
const actionType = entry.getActionType();
197198
const transitionTime = entry.getAttribute('transitionTime');
198-
const location = this.objectMD?.dataStoreName || entry.getAttribute('details.dataStoreName');
199+
const location = resolveLifecycleMetricObjectLocation(
200+
this.objectMD,
201+
entry.getAttribute('details.dataStoreName')
202+
);
199203

200204
let reqMethod = 'deleteObject';
201205
let actionMethod = this._deleteObject.bind(this);

tests/unit/lifecycle/LifecycleDeleteObjectTask.spec.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const { ObjectMD } = require('arsenal').models;
77
const ActionQueueEntry = require('../../../lib/models/ActionQueueEntry');
88
const LifecycleDeleteObjectTask = require(
99
'../../../extensions/lifecycle/tasks/LifecycleDeleteObjectTask');
10+
const { LifecycleMetrics } = require('../../../extensions/lifecycle/LifecycleMetrics');
1011

1112
const day = 1000 * 60 * 60 * 24;
1213

@@ -51,6 +52,7 @@ describe('LifecycleDeleteObjectTask', () => {
5152
});
5253

5354
afterEach(() => {
55+
sinon.restore();
5456
backbeatMdProxyClient.setError(null);
5557
});
5658

@@ -279,6 +281,40 @@ describe('LifecycleDeleteObjectTask', () => {
279281
});
280282
});
281283

284+
it('should emit expiration metrics with restored object cold location', done => {
285+
const requestedAt = new Date(Date.now() - (2 * day)).toISOString();
286+
const completedAt = new Date(Date.now() - day).toISOString();
287+
const expireAt = new Date(Date.now() + day).toISOString();
288+
objMd.setDataStoreName('STANDARD')
289+
.setAmzStorageClass('cold-location')
290+
.setArchive({
291+
archiveInfo: {
292+
archiveId: 'archive-id',
293+
},
294+
restoreRequestedAt: requestedAt,
295+
restoreRequestedDays: 1,
296+
restoreCompletedAt: completedAt,
297+
restoreWillExpireAt: expireAt,
298+
});
299+
const startedMetric = sinon.stub(LifecycleMetrics, 'onLifecycleStarted');
300+
const completedMetric = sinon.stub(LifecycleMetrics, 'onLifecycleCompleted');
301+
const entry = ActionQueueEntry.create('deleteObject')
302+
.setAttribute('target.owner', 'testowner')
303+
.setAttribute('target.bucket', 'testbucket')
304+
.setAttribute('target.accountId', 'testid')
305+
.setAttribute('target.key', 'testkey')
306+
.setAttribute('target.version', 'testversion')
307+
.setAttribute('details.dataStoreName', 'STANDARD')
308+
.setAttribute('transitionTime', Date.now() - day);
309+
backbeatClient.setResponse(null, {});
310+
task.processActionEntry(entry, err => {
311+
assert.ifError(err);
312+
assert.strictEqual(startedMetric.firstCall.args[2], 'cold-location');
313+
assert.strictEqual(completedMetric.firstCall.args[2], 'cold-location');
314+
done();
315+
});
316+
});
317+
282318
it('should fallback to deleteObject method if deleteObjectFromExpiration is not supported', done => {
283319
const entry = ActionQueueEntry.create('deleteObject')
284320
.setAttribute('target.owner', 'testowner')

tests/unit/lifecycle/LifecycleUpdateExpirationTask.spec.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
const assert = require('assert');
2+
const sinon = require('sinon');
23
const werelogs = require('werelogs');
34

45
const { ObjectMD } = require('arsenal').models;
56
const ActionQueueEntry = require('../../../lib/models/ActionQueueEntry');
67
const LifecycleUpdateExpirationTask = require(
78
'../../../extensions/lifecycle/tasks/LifecycleUpdateExpirationTask');
9+
const { LifecycleMetrics } = require('../../../extensions/lifecycle/LifecycleMetrics');
810

911
const {
1012
GarbageCollectorProducerMock,
@@ -60,7 +62,13 @@ describe('LifecycleUpdateExpirationTask', () => {
6062
task = new LifecycleUpdateExpirationTask(objectProcessor);
6163
});
6264

65+
afterEach(() => {
66+
sinon.restore();
67+
});
68+
6369
it('should expire restored object', done => {
70+
const startedMetric = sinon.stub(LifecycleMetrics, 'onLifecycleStarted');
71+
const completedMetric = sinon.stub(LifecycleMetrics, 'onLifecycleCompleted');
6472
const requestedAt = new Date();
6573
const restoreCompletedAt = new Date();
6674
const expireDate = new Date();
@@ -94,6 +102,8 @@ describe('LifecycleUpdateExpirationTask', () => {
94102
const receivedGcEntry = gcProducer.getReceivedEntry();
95103
assert.strictEqual(receivedGcEntry.getActionType(), 'deleteData');
96104
assert.deepStrictEqual(receivedGcEntry.getAttribute('target.locations'), oldLocation);
105+
assert.strictEqual(startedMetric.firstCall.args[2], 'location-dmf-v1');
106+
assert.strictEqual(completedMetric.firstCall.args[2], 'location-dmf-v1');
97107
done();
98108
});
99109
});

0 commit comments

Comments
 (0)