001/*
002 * Licensed to DuraSpace under one or more contributor license agreements.
003 * See the NOTICE file distributed with this work for additional information
004 * regarding copyright ownership.
005 *
006 * DuraSpace licenses this file to you under the Apache License,
007 * Version 2.0 (the "License"); you may not use this file except in
008 * compliance with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019package org.fcrepo.kernel.impl;
020
021import io.micrometer.core.instrument.Metrics;
022import io.micrometer.core.instrument.Timer;
023import org.fcrepo.common.metrics.MetricsHelper;
024import org.fcrepo.kernel.api.ContainmentIndex;
025import org.fcrepo.kernel.api.identifiers.FedoraId;
026import org.springframework.beans.factory.annotation.Autowired;
027import org.springframework.beans.factory.annotation.Qualifier;
028import org.springframework.stereotype.Component;
029
030import java.time.Instant;
031import java.util.stream.Stream;
032
033/**
034 * ContainmentIndex wrapper for adding metrics
035 *
036 * @author pwinckles
037 */
038@Component("containmentIndex")
039public class ContainmentIndexMetrics implements ContainmentIndex {
040
041    private static final String METRIC_NAME = "fcrepo.db";
042    private static final String DB = "db";
043    private static final String CONTAINMENT = "containment";
044    private static final String OPERATION = "operation";
045
046    private static final Timer getContainsTimer = Metrics.timer(METRIC_NAME,
047            DB, CONTAINMENT, OPERATION, "getContains");
048    private static final Timer getContainsDeletedTimer = Metrics.timer(METRIC_NAME,
049            DB, CONTAINMENT, OPERATION, "getContainsDeleted");
050    private static final Timer getContainsByTimer = Metrics.timer(METRIC_NAME,
051            DB, CONTAINMENT, OPERATION, "getContainsBy");
052    private static final Timer removeContainedByTimer = Metrics.timer(METRIC_NAME,
053            DB, CONTAINMENT, OPERATION, "removeContainedBy");
054    private static final Timer removeResourceTimer = Metrics.timer(METRIC_NAME,
055            DB, CONTAINMENT, OPERATION, "removeResource");
056    private static final Timer purgeResourceTimer = Metrics.timer(METRIC_NAME,
057            DB, CONTAINMENT, OPERATION, "purgeResource");
058    private static final Timer addContainedByTimer = Metrics.timer(METRIC_NAME,
059            DB, CONTAINMENT, OPERATION, "addContainedBy");
060    private static final Timer commitTransactionTimer = Metrics.timer(METRIC_NAME,
061            DB, CONTAINMENT, OPERATION, "commitTransaction");
062    private static final Timer rollbackTransactionTimer = Metrics.timer(METRIC_NAME,
063            DB, CONTAINMENT, OPERATION, "rollbackTransaction");
064    private static final Timer resourceExistsTimer = Metrics.timer(METRIC_NAME,
065            DB, CONTAINMENT, OPERATION, "resourceExists");
066    private static final Timer getContainerIdByPathTimer = Metrics.timer(METRIC_NAME,
067            DB, CONTAINMENT, OPERATION, "getContainerIdByPath");
068    private static final Timer resetTimer = Metrics.timer(METRIC_NAME,
069            DB, CONTAINMENT, OPERATION, "reset");
070    private static final Timer hasResourcesStartingWithTimer = Metrics.timer(METRIC_NAME,
071            DB, CONTAINMENT, OPERATION, "hasResourcesStartingWith");
072
073    @Autowired
074    @Qualifier("containmentIndexImpl")
075    private ContainmentIndex containmentIndexImpl;
076
077    @Override
078    public Stream<String> getContains(final String txId, final FedoraId fedoraId) {
079        return MetricsHelper.time(getContainsTimer, () -> {
080            return containmentIndexImpl.getContains(txId, fedoraId);
081        });
082    }
083
084    @Override
085    public Stream<String> getContainsDeleted(final String txId, final FedoraId fedoraId) {
086        return MetricsHelper.time(getContainsDeletedTimer, () -> {
087            return containmentIndexImpl.getContainsDeleted(txId, fedoraId);
088        });
089    }
090
091    @Override
092    public String getContainedBy(final String txID, final FedoraId resource) {
093        return MetricsHelper.time(getContainsByTimer, () -> {
094            return containmentIndexImpl.getContainedBy(txID, resource);
095        });
096    }
097
098    @Override
099    public void removeContainedBy(final String txID, final FedoraId parent, final FedoraId child) {
100        removeContainedByTimer.record(() -> {
101            containmentIndexImpl.removeContainedBy(txID, parent, child);
102        });
103    }
104
105    @Override
106    public void removeResource(final String txID, final FedoraId resource) {
107        removeResourceTimer.record(() -> {
108            containmentIndexImpl.removeResource(txID, resource);
109        });
110    }
111
112    @Override
113    public void purgeResource(final String txID, final FedoraId resource) {
114        purgeResourceTimer.record(() -> {
115            containmentIndexImpl.purgeResource(txID, resource);
116        });
117    }
118
119    @Override
120    public void addContainedBy(final String txID, final FedoraId parent, final FedoraId child) {
121        addContainedByTimer.record(() -> {
122            containmentIndexImpl.addContainedBy(txID, parent, child);
123        });
124    }
125
126    @Override
127    public void addContainedBy(final String txId, final FedoraId parent, final FedoraId child,
128                               final Instant startTime, final Instant endTime) {
129        addContainedByTimer.record(() -> containmentIndexImpl.addContainedBy(txId, parent, child, startTime, endTime));
130    }
131
132    @Override
133    public void commitTransaction(final String txId) {
134        commitTransactionTimer.record(() -> {
135            containmentIndexImpl.commitTransaction(txId);
136        });
137    }
138
139    @Override
140    public void rollbackTransaction(final String txId) {
141        rollbackTransactionTimer.record(() -> {
142            containmentIndexImpl.rollbackTransaction(txId);
143        });
144    }
145
146    @Override
147    public boolean resourceExists(final String txID, final FedoraId fedoraId, final boolean includeDeleted) {
148        return MetricsHelper.time(resourceExistsTimer, () -> {
149            return containmentIndexImpl.resourceExists(txID, fedoraId, includeDeleted);
150        });
151    }
152
153    @Override
154    public FedoraId getContainerIdByPath(final String txID, final FedoraId fedoraId, final boolean checkDeleted) {
155        return MetricsHelper.time(getContainerIdByPathTimer, () -> {
156            return containmentIndexImpl.getContainerIdByPath(txID, fedoraId, checkDeleted);
157        });
158    }
159
160    @Override
161    public void reset() {
162        resetTimer.record(() -> {
163            containmentIndexImpl.reset();
164        });
165    }
166
167    @Override
168    public boolean hasResourcesStartingWith(final String txId, final FedoraId fedoraId) {
169        return MetricsHelper.time(hasResourcesStartingWithTimer, () ->
170                containmentIndexImpl.hasResourcesStartingWith(txId, fedoraId));
171    }
172}