From 09f129ca06057728d9e60610330afe2625c09da0 Mon Sep 17 00:00:00 2001 From: Bernd Ritter Date: Sat, 4 May 2024 00:04:17 +0200 Subject: [PATCH] =?UTF-8?q?Logging=20von=20nodeId=20f=C3=BCr=20wiki,=20Sta?= =?UTF-8?q?ts=20f=C3=BCr=20wiki?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../db/repositories/NodeAwareRepository.java | 19 +++++++- .../backend/types/StatIntervalType.java | 10 ++++ .../backend/view/NodeStatisticsView.java | 8 ++++ .../web/controller/WikiController.java | 46 ++++++++++++++++--- .../RequestLoggingInterceptor.java | 9 ++-- .../WEB-INF/templates/sites/wiki/show.html | 2 +- .../WEB-INF/templates/sites/wiki/stats.html | 28 +++++++++++ 7 files changed, 110 insertions(+), 12 deletions(-) create mode 100644 src/main/java/de/holarse/backend/types/StatIntervalType.java create mode 100644 src/main/java/de/holarse/backend/view/NodeStatisticsView.java create mode 100644 src/main/webapp/WEB-INF/templates/sites/wiki/stats.html diff --git a/src/main/java/de/holarse/backend/db/repositories/NodeAwareRepository.java b/src/main/java/de/holarse/backend/db/repositories/NodeAwareRepository.java index dc135f67..696302a4 100644 --- a/src/main/java/de/holarse/backend/db/repositories/NodeAwareRepository.java +++ b/src/main/java/de/holarse/backend/db/repositories/NodeAwareRepository.java @@ -1,10 +1,27 @@ package de.holarse.backend.db.repositories; +import de.holarse.backend.view.NodeStatisticsView; import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; public interface NodeAwareRepository { @Query("SELECT nextval('node_sequence')") int nextNodeId(); - + + @Query(value = "SELECT to_char(np.accessed, 'YYYY-MM-DD') as time, sum(1) as amount from node_pagevisits np " + + "WHERE np.nodeid = :nodeId and np.accessed >= now() - interval '1 day' * :days " + + "GROUP BY to_char(np.accessed, 'YYYY-MM-DD') " + + "ORDER BY to_char(np.accessed, 'YYYY-MM-DD')", nativeQuery = true) + List getDailyStats(@Param("nodeId") final Integer nodeId, @Param("days") final int days); + + @Query(value = "SELECT to_char(np.accessed, 'YYYY-MM') as time, sum(1) as amount from node_pagevisits np " + + "WHERE np.nodeid = :nodeId and np.accessed >= now() - interval '1 month' * :months " + + "GROUP BY to_char(np.accessed, 'YYYY-MM') " + + "ORDER BY to_char(np.accessed, 'YYYY-MM')", nativeQuery = true) + List getMonthlyStats(@Param("nodeId") final Integer nodeId, @Param("months") final int months); + + } diff --git a/src/main/java/de/holarse/backend/types/StatIntervalType.java b/src/main/java/de/holarse/backend/types/StatIntervalType.java new file mode 100644 index 00000000..0e45e359 --- /dev/null +++ b/src/main/java/de/holarse/backend/types/StatIntervalType.java @@ -0,0 +1,10 @@ +package de.holarse.backend.types; + +public enum StatIntervalType { + + // Statistiken in täglicher Auflösung + daily, + // Statistiken in monatlicher Auflösung + monthly + +} diff --git a/src/main/java/de/holarse/backend/view/NodeStatisticsView.java b/src/main/java/de/holarse/backend/view/NodeStatisticsView.java new file mode 100644 index 00000000..b06abe97 --- /dev/null +++ b/src/main/java/de/holarse/backend/view/NodeStatisticsView.java @@ -0,0 +1,8 @@ +package de.holarse.backend.view; + +public interface NodeStatisticsView { + + String getTime(); + Integer getAmount(); + +} diff --git a/src/main/java/de/holarse/web/controller/WikiController.java b/src/main/java/de/holarse/web/controller/WikiController.java index 4565dfe9..538a847c 100644 --- a/src/main/java/de/holarse/web/controller/WikiController.java +++ b/src/main/java/de/holarse/web/controller/WikiController.java @@ -7,6 +7,7 @@ import de.holarse.backend.db.repositories.*; import de.holarse.backend.types.AttachmentGroupType; import de.holarse.backend.types.NodeType; +import de.holarse.backend.types.StatIntervalType; import de.holarse.backend.view.*; import static de.holarse.config.JmsQueueTypes.QUEUE_SEARCH; @@ -34,11 +35,7 @@ import org.springframework.security.core.Authentication; import org.springframework.stereotype.Controller; import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.view.RedirectView; @@ -104,12 +101,45 @@ public ModelAndView index(@PageableDefault(sort={"title"}, value=WIKI_ARTICLES_D // return mv; } + + @GetMapping(value = "{slug}", params="stats") + public RedirectView stats(@PathVariable final String slug, final ModelAndView mv) { + final Article article = articleRepository.findBySlug(slug).orElseThrow(EntityNotFoundException::new); + return new RedirectView(String.format("%d/stats", article.getNodeId())); + } + + @GetMapping(value = "{nodeId}/stats") + public ModelAndView stats(@PathVariable final Integer nodeId, + @RequestParam(value="interval", defaultValue = "daily") final StatIntervalType statIntervalType, + @RequestParam(value="amount", defaultValue = "3") final int amount, + final ModelAndView mv) { + mv.setViewName("layouts/bare"); + mv.addObject("title", "Die Linuxspiele-Seite für Linuxspieler"); + mv.addObject(WebDefines.DEFAULT_VIEW_ATTRIBUTE_NAME, "sites/wiki/stats"); + + final Article article = articleRepository.findByNodeId(nodeId).orElseThrow(EntityNotFoundException::new); + final ArticleRevision articleRevision = article.getNodeRevision(); + + final List stats = switch (statIntervalType) { + case daily -> articleRepository.getDailyStats(article.getNodeId(), amount); + case monthly -> articleRepository.getMonthlyStats(article.getNodeId(), amount); + }; + + stats.forEach(s -> logger.debug("Stats: time: {} amount: {}", s.getTime(), s.getAmount())); + + + mv.addObject("title1", articleRevision.getTitle1()); + mv.addObject("interval", statIntervalType); + mv.addObject("amount", amount); + mv.addObject("stats", stats); + return mv; + } @GetMapping(value = "{slug}") public ModelAndView show(@PathVariable("slug") final String slug, final ModelAndView mv, final Principal principal) { mv.setViewName("layouts/bare"); mv.addObject("title", "Die Linuxspiele-Seite für Linuxspieler"); - mv.addObject(WebDefines.DEFAULT_VIEW_ATTRIBUTE_NAME, "sites/wiki/show"); + mv.addObject(WebDefines.DEFAULT_VIEW_ATTRIBUTE_NAME, "sites/wiki/show"); boolean adminOverride = false; @@ -118,7 +148,9 @@ public ModelAndView show(@PathVariable("slug") final String slug, final ModelAnd final Set tags = article.getTags(); final List relevantTagGroups = tags.stream().map(t -> t.getTagGroup()).toList(); final NodeSlug mainSlug = nodeSlugRepository.findMainSlug(articleRevision.getNodeId(), NodeType.article).orElseThrow(EntityNotFoundException::new); - + + mv.addObject("nodeid", article.getNodeId()); + // TODO // if (article.getNodeStatus().isDeleted() || !article.getNodeStatus().isPublished()) { // logger.debug("Principal: {}", principal); diff --git a/src/main/java/de/holarse/web/interceptors/RequestLoggingInterceptor.java b/src/main/java/de/holarse/web/interceptors/RequestLoggingInterceptor.java index d523ffe3..a4cf0924 100644 --- a/src/main/java/de/holarse/web/interceptors/RequestLoggingInterceptor.java +++ b/src/main/java/de/holarse/web/interceptors/RequestLoggingInterceptor.java @@ -57,7 +57,7 @@ public class RequestLoggingInterceptor implements HandlerInterceptor { public void afterCompletion(final HttpServletRequest request, final HttpServletResponse response, final Object handler, final Exception ex) throws Exception { final String requestPath = request.getServletPath(); // Ignorierte URLs nun ja... ignorieren - if (IGNORED_URLS.stream().anyMatch(i -> requestPath.startsWith(i))) { + if (IGNORED_URLS.stream().anyMatch(requestPath::startsWith)) { return; } @@ -80,8 +80,10 @@ public void afterCompletion(final HttpServletRequest request, final HttpServletR //logger.debug("Admin user browsing"); internal = true; } - } - + } + + final Integer nodeId = (Integer) request.getAttribute("nodeid"); + final PageVisit pageVisit = new PageVisit(); pageVisit.setUrl(StringUtils.substring(requestPath, 0, 2083)); pageVisit.setHttpStatus(response.getStatus()); @@ -91,6 +93,7 @@ public void afterCompletion(final HttpServletRequest request, final HttpServletR pageVisit.setVisitorId(request.getRequestedSessionId()); pageVisit.setSearchWord(StringUtils.substring(request.getParameter("q"), 0, 255)); pageVisit.setInternal(internal); + pageVisit.setNodeId(nodeId); pageVisit.setBot(false); if (request.getParameterNames().hasMoreElements()) { diff --git a/src/main/webapp/WEB-INF/templates/sites/wiki/show.html b/src/main/webapp/WEB-INF/templates/sites/wiki/show.html index 5b725ace..fde44464 100644 --- a/src/main/webapp/WEB-INF/templates/sites/wiki/show.html +++ b/src/main/webapp/WEB-INF/templates/sites/wiki/show.html @@ -22,7 +22,7 @@

diff --git a/src/main/webapp/WEB-INF/templates/sites/wiki/stats.html b/src/main/webapp/WEB-INF/templates/sites/wiki/stats.html new file mode 100644 index 00000000..5df55214 --- /dev/null +++ b/src/main/webapp/WEB-INF/templates/sites/wiki/stats.html @@ -0,0 +1,28 @@ +
+
+
+ +
+

Lorem ipsum standard

+
+
+
+ + + + + + + + + + + + + +
ZeitZugriffe
+
+
+
+
+