com.speedment.runtime.core.internal.util.Statistics Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of runtime-deploy Show documentation
Show all versions of runtime-deploy Show documentation
A Speedment bundle that shades all dependencies into one jar. This is
useful when deploying an application on a server.
/**
*
* Copyright (c) 2006-2019, Speedment, Inc. All Rights Reserved.
*
* 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.speedment.runtime.core.internal.util;
import com.speedment.common.json.Json;
import com.speedment.common.lazy.LazyLong;
import com.speedment.common.lazy.specialized.LazyString;
import com.speedment.common.logger.Logger;
import com.speedment.common.logger.LoggerManager;
import com.speedment.runtime.config.Dbms;
import com.speedment.runtime.config.Project;
import com.speedment.runtime.core.component.InfoComponent;
import com.speedment.runtime.core.component.ProjectComponent;
import com.speedment.runtime.core.internal.util.testing.TestSettings;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.time.Clock;
import java.time.Instant;
import java.time.ZoneId;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.toList;
/**
* Utility class for reporting events to the statistics manager.
*
* @author Emil Forslund
*/
public final class Statistics {
public enum Event {
GUI_STARTED ("gui-started"),
GUI_PROJECT_LOADED ("gui-project-loaded"),
GENERATE ("generate"),
NODE_STARTED ("node-started"),
NODE_ALIVE ("node-alive"),
NODE_STOPPED ("node-stopped");
private final String eventName;
Event(String eventName) {
this.eventName = eventName;
}
}
private final static Logger LOGGER = LoggerManager.getLogger(Statistics.class);
private final static String PING_URL = "https://service.speedment.com/stats";
public static void report(final InfoComponent info,
final ProjectComponent projects,
final Event event) {
requireNonNull(info);
requireNonNull(projects);
requireNonNull(event);
if (TestSettings.isTestMode()) {
return;
}
final Project project = projects.getProject();
final Map ping = new HashMap<>();
ping.put("userId", InternalEmailUtil.getUserId().toString());
ping.put("appId", project.getAppId());
ping.put("eventType", event.eventName);
ping.put("productName", info.getTitle());
ping.put("productVersion", info.getImplementationVersion());
ping.put("databases", project.dbmses()
.map(Dbms::getTypeName)
.distinct()
.collect(toList())
);
ping.put("emailAddress", InternalEmailUtil.getEmail());
ping.put("computerName", HOST_NAME.getOrCompute(Statistics::getComputerName));
ping.put("dateStarted", STARTED.getOrCompute(
() -> Instant.now(Clock.system(ZoneId.of("UTC"))).getEpochSecond()
));
sendPostRequest(PING_URL, Json.toJson(ping));
}
private static void sendPostRequest(final String url, String data) {
CompletableFuture.runAsync(() -> {
try {
final HttpURLConnection con = (HttpURLConnection)
new URL(url).openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
con.setUseCaches(false);
con.setAllowUserInteraction(false);
con.setDoOutput(true);
con.connect();
try (final OutputStream out = con.getOutputStream()) {
out.write(data.getBytes(StandardCharsets.UTF_8));
out.flush();
}
int status = getResponseCodeFrom(con);
final String text;
try (final BufferedReader rd = new BufferedReader(
new InputStreamReader(status >= 400
? con.getErrorStream()
: con.getInputStream()))) {
final StringBuilder sb = new StringBuilder();
String line;
while ((line = rd.readLine()) != null) {
sb.append(line);
}
text = sb.toString();
}
LOGGER.debug("Statistics response %d: %s", status, text);
} catch (final IOException ex) {
LOGGER.debug(ex);
}
});
}
private static String getComputerName() {
final String hostName;
try {
hostName = InetAddress.getLocalHost().getHostName();
if (hostName != null && !hostName.isEmpty()) {
return hostName;
}
} catch (final Exception ex) {
// Ignore exception.
}
return Optional.ofNullable(System.getenv("COMPUTERNAME"))
.orElseGet(() -> Optional.ofNullable(System.getenv("HOSTNAME"))
.orElse("unknown")
);
}
private static int getResponseCodeFrom(final HttpURLConnection conn)
throws IOException {
try {
return conn.getResponseCode();
} catch (final FileNotFoundException ex) {
return 404;
}
}
private static final LazyString HOST_NAME = LazyString.create();
private static final LazyLong STARTED = LazyLong.create();
/**
* Utility classes should not be instantiated.
*/
private Statistics() {
throw new UnsupportedOperationException();
}
}