001/*
002 * (C) Copyright 2020 Nuxeo (http://nuxeo.com/) and others.
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 *
016 * Contributors:
017 *     bdelbosc
018 */
019package org.nuxeo.runtime.metrics;
020
021import static org.apache.commons.lang3.StringUtils.isBlank;
022
023import java.net.InetAddress;
024import java.net.URI;
025import java.net.URISyntaxException;
026import java.net.UnknownHostException;
027import java.time.Duration;
028import java.util.Map;
029
030import org.nuxeo.runtime.api.Framework;
031
032import io.opencensus.trace.Tracing;
033import io.opencensus.trace.config.TraceConfig;
034import io.opencensus.trace.config.TraceParams;
035import io.opencensus.trace.samplers.Samplers;
036
037/**
038 * @since 11.1
039 */
040public abstract class AbstractMetricsReporter implements MetricsReporter {
041
042    public static final String URL_OPTION = "url";
043
044    public static final String TIMEOUT_OPTION = "timeout";
045
046    public static final Duration DEFAULT_TIMEOUT = Duration.ofSeconds(10);
047
048    public static final String SERVICE_OPTION = "service";
049
050    public static final String DEFAULT_SERVICE = "nuxeo";
051
052    public static final String MAX_ATTRIBUTES_OPTION = "maxAttributes";
053
054    public static final String DEFAULT_MAX_ATTRIBUTES = "128";
055
056    public static final String MAX_ANNOTATIONS_OPTION = "maxAnnotations";
057
058    public static final String DEFAULT_MAX_ANNOTATIONS = "128";
059
060    public static final String SAMPLER_PROB_OPTION = "samplerProbability";
061
062    public static final String DEFAULT_SAMPLER_PROB = "0.1";
063
064    protected Map<String, String> options;
065
066    protected long pollInterval;
067
068    public void enableTracing() {
069        TraceConfig traceConfig = Tracing.getTraceConfig();
070        TraceParams activeTraceParams = traceConfig.getActiveTraceParams();
071        TraceParams.Builder builder = activeTraceParams.toBuilder();
072        int maxAttributes = Integer.parseInt(options.getOrDefault(MAX_ATTRIBUTES_OPTION, DEFAULT_MAX_ATTRIBUTES));
073        int maxAnnotations = Integer.parseInt(options.getOrDefault(MAX_ANNOTATIONS_OPTION, DEFAULT_MAX_ANNOTATIONS));
074        builder.setMaxNumberOfAttributes(maxAttributes).setMaxNumberOfAnnotations(maxAnnotations);
075        float samplerProbability = Float.parseFloat(options.getOrDefault(SAMPLER_PROB_OPTION, DEFAULT_SAMPLER_PROB));
076        if (samplerProbability >= 0.999) {
077            builder.setSampler(Samplers.alwaysSample());
078        } else if (samplerProbability < 0) {
079            builder.setSampler(Samplers.neverSample());
080        } else {
081            builder.setSampler(Samplers.probabilitySampler(samplerProbability));
082        }
083        traceConfig.updateActiveTraceParams(builder.build());
084    }
085
086    @Override
087    public void init(long pollInterval, Map<String, String> options) {
088        this.options = options;
089        this.pollInterval = pollInterval;
090    }
091
092    protected String getCurrentHostname() {
093        try {
094            return InetAddress.getLocalHost().getHostName().split("\\.")[0];
095        } catch (UnknownHostException e) {
096            return "unknown";
097        }
098    }
099
100    protected long getPollInterval() {
101        return pollInterval;
102    }
103
104    protected String getHostnameFromNuxeoUrl() {
105        try {
106            String url = Framework.getProperty("nuxeo.url");
107            if (isBlank(url)) {
108                return "";
109            }
110            URI uri = new URI(url);
111            String domain = uri.getHost();
112            if (isBlank(domain)) {
113                return "";
114            }
115            return domain.startsWith("www.") ? domain.substring(4) : domain;
116        } catch (URISyntaxException e) {
117            return "";
118        }
119    }
120
121    protected String getOption(String name, String defaultValue) {
122        String value = options.get(name);
123        if (isBlank(value)) {
124            return defaultValue;
125        }
126        return value;
127    }
128
129    protected String requireOption(String name) {
130        return requireOption(name, null);
131    }
132
133    protected String requireOption(String name, String errorMessage) {
134        String value = options.get(name);
135        if (isBlank(value)) {
136            throw new IllegalArgumentException("Metric Reporter configuration requires option: " + name
137                    + (isBlank(errorMessage) ? "" : " " + errorMessage));
138        }
139        return value;
140    }
141
142    protected int getOptionAsInt(String name, int defaultValue) {
143        String value = options.get(name);
144        if (isBlank(value)) {
145            return defaultValue;
146        }
147        return Integer.parseInt(value);
148    }
149
150    protected boolean getOptionAsBoolean(String name, boolean defaultValue) {
151        String value = options.get(name);
152        if (isBlank(value)) {
153            return defaultValue;
154        }
155        return Boolean.parseBoolean(value);
156    }
157
158}