001/* 002 * Copyright 2021 DuraSpace, Inc. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.fcrepo.migration.handlers.ocfl; 017 018import java.io.InputStream; 019import java.time.OffsetDateTime; 020import java.util.List; 021import java.util.stream.Stream; 022 023import io.micrometer.core.instrument.Metrics; 024import io.micrometer.core.instrument.Timer; 025import org.fcrepo.storage.ocfl.CommitType; 026import org.fcrepo.storage.ocfl.OcflObjectSession; 027import org.fcrepo.storage.ocfl.OcflVersionInfo; 028import org.fcrepo.storage.ocfl.ResourceContent; 029import org.fcrepo.storage.ocfl.ResourceHeaders; 030 031/** 032 * A wrapper similar to the FcrepoOcflObjectSessionWrapper to time operations 033 * 034 * @author mikejritter 035 */ 036public class OcflObjectSessionWrapper implements OcflObjectSession { 037 038 private final OcflObjectSession inner; 039 040 private static final String METRIC_NAME = "fcrepo.storage.ocfl.object"; 041 private static final String OPERATION = "operation"; 042 private static final Timer writeTimer = Metrics.timer(METRIC_NAME, OPERATION, "write"); 043 private static final Timer writeHeadersTimer = Metrics.timer(METRIC_NAME, OPERATION, "writeHeaders"); 044 private static final Timer deleteContentTimer = Metrics.timer(METRIC_NAME, OPERATION, "deleteContent"); 045 private static final Timer deleteResourceTimer = Metrics.timer(METRIC_NAME, OPERATION, "deleteResource"); 046 private static final Timer readHeadersTimer = Metrics.timer(METRIC_NAME, OPERATION, "readHeaders"); 047 private static final Timer readContentTimer = Metrics.timer(METRIC_NAME, OPERATION, "readContent"); 048 private static final Timer listVersionsTimer = Metrics.timer(METRIC_NAME, OPERATION, "listVersions"); 049 private static final Timer containsResourceTimer = Metrics.timer(METRIC_NAME, OPERATION, "containsResource"); 050 private static final Timer commitTimer = Metrics.timer(METRIC_NAME, OPERATION, "commit"); 051 052 053 public OcflObjectSessionWrapper(final OcflObjectSession inner) { 054 this.inner = inner; 055 } 056 057 @Override 058 public String sessionId() { 059 return inner.sessionId(); 060 } 061 062 @Override 063 public String ocflObjectId() { 064 return inner.ocflObjectId(); 065 } 066 067 @Override 068 public ResourceHeaders writeResource(final ResourceHeaders headers, final InputStream content) { 069 // The ocfl write further down expects content to be nullable, so if it is null just continue to pass it down 070 final var countingStream = content != null ? new CountingInputStream(content) : null; 071 return writeTimer.record(() -> inner.writeResource(headers, countingStream)); 072 } 073 074 @Override 075 public void writeHeaders(final ResourceHeaders headers) { 076 writeHeadersTimer.record(() -> inner.writeHeaders(headers)); 077 } 078 079 @Override 080 public void deleteContentFile(final ResourceHeaders headers) { 081 deleteContentTimer.record(() -> inner.deleteContentFile(headers)); 082 } 083 084 @Override 085 public void deleteResource(final String resourceId) { 086 deleteResourceTimer.record(() -> inner.deleteResource(resourceId)); 087 } 088 089 @Override 090 public boolean containsResource(final String resourceId) { 091 return containsResourceTimer.record(() -> inner.containsResource(resourceId)); 092 } 093 094 @Override 095 public ResourceHeaders readHeaders(final String resourceId) { 096 return readHeadersTimer.record(() -> inner.readHeaders(resourceId)); 097 } 098 099 @Override 100 public ResourceHeaders readHeaders(final String resourceId, final String versionNumber) { 101 return readHeadersTimer.record(() -> inner.readHeaders(resourceId, versionNumber)); 102 } 103 104 @Override 105 public ResourceContent readContent(final String resourceId) { 106 return readContentTimer.record(() -> inner.readContent(resourceId)); 107 } 108 109 @Override 110 public ResourceContent readContent(final String resourceId, final String versionNumber) { 111 return readContentTimer.record(() -> inner.readContent(resourceId, versionNumber)); 112 } 113 114 @Override 115 public List<OcflVersionInfo> listVersions(final String resourceId) { 116 return listVersionsTimer.record(() -> inner.listVersions(resourceId)); 117 } 118 119 @Override 120 public Stream<ResourceHeaders> streamResourceHeaders() { 121 return inner.streamResourceHeaders(); 122 } 123 124 @Override 125 public void versionCreationTimestamp(final OffsetDateTime timestamp) { 126 inner.versionCreationTimestamp(timestamp); 127 } 128 129 @Override 130 public void versionAuthor(final String name, final String address) { 131 inner.versionAuthor(name, address); 132 } 133 134 @Override 135 public void versionMessage(final String message) { 136 inner.versionMessage(message); 137 } 138 139 @Override 140 public void invalidateCache(final String objectId) { 141 inner.invalidateCache(objectId); 142 } 143 144 @Override 145 public void commitType(final CommitType commitType) { 146 inner.commitType(commitType); 147 } 148 149 @Override 150 public void commit() { 151 commitTimer.record(inner::commit); 152 } 153 154 @Override 155 public void abort() { 156 inner.abort(); 157 } 158 159 @Override 160 public void rollback() { 161 inner.rollback(); 162 } 163 164 @Override 165 public boolean isOpen() { 166 return inner.isOpen(); 167 } 168 169 @Override 170 public void close() { 171 inner.close(); 172 } 173}