All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.couchbase.client.java.bucket.api.Utils Maven / Gradle / Ivy

There is a newer version: 3.7.7
Show newest version
/*
 * Copyright (c) 2018 Couchbase, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.couchbase.client.java.bucket.api;

import com.couchbase.client.core.CouchbaseException;
import com.couchbase.client.core.annotations.InterfaceAudience;
import com.couchbase.client.core.annotations.InterfaceStability;
import com.couchbase.client.core.logging.CouchbaseLogger;
import com.couchbase.client.core.logging.CouchbaseLoggerFactory;
import com.couchbase.client.core.message.CouchbaseRequest;
import com.couchbase.client.core.message.CouchbaseResponse;
import com.couchbase.client.core.message.analytics.AnalyticsRequest;
import com.couchbase.client.core.message.config.ConfigRequest;
import com.couchbase.client.core.message.kv.BinaryRequest;
import com.couchbase.client.core.message.query.QueryRequest;
import com.couchbase.client.core.message.search.SearchRequest;
import com.couchbase.client.core.message.view.ViewRequest;
import com.couchbase.client.core.tracing.ThresholdLogReporter;
import com.couchbase.client.core.utils.DefaultObjectMapper;
import com.couchbase.client.deps.com.fasterxml.jackson.core.JsonProcessingException;
import com.couchbase.client.java.env.CouchbaseEnvironment;
import io.opentracing.Scope;
import io.opentracing.Span;
import rx.Observable;
import rx.functions.Func1;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

@InterfaceAudience.Private
@InterfaceStability.Uncommitted
public class Utils {

    private static final CouchbaseLogger LOGGER = CouchbaseLoggerFactory.getInstance(Utils.class);

    /**
     * Helper method to encapsulate the logic of enriching the exception with detailed status info.
     */
    @InterfaceAudience.Private
    @InterfaceStability.Uncommitted
    public static  X addDetails(X ex, R r) {
        if (r.statusDetails() != null) {
            ex.details(r.statusDetails());
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("{} returned with enhanced error details {}", r, ex);
            }
        }
        return ex;
    }

    /**
     * This method take the given request and produces the correct additional timeout
     * information according to the RFC.
     */
    static String formatTimeout(final CouchbaseRequest request, final long timeout) {
        Map fieldMap = new HashMap();
        fieldMap.put("t", timeout);

        if (request != null) {
            fieldMap.put("s", formatServiceType(request));
            putIfNotNull(fieldMap, "i", request.operationId());
            putIfNotNull(fieldMap, "b", request.bucket());
            putIfNotNull(fieldMap, "c", request.lastLocalId());
            putIfNotNull(fieldMap, "l", request.lastLocalSocket());
            putIfNotNull(fieldMap, "r", request.lastRemoteSocket());
        }

        try {
            return DefaultObjectMapper.writeValueAsString(fieldMap);
        } catch (JsonProcessingException e) {
            LOGGER.warn("Could not format timeout information for request " + request, e);
            return null;
        }
    }

    /**
     * Helper method to avoid ugly if/else blocks in {@link #formatTimeout(CouchbaseRequest, long)}.
     */
    private static void putIfNotNull(final Map map, final String key, final Object value) {
        if (value != null) {
            map.put(key, value);
        }
    }

    /**
     * Helper method to turn the request into the proper string service type.
     */
    private static String formatServiceType(final CouchbaseRequest request) {
        if (request instanceof BinaryRequest) {
            return ThresholdLogReporter.SERVICE_KV;
        } else if (request instanceof QueryRequest) {
            return ThresholdLogReporter.SERVICE_N1QL;
        } else if (request instanceof ViewRequest) {
            return ThresholdLogReporter.SERVICE_VIEW;
        } else if (request instanceof AnalyticsRequest) {
            return ThresholdLogReporter.SERVICE_ANALYTICS;
        } else if (request instanceof SearchRequest) {
            return ThresholdLogReporter.SERVICE_FTS;
        } else if (request instanceof ConfigRequest) {
            // Shouldn't be user visible, but just for completeness sake.
            return "config";
        } else {
            return "unknown";
        }
    }

    public static  Observable applyTimeout(final Observable input, final CouchbaseRequest request,
        final CouchbaseEnvironment environment, final long timeout, final TimeUnit timeUnit) {
        if (timeout > 0) {
            return input
                .timeout(timeout, timeUnit, environment.scheduler())
                .onErrorResumeNext(new Func1>() {
                    @Override
                    public Observable call(Throwable t) {
                        if (t instanceof TimeoutException) {
                            return Observable.error(new TimeoutException(Utils.formatTimeout(
                                request,
                                timeUnit.toMicros(timeout)
                            )));
                        } else {
                            return Observable.error(t);
                        }
                    }
                });
        } else {
            return input;
        }
    }

    public static void addRequestSpan(CouchbaseEnvironment env, CouchbaseRequest request, String opName) {
        if (env.operationTracingEnabled()) {
            if (env.propagateParentSpan()) {
                Span potentialParent = env.tracer().activeSpan();
                if (potentialParent != null) {
                    // there is an active span, use it as a parent
                    addRequestSpanWithParent(env, potentialParent, request, opName);
                    return;
                }
            }

            Scope scope = env.tracer()
                .buildSpan(opName)
                .startActive(false);
            request.span(scope.span(), env);
            scope.close();
        }
    }

    public static void addRequestSpanWithParent(CouchbaseEnvironment env, Span parent, CouchbaseRequest request,
        String opName) {
        if (env.operationTracingEnabled()) {
            Scope scope = env.tracer()
                .buildSpan(opName)
                .asChildOf(parent)
                .startActive(false);
            request.span(scope.span(), env);
            scope.close();
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy