001/* 002 * Copyright 2023 Anyware Services 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 */ 016package org.ametys.plugins.workspaces.statistics; 017 018import java.util.ArrayList; 019import java.util.List; 020import java.util.Map; 021 022import org.apache.avalon.framework.service.ServiceException; 023import org.apache.avalon.framework.service.ServiceManager; 024import org.apache.avalon.framework.service.Serviceable; 025 026import org.ametys.plugins.repository.AmetysObjectIterable; 027import org.ametys.plugins.workspaces.project.ProjectManager; 028import org.ametys.plugins.workspaces.project.modules.WorkspaceModule; 029import org.ametys.plugins.workspaces.project.modules.WorkspaceModuleExtensionPoint; 030import org.ametys.plugins.workspaces.project.objects.Project; 031import org.ametys.runtime.config.Config; 032import org.ametys.runtime.i18n.I18nizableText; 033import org.ametys.runtime.plugin.component.PluginAware; 034import org.ametys.runtime.plugins.admin.statistics.Statistics; 035import org.ametys.runtime.plugins.admin.statistics.StatisticsNode; 036import org.ametys.runtime.plugins.admin.statistics.StatisticsProvider; 037import org.ametys.runtime.plugins.admin.statistics.StatisticsValue; 038 039/** 040 * Send workspaces statistics 041 */ 042public class WorkspacesStatisticsProvider implements StatisticsProvider, Serviceable, PluginAware 043{ 044 private ProjectManager _projectManager; 045 private WorkspaceModuleExtensionPoint _workspaceModuleEP; 046 private String _id; 047 048 public void service(ServiceManager manager) throws ServiceException 049 { 050 _projectManager = (ProjectManager) manager.lookup(ProjectManager.ROLE); 051 _workspaceModuleEP = (WorkspaceModuleExtensionPoint) manager.lookup(WorkspaceModuleExtensionPoint.ROLE); 052 } 053 054 public void setPluginInfo(String pluginName, String featureName, String id) 055 { 056 _id = id; 057 } 058 059 public Statistics getStatistics() 060 { 061 return new StatisticsNode( 062 _id, 063 new I18nizableText("plugin.workspaces", "PLUGINS_WORKSPACES_STATISTICS_LABEL"), 064 "ametysicon-abecedary4", 065 null, 066 List.of( 067 _configStats(), 068 _projectsStats(), 069 _modulesStats() 070 ), 071 true 072 ); 073 } 074 075 private StatisticsNode _configStats() 076 { 077 boolean configOOPreview = Config.getInstance().getValue("workspaces.onlyoffice.enabled", false, false); 078 boolean configOOEdit = configOOPreview && Config.getInstance().getValue("workspaces.onlyoffice.edition.enabled", false, false); 079 boolean configWebdav = Config.getInstance().getValue("workspaces.msoffice.enabled", false, false); 080 081 return new StatisticsNode( 082 "config", 083 new I18nizableText("plugin.workspaces", "PLUGINS_WORKSPACES_STATISTICS_CONFIG_LABEL"), 084 "ametysicon-gear39", 085 (configOOPreview ? 1 : 0) + (configOOEdit ? 1 : 0) + (configWebdav ? 1 : 0), 086 List.of( 087 new StatisticsValue( 088 "oopreview", 089 new I18nizableText("plugin.workspaces", "PLUGINS_WORKSPACES_STATISTICS_CONFIG_OOPREVIEW_LABEL"), 090 "ametysicon-code-html-picture62", 091 configOOPreview 092 ), 093 new StatisticsValue( 094 "ooedit", 095 new I18nizableText("plugin.workspaces", "PLUGINS_WORKSPACES_STATISTICS_CONFIG_OOEDIT_LABEL"), 096 "ametysicon-editor-indent-more", 097 configOOEdit 098 ), 099 new StatisticsValue( 100 "webdav", 101 new I18nizableText("plugin.workspaces", "PLUGINS_WORKSPACES_STATISTICS_CONFIG_WEBDAV_LABEL"), 102 "ametysicon-file-extension-doc", 103 configWebdav 104 ) 105 ), 106 false 107 ); 108 } 109 110 private StatisticsNode _modulesStats() 111 { 112 List<Map<String, Object>> projectsStatistics = _projectManager.getProjectsStatisticsForClientSide(); 113 114 List<Statistics> modulesStats = new ArrayList<>(); 115 for (WorkspaceModule module : _workspaceModuleEP.getModules()) 116 { 117 modulesStats.add(_moduleStat(projectsStatistics, module)); 118 } 119 120 return new StatisticsNode( 121 "modules", 122 new I18nizableText("plugin.workspaces", "PLUGINS_WORKSPACES_STATISTICS_MODULES_LABEL"), 123 "ametysicon-puzzle-piece1", 124 null, 125 modulesStats, 126 true 127 ); 128 } 129 130 private Statistics _moduleStat(List<Map<String, Object>> projectsStatistics, WorkspaceModule module) 131 { 132 long totalActivated = 0; 133 134 long totalSize = 0; 135 long maxSize = 0; 136 List<Long> sizes = new ArrayList<>(); 137 138 long totalCount = 0; 139 long maxCount = 0; 140 List<Long> counts = new ArrayList<>(); 141 142 for (Map<String, Object> oneProjectStatistics : projectsStatistics) 143 { 144 if ((Boolean) oneProjectStatistics.get(module.getModuleName() + "$activated")) 145 { 146 totalActivated++; 147 148 long size = (Long) oneProjectStatistics.get(module.getModuleName() + "$size"); 149 if (size > 0) // negative size are error messages 150 { 151 totalSize += size; 152 maxSize = Math.max(maxSize, size); 153 sizes.add(size); 154 } 155 156 String numberKey = oneProjectStatistics.keySet().stream().filter(k -> k.startsWith(module.getModuleName() + "$") && k.endsWith("_number")).findFirst().orElse(null); 157 if (numberKey != null) 158 { 159 long count = ((Number) oneProjectStatistics.get(numberKey)).longValue(); 160 totalCount += count; 161 maxCount = Math.max(maxCount, count); 162 counts.add(count); 163 } 164 } 165 } 166 167 counts.sort(null); 168 sizes.sort(null); 169 170 return new StatisticsNode( 171 module.getModuleName(), 172 module.getModuleTitle(), 173 "ametysicon-puzzle33", 174 totalActivated, 175 List.of( 176 new StatisticsNode( 177 "count", 178 new I18nizableText("plugin.workspaces", "PLUGINS_WORKSPACES_STATISTICS_MODULES_COUNT_LABEL"), 179 "ametysicon-maths-abacus", 180 totalCount, 181 List.of( 182 new StatisticsValue( 183 "max", 184 new I18nizableText("plugin.workspaces", "PLUGINS_WORKSPACES_STATISTICS_MODULES_COUNT_MAX_LABEL"), 185 "ametysicon-sort51", 186 maxCount 187 ), 188 new StatisticsValue( 189 "median", 190 new I18nizableText("plugin.workspaces", "PLUGINS_WORKSPACES_STATISTICS_MODULES_COUNT_MEDIAN_LABEL"), 191 "ametysicon-maths-window-symbol-x", 192 counts.size() > 0 ? counts.get(counts.size() / 2) : 0 193 ) 194 ), 195 false 196 ), 197 new StatisticsNode( 198 "size", 199 new I18nizableText("plugin.workspaces", "PLUGINS_WORKSPACES_STATISTICS_MODULES_SIZE_LABEL"), 200 "ametysicon-code-css-letter-spacing", 201 totalSize, 202 List.of( 203 new StatisticsValue( 204 "max", 205 new I18nizableText("plugin.workspaces", "PLUGINS_WORKSPACES_STATISTICS_MODULES_SIZE_MAX_LABEL"), 206 "ametysicon-sort51", 207 maxSize 208 ), 209 new StatisticsValue( 210 "median", 211 new I18nizableText("plugin.workspaces", "PLUGINS_WORKSPACES_STATISTICS_MODULES_SIZE_MEDIAN_LABEL"), 212 "ametysicon-maths-window-symbol-x", 213 sizes.size() > 0 ? sizes.get(sizes.size() / 2) : 0 214 ) 215 ), 216 false 217 ) 218 ), 219 false 220 ); 221 } 222 223 private StatisticsNode _projectsStats() 224 { 225 long nbPrivate = 0; 226 long nbModerated = 0; 227 long nbPublic = 0; 228 229 try (AmetysObjectIterable<Project> projects = _projectManager.getProjects()) 230 { 231 for (Project project : projects) 232 { 233 switch (project.getInscriptionStatus()) 234 { 235 case OPEN: 236 nbPublic++; 237 break; 238 case MODERATED: 239 nbModerated++; 240 break; 241 case PRIVATE: 242 nbPrivate++; 243 break; 244 default: 245 throw new IllegalArgumentException("Unknown inscriptionStatus " + project.getInscriptionStatus().toString() + " for project " + project.getId()); 246 } 247 } 248 } 249 250 return new StatisticsNode( 251 "count", 252 new I18nizableText("plugin.workspaces", "PLUGINS_WORKSPACES_STATISTICS_PROJECTS_LABEL"), 253 "ametysicon-file98", 254 nbPrivate + nbModerated + nbPublic, 255 List.of( 256 new StatisticsValue( 257 "open", 258 new I18nizableText("plugin.workspaces", "PLUGINS_WORKSPACES_STATISTICS_PROJECTS_OPEN_LABEL"), 259 "ametysicon-body-group", 260 nbPublic 261 ), 262 new StatisticsValue( 263 "moderated", 264 new I18nizableText("plugin.workspaces", "PLUGINS_WORKSPACES_STATISTICS_PROJECTS_MODERATED_LABEL"), 265 "ametysicon-body-people-tie", 266 nbModerated 267 ), 268 new StatisticsValue( 269 "private", 270 new I18nizableText("plugin.workspaces", "PLUGINS_WORKSPACES_STATISTICS_PROJECTS_PRIVATE_LABEL"), 271 "ametysicon-body-people", 272 nbPrivate 273 ) 274 ), 275 false 276 ); 277 } 278}