kris/log_flag_ui
から master
へマージ 4年前
@@ -10,9 +10,13 @@ import lombok.NonNull; | |||
import org.glassfish.jersey.server.ContainerRequest; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import javax.annotation.Nullable; | |||
import javax.ws.rs.*; | |||
import javax.ws.rs.core.Context; | |||
import javax.ws.rs.core.Response; | |||
import java.util.HashMap; | |||
import java.util.Optional; | |||
import java.util.concurrent.TimeUnit; | |||
import static bubble.ApiConstants.*; | |||
import static org.cobbzilla.util.http.HttpContentTypes.APPLICATION_JSON; | |||
@@ -33,17 +37,26 @@ public class LogsResource { | |||
@GET @Path(EP_STATUS) | |||
@NonNull public Response getLoggingStatus(@NonNull @Context final ContainerRequest ctx) { | |||
return ok(selfNodeService.getLogFlag()); | |||
final var flag = new HashMap<String, Object>(2); | |||
flag.put("flag", selfNodeService.getLogFlag()); | |||
flag.put("expireAt", selfNodeService.getLogFlagExpirationTime().orElse(null)); | |||
return ok(flag); | |||
} | |||
@POST @Path(EP_START) | |||
@NonNull public Response startLogging(@NonNull @Context final ContainerRequest ctx) { return setLogFlag(true); } | |||
@NonNull public Response startLogging(@NonNull @Context final ContainerRequest ctx, | |||
@Nullable @QueryParam("ttlDays") final Byte ttlDays) { | |||
return setLogFlag(true, Optional.ofNullable(ttlDays)); | |||
} | |||
@POST @Path(EP_STOP) | |||
@NonNull public Response stopLogging(@NonNull @Context final ContainerRequest ctx) { return setLogFlag(false); } | |||
@NonNull public Response stopLogging(@NonNull @Context final ContainerRequest ctx) { | |||
return setLogFlag(false, Optional.empty()); | |||
} | |||
@NonNull private Response setLogFlag(final boolean b) { | |||
@NonNull private Response setLogFlag(final boolean b, @NonNull final Optional<Byte> ttlInDays) { | |||
if (!account.admin()) throw forbiddenEx(); // caller must be admin | |||
selfNodeService.setLogFlag(b); | |||
selfNodeService.setLogFlag(b, ttlInDays.map(days -> (int) TimeUnit.DAYS.toSeconds(days))); | |||
return ok(); | |||
} | |||
} |
@@ -7,6 +7,9 @@ package bubble.service.boot; | |||
import bubble.model.bill.BubblePlan; | |||
import bubble.model.cloud.BubbleNetwork; | |||
import bubble.model.cloud.BubbleNode; | |||
import lombok.NonNull; | |||
import java.util.Optional; | |||
public interface SelfNodeService { | |||
@@ -24,6 +27,13 @@ public interface SelfNodeService { | |||
BubblePlan getThisPlan(); | |||
Boolean getLogFlag(); | |||
void setLogFlag(final boolean logFlag); | |||
boolean getLogFlag(); | |||
/** | |||
* @return Empty if TTL for log flag is a special one (less than 0), else timestamp (milliseconds) when log flag | |||
* will be expired (to be precise, a very close time after the real expiration time as some time is spent | |||
* for processing here). | |||
*/ | |||
@NonNull Optional<Long> getLogFlagExpirationTime(); | |||
void setLogFlag(final boolean logFlag, @NonNull final Optional<Integer> ttlInSeconds); | |||
} |
@@ -41,6 +41,7 @@ import org.springframework.stereotype.Service; | |||
import java.io.File; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import java.util.Optional; | |||
import java.util.concurrent.atomic.AtomicBoolean; | |||
import java.util.concurrent.atomic.AtomicReference; | |||
@@ -52,8 +53,7 @@ import static bubble.server.BubbleServer.isRestoreMode; | |||
import static java.util.concurrent.TimeUnit.DAYS; | |||
import static java.util.concurrent.TimeUnit.MINUTES; | |||
import static java.util.function.Predicate.not; | |||
import static org.cobbzilla.util.daemon.ZillaRuntime.background; | |||
import static org.cobbzilla.util.daemon.ZillaRuntime.die; | |||
import static org.cobbzilla.util.daemon.ZillaRuntime.*; | |||
import static org.cobbzilla.util.io.FileUtil.abs; | |||
import static org.cobbzilla.util.io.FileUtil.toFileOrDie; | |||
import static org.cobbzilla.util.json.JsonUtil.*; | |||
@@ -72,8 +72,8 @@ public class StandardSelfNodeService implements SelfNodeService { | |||
public static final long MIN_SAGE_KEY_TTL = MINUTES.toMillis(5); | |||
private static final String REDIS_LOG_FLAG_KEY = "bubble_server_logs_enabled"; | |||
private static final long TTL_LOG_FLAG_NODE = DAYS.toSeconds(7); | |||
private static final long TTL_LOG_FLAG_SAGE = DAYS.toSeconds(30); | |||
private static final int TTL_LOG_FLAG_NODE = (int) DAYS.toSeconds(7); | |||
private static final int TTL_LOG_FLAG_SAGE = (int) DAYS.toSeconds(30); | |||
@Autowired private BubbleNodeDAO nodeDAO; | |||
@Autowired private BubbleNodeKeyDAO nodeKeyDAO; | |||
@@ -442,16 +442,22 @@ public class StandardSelfNodeService implements SelfNodeService { | |||
} | |||
@Override | |||
public Boolean getLogFlag() { | |||
if (!getNodeConfig().exists(REDIS_LOG_FLAG_KEY)) return false; | |||
return Boolean.valueOf(getNodeConfig().get_plaintext(REDIS_LOG_FLAG_KEY)); | |||
public boolean getLogFlag() { | |||
var flagStr = getNodeConfig().get_plaintext(REDIS_LOG_FLAG_KEY); | |||
return empty(flagStr) ? false : Boolean.valueOf(flagStr); | |||
} | |||
@Override | |||
public void setLogFlag(final boolean logFlag) { | |||
@NonNull public Optional<Long> getLogFlagExpirationTime() { | |||
var ttl = getNodeConfig().get_ttl(REDIS_LOG_FLAG_KEY); | |||
return ttl < 0 ? Optional.empty() : Optional.of(now() + ttl * 1000); | |||
} | |||
@Override | |||
public void setLogFlag(final boolean logFlag, @NonNull final Optional<Integer> ttlInSeconds) { | |||
if (logFlag) { | |||
getNodeConfig().set_plaintext(REDIS_LOG_FLAG_KEY, "true", EX, | |||
isSelfSage() ? TTL_LOG_FLAG_SAGE : TTL_LOG_FLAG_NODE); | |||
ttlInSeconds.orElse(isSelfSage() ? TTL_LOG_FLAG_SAGE : TTL_LOG_FLAG_NODE)); | |||
} else { | |||
// just (try to) remove the flag | |||
getNodeConfig().del(REDIS_LOG_FLAG_KEY); | |||
@@ -8,8 +8,11 @@ import bubble.model.bill.BubblePlan; | |||
import bubble.model.cloud.BubbleNetwork; | |||
import bubble.model.cloud.BubbleNode; | |||
import bubble.service.boot.SelfNodeService; | |||
import lombok.NonNull; | |||
import org.springframework.stereotype.Service; | |||
import java.util.Optional; | |||
import static org.cobbzilla.util.daemon.ZillaRuntime.notSupported; | |||
@Service | |||
@@ -29,7 +32,12 @@ public class DbFilterSelfNodeService implements SelfNodeService { | |||
@Override public BubblePlan getThisPlan() { return notSupported("getThisPlan"); } | |||
@Override public Boolean getLogFlag() { return notSupported("getLogFlag"); } | |||
@Override public void setLogFlag(boolean logFlag) { notSupported("setLogFlag"); } | |||
@Override public boolean getLogFlag() { return notSupported("getLogFlag"); } | |||
@Override @NonNull public Optional<Long> getLogFlagExpirationTime() { | |||
return notSupported("getLogFlagExpirationTime"); | |||
} | |||
@Override public void setLogFlag(boolean logFlag, @NonNull final Optional<Integer> ttlInSeconds) { | |||
notSupported("setLogFlag"); | |||
} | |||
} |
@@ -250,6 +250,16 @@ button_label_restore=Restore | |||
button_description_restore=You will need full network restore key build from this bubble while if was running. | |||
restore_not_possible_nodes_exist_html=Cannot restore bubbles with existing nodes. Please contact <a href="mailto:support@getbubblenow.com">support@getbubblenow.com</a> | |||
# Network Page - Log flag | |||
node_logs_enabled=logs enabled | |||
node_logs_until=until | |||
button_node_logs_disable=Disable Logs | |||
node_logs_disable_after=Disable Logging After | |||
node_logs_days=Days | |||
button_node_logs_set_disable_after=Set | |||
node_logs_disabled=logs are disabled | |||
button_node_logs_enable=Enable Logs | |||
# Network Page - Danger Zone | |||
title_network_danger_zone=Danger Zone | |||
link_network_action_stop=Stop | |||