From 53bcb5c788e6b24bf8f6f631445b61a87c5f715f Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 25 Sep 2016 14:51:16 +1300 Subject: Implement server statistics collection --- debug.xml | 9 +++ schema/changelog-3.8.xml | 27 +++++++ src/org/traccar/BaseProtocolDecoder.java | 3 + src/org/traccar/Context.java | 9 +++ src/org/traccar/DeviceSession.java | 3 + src/org/traccar/MainEventHandler.java | 1 + src/org/traccar/api/SecurityRequestFilter.java | 1 + src/org/traccar/api/resource/SessionResource.java | 2 + src/org/traccar/database/DataManager.java | 13 ++++ src/org/traccar/database/StatisticsManager.java | 92 +++++++++++++++++++++++ src/org/traccar/model/Statistics.java | 90 ++++++++++++++++++++++ 11 files changed, 250 insertions(+) create mode 100644 src/org/traccar/database/StatisticsManager.java create mode 100644 src/org/traccar/model/Statistics.java diff --git a/debug.xml b/debug.xml index 6f2ccc738..2314735ca 100644 --- a/debug.xml +++ b/debug.xml @@ -353,6 +353,15 @@ DELETE FROM attribute_aliases WHERE id = :id; + + SELECT * FROM statistics; + + + + INSERT INTO statistics (captureTime, activeUsers, activeDevices, requests, messagesReceived, messagesStored, attributes) + VALUES (:captureTime, :activeUsers, :activeDevices, :requests, :messagesReceived, :messagesStored, :attributes); + + 5001 diff --git a/schema/changelog-3.8.xml b/schema/changelog-3.8.xml index 304ac21d4..deab6603c 100644 --- a/schema/changelog-3.8.xml +++ b/schema/changelog-3.8.xml @@ -39,5 +39,32 @@ speedunit = 'kmh' + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/org/traccar/BaseProtocolDecoder.java b/src/org/traccar/BaseProtocolDecoder.java index 46832a4ca..72b9a7a74 100644 --- a/src/org/traccar/BaseProtocolDecoder.java +++ b/src/org/traccar/BaseProtocolDecoder.java @@ -129,6 +129,9 @@ public abstract class BaseProtocolDecoder extends ExtendedObjectDecoder { @Override protected void onMessageEvent(Channel channel, SocketAddress remoteAddress, Object msg) { + if (Context.getStatisticsManager() != null) { + Context.getStatisticsManager().registerMessageReceived(); + } DeviceSession deviceSession = getDeviceSession(channel, remoteAddress); if (deviceSession != null) { Context.getConnectionManager().updateDevice(deviceSession.getDeviceId(), Device.STATUS_ONLINE, new Date()); diff --git a/src/org/traccar/Context.java b/src/org/traccar/Context.java index 5a3dca878..827761cc5 100644 --- a/src/org/traccar/Context.java +++ b/src/org/traccar/Context.java @@ -25,6 +25,7 @@ import org.traccar.database.IdentityManager; import org.traccar.database.NotificationManager; import org.traccar.database.PermissionsManager; import org.traccar.database.GeofenceManager; +import org.traccar.database.StatisticsManager; import org.traccar.geocode.BingMapsReverseGeocoder; import org.traccar.geocode.FactualReverseGeocoder; import org.traccar.geocode.GeocodeFarmReverseGeocoder; @@ -142,6 +143,12 @@ public final class Context { return aliasesManager; } + private static StatisticsManager statisticsManager; + + public static StatisticsManager getStatisticsManager() { + return statisticsManager; + } + public static void init(String[] arguments) throws Exception { config = new Config(); @@ -245,6 +252,8 @@ public final class Context { aliasesManager = new AliasesManager(dataManager); + statisticsManager = new StatisticsManager(); + } public static void init(IdentityManager testIdentityManager) { diff --git a/src/org/traccar/DeviceSession.java b/src/org/traccar/DeviceSession.java index 5e2686f23..45bc5dcde 100644 --- a/src/org/traccar/DeviceSession.java +++ b/src/org/traccar/DeviceSession.java @@ -21,6 +21,9 @@ public class DeviceSession { public DeviceSession(long deviceId) { this.deviceId = deviceId; + if (Context.getStatisticsManager() != null) { + Context.getStatisticsManager().registerDevice(deviceId); + } } public long getDeviceId() { diff --git a/src/org/traccar/MainEventHandler.java b/src/org/traccar/MainEventHandler.java index 3f7e68b2a..24aa50117 100644 --- a/src/org/traccar/MainEventHandler.java +++ b/src/org/traccar/MainEventHandler.java @@ -62,6 +62,7 @@ public class MainEventHandler extends IdleStateAwareChannelHandler { } Log.info(s.toString()); + Context.getStatisticsManager().registerMessageStored(); } } diff --git a/src/org/traccar/api/SecurityRequestFilter.java b/src/org/traccar/api/SecurityRequestFilter.java index f0dd363db..ff4241b97 100644 --- a/src/org/traccar/api/SecurityRequestFilter.java +++ b/src/org/traccar/api/SecurityRequestFilter.java @@ -55,6 +55,7 @@ public class SecurityRequestFilter implements ContainerRequestFilter { @Override public void filter(ContainerRequestContext requestContext) { + Context.getStatisticsManager().registerRequest(); if (requestContext.getMethod().equals("OPTIONS")) { return; diff --git a/src/org/traccar/api/resource/SessionResource.java b/src/org/traccar/api/resource/SessionResource.java index deed70b37..4ab1960c9 100644 --- a/src/org/traccar/api/resource/SessionResource.java +++ b/src/org/traccar/api/resource/SessionResource.java @@ -73,6 +73,7 @@ public class SessionResource extends BaseResource { } if (userId != null) { + Context.getStatisticsManager().registerUser(userId); return Context.getPermissionsManager().getUser(userId); } else { throw new WebApplicationException(Response.status(Response.Status.NOT_FOUND).build()); @@ -85,6 +86,7 @@ public class SessionResource extends BaseResource { @FormParam("email") String email, @FormParam("password") String password) throws SQLException { User user = Context.getPermissionsManager().login(email, password); if (user != null) { + Context.getStatisticsManager().registerUser(user.getId()); request.getSession().setAttribute(USER_ID_KEY, user.getId()); return user; } else { diff --git a/src/org/traccar/database/DataManager.java b/src/org/traccar/database/DataManager.java index 02adb0455..c58fe40a5 100644 --- a/src/org/traccar/database/DataManager.java +++ b/src/org/traccar/database/DataManager.java @@ -48,6 +48,7 @@ import org.traccar.model.GroupPermission; import org.traccar.model.Notification; import org.traccar.model.Position; import org.traccar.model.Server; +import org.traccar.model.Statistics; import org.traccar.model.User; import org.traccar.model.DeviceGeofence; import org.traccar.model.GeofencePermission; @@ -484,4 +485,16 @@ public class DataManager { .setLong("id", attributeAliasId) .executeUpdate(); } + + public Collection getStatistics() throws SQLException { + return QueryBuilder.create(dataSource, getQuery("database.selectStatistics")) + .executeQuery(Statistics.class); + } + + public void addStatistics(Statistics statistics) throws SQLException { + statistics.setId(QueryBuilder.create(dataSource, getQuery("database.insertStatistics"), true) + .setObject(statistics) + .executeUpdate()); + } + } diff --git a/src/org/traccar/database/StatisticsManager.java b/src/org/traccar/database/StatisticsManager.java new file mode 100644 index 000000000..b21380332 --- /dev/null +++ b/src/org/traccar/database/StatisticsManager.java @@ -0,0 +1,92 @@ +/* + * Copyright 2016 Anton Tananaev (anton.tananaev@gmail.com) + * + * 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 org.traccar.database; + +import org.traccar.Context; +import org.traccar.helper.Log; +import org.traccar.model.Statistics; + +import java.sql.SQLException; +import java.util.Calendar; +import java.util.Date; +import java.util.HashSet; +import java.util.Set; + +public class StatisticsManager { + + private static final int SPLIT_MODE = Calendar.MINUTE; + + private int lastUpdate = Calendar.getInstance().get(SPLIT_MODE); + + private Set users = new HashSet<>(); + private Set devices = new HashSet<>(); + + private int requests; + private int messagesReceived; + private int messagesStored; + + private void checkSplit() { + int currentUpdate = Calendar.getInstance().get(SPLIT_MODE); + if (lastUpdate != currentUpdate) { + Statistics statistics = new Statistics(); + statistics.setCaptureTime(new Date()); + statistics.setActiveUsers(users.size()); + statistics.setActiveDevices(devices.size()); + statistics.setRequests(requests); + statistics.setMessagesReceived(messagesReceived); + statistics.setMessagesStored(messagesStored); + + try { + Context.getDataManager().addStatistics(statistics); + } catch (SQLException e) { + Log.warning(e); + } + + users.clear(); + devices.clear(); + requests = 0; + messagesReceived = 0; + messagesStored = 0; + lastUpdate = currentUpdate; + } + } + + public synchronized void registerUser(long userId) { + checkSplit(); + users.add(userId); + } + + public synchronized void registerDevice(long deviceId) { + checkSplit(); + devices.add(deviceId); + } + + public synchronized void registerRequest() { + checkSplit(); + requests += 1; + } + + public synchronized void registerMessageReceived() { + checkSplit(); + messagesReceived += 1; + } + + public synchronized void registerMessageStored() { + checkSplit(); + messagesStored += 1; + } + +} diff --git a/src/org/traccar/model/Statistics.java b/src/org/traccar/model/Statistics.java new file mode 100644 index 000000000..0461ebd7e --- /dev/null +++ b/src/org/traccar/model/Statistics.java @@ -0,0 +1,90 @@ +/* + * Copyright 2016 Anton Tananaev (anton.tananaev@gmail.com) + * + * 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 org.traccar.model; + +import java.util.Date; + +public class Statistics extends Extensible { + + private Date captureTime; + + public Date getCaptureTime() { + if (captureTime != null) { + return new Date(captureTime.getTime()); + } else { + return null; + } + } + + public void setCaptureTime(Date captureTime) { + if (captureTime != null) { + this.captureTime = new Date(captureTime.getTime()); + } else { + this.captureTime = null; + } + } + + private int activeUsers; + + public int getActiveUsers() { + return activeUsers; + } + + public void setActiveUsers(int activeUsers) { + this.activeUsers = activeUsers; + } + + private int activeDevices; + + public int getActiveDevices() { + return activeDevices; + } + + public void setActiveDevices(int activeDevices) { + this.activeDevices = activeDevices; + } + + private int requests; + + public int getRequests() { + return requests; + } + + public void setRequests(int requests) { + this.requests = requests; + } + + private int messagesReceived; + + public int getMessagesReceived() { + return messagesReceived; + } + + public void setMessagesReceived(int messagesReceived) { + this.messagesReceived = messagesReceived; + } + + private int messagesStored; + + public int getMessagesStored() { + return messagesStored; + } + + public void setMessagesStored(int messagesStored) { + this.messagesStored = messagesStored; + } + +} -- cgit v1.2.3