1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
|
package com.gitblit.instance;
import com.gitblit.IStoredSettings;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.utils.JsonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import static com.gitblit.utils.JsonUtils.sendJsonString;
public class GitblitInstance
{
private final static String STATS_URL = "https://instats.gitblit.dev/hiitsme/";
private final static Logger LOG = LoggerFactory.getLogger(GitblitInstance.class);
private IRuntimeManager runtimeManager;
private String instanceId;
private GitblitInstanceReport report;
private ScheduledExecutorService executor;
/**
* Initialize the Gitblit instance reporting system.
*
* This will gather the static and dynamic statistics about the running
* instance, so that they can be reported.
*
* @param runtimeManager
* The runtime manager is used to determine the type of instance
* as well as for some other settings and data.
*/
public void init(IRuntimeManager runtimeManager) {
this.runtimeManager = runtimeManager;
// Initialize ID
GitblitInstanceId instanceId = new GitblitInstanceId(runtimeManager.getBaseFolder());
this.instanceId = instanceId.getId().toString();
LOG.info(this.instanceId);
GitblitInstanceStat instanceStat;
if (runtimeManager.getSettings().hasSettings("container.dockerfileVersion")) {
instanceStat = new GitblitInstanceStat(GitblitInstanceStat.GitblitInstanceType.DOCKER);
}
else if (runtimeManager.getStatus().isGO){
instanceStat = new GitblitInstanceStat(GitblitInstanceStat.GitblitInstanceType.GO);
}
else {
instanceStat = new GitblitInstanceStat(GitblitInstanceStat.GitblitInstanceType.WAR);
}
instanceStat.init(runtimeManager.getStatus());
this.report = new GitblitInstanceReport(this.instanceId, instanceStat);
}
public void start()
{
if (shouldRunReports()) {
startReports();
}
}
public void stop()
{
if (this.executor != null && !this.executor.isShutdown() && !this.executor.isTerminated()) {
this.executor.shutdownNow();
System.out.println("Gitblit instance reporting task stopped.");
}
}
/**
* Determine if the reporting task should run.
*
* We do not want to report anything, i.e. the reporting task to run,
* if we are running unit tests or integration tests.
* Instance reports should only be sent for production instances or released versions.
* Therefore we also check if the Gitblit version is a SNAPSHOT version,
* or if the docker image is not a release version, when running from a docker image.
* A docker image running under GOSS should also not report anything.
*/
boolean shouldRunReports()
{
// We can only run reports when we have been initialized
if (this.report == null || this.runtimeManager == null) {
return false;
}
// Check if we are running in a test environment
IStoredSettings settings = this.runtimeManager.getSettings();
if (! settings.getString("gitblit.testReportingUrl", "").isEmpty()) {
// Force reporting to run overriding any test settings
LOG.debug("Enabled reporting to test server URL: {}", settings.getString("gitblit.testReportingUrl", ""));
return true;
}
if (settings.getBoolean("gitblit.testRun", false)) {
return false;
}
// Check if we are running a SNAPSHOT version
if (this.runtimeManager.getStatus().version.endsWith("SNAPSHOT")) {
return false;
}
if (this.report.instanceStat.instanceType == GitblitInstanceStat.GitblitInstanceType.DOCKER) {
// Check if we are running a docker image that is not a release version
if (! settings.getString("container.imageType", "").equals("release")) {
return false;
}
// Check if we are running a docker image under GOSS
if (System.getenv("GITBLIT_GOSS_TEST") != null) {
return false;
}
}
return true;
}
/**
* Start the reporting task.
*
* This will start a thread that runs once a day and sends the instance
* report to the popularity report server.
*/
private void startReports()
{
this.executor = Executors.newSingleThreadScheduledExecutor();
String statsUrl = STATS_URL;
int delay = 24;
int period = 24 * 60; // 24 hours in minutes
TimeUnit unit = TimeUnit.MINUTES;
long retryInterval = 60 * 60 * 1000; // 1 hour in milliseconds
final long retryTimeout = 20 * 60 * 60 * 1000; // 20 hours in milliseconds
// If we are running in a test environment, we will send the reports more frequently
String testUrl = this.runtimeManager.getSettings().getString("gitblit.testReportingUrl", "");
if (! testUrl.isEmpty()) {
statsUrl = testUrl;
delay = 10;
period = 24;
unit = TimeUnit.SECONDS;
retryInterval = 10 * 1000; // 10 seconds in milliseconds
}
final String baseUrl = statsUrl;
final long retryIntervalFinal = retryInterval;
this.executor.scheduleAtFixedRate(new Runnable()
{
@Override
public void run()
{
sendMyStats(baseUrl + instanceId, retryIntervalFinal, retryTimeout);
}
}, delay, period, unit);
}
/**
* Send the instance report to the popularity report server.
*
* This will send a JSON object to the server with the instance report.
*
* @param reportUrl
* The URL to send the report to.
* @param retryInterval
* The interval in milliseconds to wait before retrying to send the report if it failed.
* @param retryTimeout
* The timeout in milliseconds to give up sending the report if it fails repeatedly.
*/
private void sendMyStats(String reportUrl, long retryInterval, long retryTimeout)
{
// Create a HTTP POST request payload
String report = JsonUtils.toJsonString(this.report.fromNow());
int status = 0;
long timeToGiveup = System.currentTimeMillis() + retryTimeout;
while (status != 200 && System.currentTimeMillis() < timeToGiveup) {
try {
status = sendJsonString(reportUrl, report, "gitblitta", "countmein".toCharArray());
if (status != 200) {
LOG.debug("Error sending stats to " + reportUrl + ": " + status);
}
}
catch (IOException e) {
LOG.debug("Exception sending stats to " + reportUrl + ": " + e.getMessage());
}
if (status != 200) {
try {
Thread.sleep(retryInterval);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return; // exit if interrupted
}
}
}
}
}
|