]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-15423 Download access.log in system administration page
authorZipeng WU <zipeng.wu@sonarsource.com>
Tue, 2 Nov 2021 11:11:00 +0000 (12:11 +0100)
committersonartech <sonartech@sonarsource.com>
Wed, 3 Nov 2021 20:03:31 +0000 (20:03 +0000)
server/sonar-web/src/main/js/apps/system/components/PageActions.tsx
server/sonar-web/src/main/js/apps/system/components/__tests__/__snapshots__/PageActions-test.tsx.snap
server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/LogsAction.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/platform/ws/LogsActionTest.java

index 8554c67f8741784484d042d4e4035ced756a8280..3604e87eaa32ca13289aa7e5a83babe2a229b1be 100644 (file)
@@ -137,6 +137,16 @@ export default class PageActions extends React.PureComponent<Props, State> {
                     Web Server
                   </a>
                 </li>
+                <li>
+                  <a
+                    download="sonarqube_access.log"
+                    href={logsUrl + '?process=access'}
+                    id="access-logs-link"
+                    rel="noopener noreferrer"
+                    target="_blank">
+                    Access Logs
+                  </a>
+                </li>
               </ul>
             }>
             <Button>
index 6750da1de55e2ae4f7a0adb3adfb2bc4d191a697..01cd2d0dee6790f33e3154cfd43d986a98f228ca 100644 (file)
@@ -72,6 +72,17 @@ exports[`should render correctly 1`] = `
             Web Server
           </a>
         </li>
+        <li>
+          <a
+            download="sonarqube_access.log"
+            href="/api/system/logs?process=access"
+            id="access-logs-link"
+            rel="noopener noreferrer"
+            target="_blank"
+          >
+            Access Logs
+          </a>
+        </li>
       </ul>
     }
   >
@@ -150,6 +161,17 @@ exports[`should render correctly 2`] = `
           Web Server
         </a>
       </li>
+      <li>
+        <a
+          download="sonarqube_access.log"
+          href="/api/system/logs?process=access"
+          id="access-logs-link"
+          rel="noopener noreferrer"
+          target="_blank"
+        >
+          Access Logs
+        </a>
+      </li>
     </ul>
   }
 >
index 715fdde6d185c2dfdffb0048f7681915450496b3..f0e1b2e8b23f674012b2d661b471483229f0e23c 100644 (file)
@@ -32,17 +32,18 @@ import org.apache.commons.io.FileUtils;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
-import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.process.ProcessId;
 import org.sonar.server.log.ServerLogging;
 import org.sonar.server.user.UserSession;
 import org.sonarqube.ws.MediaTypes;
 
 import static java.util.Arrays.stream;
+import static java.util.stream.Collectors.toList;
 
 public class LogsAction implements SystemWsAction {
 
   private static final String PROCESS_PROPERTY = "process";
+  private static final String ACCESS_LOG = "access";
 
   private final UserSession userSession;
   private final ServerLogging serverLogging;
@@ -54,6 +55,10 @@ public class LogsAction implements SystemWsAction {
 
   @Override
   public void define(WebService.NewController controller) {
+    var values = stream(ProcessId.values()).map(ProcessId::getKey).collect(toList());
+    values.add(ACCESS_LOG);
+    values.sort(String::compareTo);
+
     WebService.NewAction action = controller.createAction("logs")
       .setDescription("Get system logs in plain-text format. Requires system administration permission.")
       .setResponseExample(getClass().getResource("logs-example.log"))
@@ -62,10 +67,7 @@ public class LogsAction implements SystemWsAction {
 
     action
       .createParam(PROCESS_PROPERTY)
-      .setPossibleValues(stream(ProcessId.values())
-        .map(ProcessId::getKey)
-        .sorted()
-        .collect(MoreCollectors.toList(ProcessId.values().length)))
+      .setPossibleValues(values)
       .setDefaultValue(ProcessId.APP.getKey())
       .setSince("6.2")
       .setDescription("Process to get logs from");
@@ -76,13 +78,13 @@ public class LogsAction implements SystemWsAction {
     userSession.checkIsSystemAdministrator();
 
     String processKey = wsRequest.mandatoryParam(PROCESS_PROPERTY);
-    ProcessId processId = ProcessId.fromKey(processKey);
+    String filePrefix = ACCESS_LOG.equals(processKey) ? ACCESS_LOG : ProcessId.fromKey(processKey).getLogFilenamePrefix();
 
     File logsDir = serverLogging.getLogsDir();
 
     try (Stream<Path> stream = Files.list(Paths.get(logsDir.getPath()))) {
       Optional<Path> path = stream
-        .filter(p -> p.getFileName().toString().contains(processId.getLogFilenamePrefix())
+        .filter(p -> p.getFileName().toString().contains(filePrefix)
           && p.getFileName().toString().endsWith(".log"))
         .max(Comparator.comparing(Path::toString));
 
index 5d31994b631fa3b8b8fa6c4283e151451191217d..cc7630ad5c83e3e8f7075a95e87579fe618072ef 100644 (file)
@@ -34,6 +34,7 @@ import org.sonar.server.ws.TestResponse;
 import org.sonar.server.ws.WsActionTester;
 import org.sonarqube.ws.MediaTypes;
 
+import static java.util.Arrays.asList;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
@@ -55,7 +56,7 @@ public class LogsActionTest {
   public void values_of_process_parameter_are_names_of_processes() {
     Set<String> values = actionTester.getDef().param("process").possibleValues();
     // values are lower-case and alphabetically ordered
-    assertThat(values).containsExactly("app", "ce", "es", "web");
+    assertThat(values).containsExactly("access", "app", "ce", "es", "web");
   }
 
   @Test
@@ -96,42 +97,18 @@ public class LogsActionTest {
   }
 
   @Test
-  public void get_ce_logs() throws IOException {
+  public void download_logs() throws IOException {
     logInAsSystemAdministrator();
 
     createAllLogsFiles();
 
-    TestResponse response = actionTester.newRequest()
-      .setParam("process", "ce")
-      .execute();
-    assertThat(response.getMediaType()).isEqualTo(MediaTypes.TXT);
-    assertThat(response.getInput()).isEqualTo("{ce}");
-  }
-
-  @Test
-  public void get_es_logs() throws IOException {
-    logInAsSystemAdministrator();
-
-    createAllLogsFiles();
-
-    TestResponse response = actionTester.newRequest()
-      .setParam("process", "es")
-      .execute();
-    assertThat(response.getMediaType()).isEqualTo(MediaTypes.TXT);
-    assertThat(response.getInput()).isEqualTo("{es}");
-  }
-
-  @Test
-  public void get_web_logs() throws IOException {
-    logInAsSystemAdministrator();
-
-    createAllLogsFiles();
-
-    TestResponse response = actionTester.newRequest()
-      .setParam("process", "web")
-      .execute();
-    assertThat(response.getMediaType()).isEqualTo(MediaTypes.TXT);
-    assertThat(response.getInput()).isEqualTo("{web}");
+    asList("ce", "es", "web", "access").forEach(process -> {
+      TestResponse response = actionTester.newRequest()
+        .setParam("process", process)
+        .execute();
+      assertThat(response.getMediaType()).isEqualTo(MediaTypes.TXT);
+      assertThat(response.getInput()).isEqualTo("{" + process + "}");
+    });
   }
 
   @Test
@@ -166,6 +143,7 @@ public class LogsActionTest {
 
   private File createAllLogsFiles() throws IOException {
     File dir = createLogsDir();
+    FileUtils.write(new File(dir, "access.log"), "{access}");
     FileUtils.write(new File(dir, "sonar.log"), "{app}");
     FileUtils.write(new File(dir, "ce.log"), "{ce}");
     FileUtils.write(new File(dir, "es.log"), "{es}");