This is an automated email from the ASF dual-hosted git repository. dahn pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/main by this push: new 9a73a2f9e14 Display dates in Quota and Usage messages according to the timezone configurations (#8230) 9a73a2f9e14 is described below commit 9a73a2f9e1433103373e7bd9da8b5feef4479feb Author: Fabricio Duarte <fabricio.duarte...@gmail.com> AuthorDate: Mon Mar 4 08:44:03 2024 -0300 Display dates in Quota and Usage messages according to the timezone configurations (#8230) Co-authored-by: Daniel Augusto Veronezi Salvador <38945620+gutoveron...@users.noreply.github.com> --- .../src/main/java/com/cloud/usage/UsageVO.java | 11 +++- .../cloudstack/quota/QuotaAlertManagerImpl.java | 7 ++- .../apache/cloudstack/quota/QuotaManagerImpl.java | 69 ++++++++++------------ .../apache/cloudstack/quota/vo/QuotaTariffVO.java | 13 +++- .../api/response/QuotaResponseBuilderImpl.java | 26 ++++---- .../apache/cloudstack/quota/QuotaServiceImpl.java | 18 +----- .../cloudstack/quota/QuotaServiceImplTest.java | 1 - .../java/com/cloud/usage/UsageServiceImpl.java | 17 +++--- .../java/com/cloud/usage/UsageManagerImpl.java | 60 +++++++++++-------- .../cloud/usage/parser/IPAddressUsageParser.java | 9 +-- .../usage/parser/LoadBalancerUsageParser.java | 9 +-- .../usage/parser/NetworkOfferingUsageParser.java | 9 +-- .../com/cloud/usage/parser/NetworkUsageParser.java | 10 ++-- .../usage/parser/PortForwardingUsageParser.java | 9 +-- .../usage/parser/SecurityGroupUsageParser.java | 9 +-- .../com/cloud/usage/parser/StorageUsageParser.java | 9 +-- .../cloud/usage/parser/VMInstanceUsageParser.java | 9 +-- .../usage/parser/VMSnapshotOnPrimaryParser.java | 9 +-- .../cloud/usage/parser/VMSnapshotUsageParser.java | 9 +-- .../com/cloud/usage/parser/VPNUserUsageParser.java | 9 +-- .../com/cloud/usage/parser/VmDiskUsageParser.java | 11 ++-- .../com/cloud/usage/parser/VolumeUsageParser.java | 9 +-- utils/src/main/java/com/cloud/utils/DateUtil.java | 17 ++++-- 23 files changed, 196 insertions(+), 163 deletions(-) diff --git a/engine/schema/src/main/java/com/cloud/usage/UsageVO.java b/engine/schema/src/main/java/com/cloud/usage/UsageVO.java index 10b295f593c..50884e3c012 100644 --- a/engine/schema/src/main/java/com/cloud/usage/UsageVO.java +++ b/engine/schema/src/main/java/com/cloud/usage/UsageVO.java @@ -17,6 +17,7 @@ package com.cloud.usage; import java.util.Date; +import java.util.TimeZone; import javax.persistence.Column; import javax.persistence.Entity; @@ -27,9 +28,11 @@ import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.TemporalType; +import com.cloud.utils.DateUtil; import org.apache.cloudstack.api.InternalIdentity; import org.apache.cloudstack.usage.Usage; import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils; +import org.apache.commons.lang3.StringUtils; @Entity @Table(name = "cloud_usage") @@ -400,6 +403,12 @@ public class UsageVO implements Usage, InternalIdentity { @Override public String toString() { - return ReflectionToStringBuilderUtils.reflectOnlySelectedFields(this, "id", "usageId", "usageType", "startDate", "endDate"); + return ReflectionToStringBuilderUtils.reflectOnlySelectedFields(this, "id", "usageId", "usageType"); + } + + public String toString(TimeZone timeZone) { + String startDateString = DateUtil.displayDateInTimezone(timeZone, getStartDate()); + String endDateString = DateUtil.displayDateInTimezone(timeZone, getEndDate()); + return String.format("%s,\"startDate\":\"%s\",\"endDate\":\"%s\"}", StringUtils.chop(this.toString()), startDateString, endDateString); } } diff --git a/framework/quota/src/main/java/org/apache/cloudstack/quota/QuotaAlertManagerImpl.java b/framework/quota/src/main/java/org/apache/cloudstack/quota/QuotaAlertManagerImpl.java index 8d35bb9f434..ff41a8141d7 100644 --- a/framework/quota/src/main/java/org/apache/cloudstack/quota/QuotaAlertManagerImpl.java +++ b/framework/quota/src/main/java/org/apache/cloudstack/quota/QuotaAlertManagerImpl.java @@ -29,6 +29,7 @@ import java.util.concurrent.TimeUnit; import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.utils.DateUtil; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.quota.constant.QuotaConfig; import org.apache.cloudstack.quota.constant.QuotaConfig.QuotaEmailTemplateTypes; @@ -156,9 +157,9 @@ public class QuotaAlertManagerImpl extends ManagerBase implements QuotaAlertMana if (account == null) { continue; // the account is removed } - if (logger.isDebugEnabled()) { - logger.debug("checkAndSendQuotaAlertEmails: Check id=" + account.getId() + " bal=" + accountBalance + ", alertDate=" + alertDate + ", lockable=" + lockable); - } + logger.debug("checkAndSendQuotaAlertEmails: Check id={} bal={}, alertDate={}, lockable={}", account.getId(), + accountBalance, DateUtil.displayDateInTimezone(QuotaManagerImpl.getUsageAggregationTimeZone(), alertDate), + lockable); if (accountBalance.compareTo(zeroBalance) < 0) { if (_lockAccountEnforcement && (lockable == 1)) { if (_quotaManager.isLockable(account)) { diff --git a/framework/quota/src/main/java/org/apache/cloudstack/quota/QuotaManagerImpl.java b/framework/quota/src/main/java/org/apache/cloudstack/quota/QuotaManagerImpl.java index 4293415755a..9c15a47444a 100644 --- a/framework/quota/src/main/java/org/apache/cloudstack/quota/QuotaManagerImpl.java +++ b/framework/quota/src/main/java/org/apache/cloudstack/quota/QuotaManagerImpl.java @@ -49,9 +49,9 @@ import org.apache.cloudstack.usage.UsageUnitTypes; import org.apache.cloudstack.utils.bytescale.ByteScaleUtils; import org.apache.cloudstack.utils.jsinterpreter.JsInterpreter; import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils; -import org.apache.cloudstack.utils.usage.UsageUtils; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.math.NumberUtils; import org.springframework.stereotype.Component; @@ -85,8 +85,7 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager { @Inject protected PresetVariableHelper presetVariableHelper; - private TimeZone _usageTimezone; - private int _aggregationDuration = 0; + private static TimeZone usageAggregationTimeZone = TimeZone.getTimeZone("GMT"); static final BigDecimal GiB_DECIMAL = BigDecimal.valueOf(ByteScaleUtils.GiB); List<Account.Type> lockablesAccountTypes = Arrays.asList(Account.Type.NORMAL, Account.Type.DOMAIN_ADMIN); @@ -112,24 +111,16 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager { mergeConfigs(configs, params); } - String aggregationRange = configs.get("usage.stats.job.aggregation.range"); - String timeZoneStr = configs.get("usage.aggregation.timezone"); - - if (timeZoneStr == null) { - timeZoneStr = "GMT"; - } - _usageTimezone = TimeZone.getTimeZone(timeZoneStr); - - _aggregationDuration = Integer.parseInt(aggregationRange); - if (_aggregationDuration < UsageUtils.USAGE_AGGREGATION_RANGE_MIN) { - logger.warn("Usage stats job aggregation range is to small, using the minimum value of " + UsageUtils.USAGE_AGGREGATION_RANGE_MIN); - _aggregationDuration = UsageUtils.USAGE_AGGREGATION_RANGE_MIN; - } - logger.info("Usage timezone = " + _usageTimezone + " AggregationDuration=" + _aggregationDuration); + String usageAggregationTimeZoneStr = ObjectUtils.defaultIfNull(configs.get("usage.aggregation.timezone"), "GMT"); + usageAggregationTimeZone = TimeZone.getTimeZone(usageAggregationTimeZoneStr); return true; } + public static TimeZone getUsageAggregationTimeZone() { + return usageAggregationTimeZone; + } + @Override public boolean start() { if (logger.isInfoEnabled()) { @@ -158,8 +149,9 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager { Date startDate = firstQuotaUsage.getStartDate(); Date endDate = firstQuotaUsage.getStartDate(); - logger.info(String.format("Processing quota balance for account [%s] between [%s] and [%s].", accountToString, startDate, - accountQuotaUsages.get(accountQuotaUsages.size() - 1).getEndDate())); + logger.info("Processing quota balance for account [{}] between [{}] and [{}].", accountToString, + DateUtil.displayDateInTimezone(usageAggregationTimeZone, startDate), + DateUtil.displayDateInTimezone(usageAggregationTimeZone, accountQuotaUsages.get(accountQuotaUsages.size() - 1).getEndDate())); BigDecimal aggregatedUsage = BigDecimal.ZERO; long accountId = accountVo.getAccountId(); @@ -246,17 +238,20 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager { protected BigDecimal aggregateCreditBetweenDates(Long accountId, Long domainId, Date startDate, Date endDate, String accountToString) { List<QuotaBalanceVO> creditsReceived = _quotaBalanceDao.findCreditBalance(accountId, domainId, startDate, endDate); - logger.debug(String.format("Account [%s] has [%s] credit entries before [%s].", accountToString, creditsReceived.size(), endDate)); + logger.debug("Account [{}] has [{}] credit entries before [{}].", accountToString, creditsReceived.size(), + DateUtil.displayDateInTimezone(usageAggregationTimeZone, endDate)); BigDecimal aggregatedUsage = BigDecimal.ZERO; - logger.debug(String.format("Aggregating the account [%s] credit entries before [%s].", accountToString, endDate)); + logger.debug("Aggregating the account [{}] credit entries before [{}].", accountToString, + DateUtil.displayDateInTimezone(usageAggregationTimeZone, endDate)); for (QuotaBalanceVO credit : creditsReceived) { aggregatedUsage = aggregatedUsage.add(credit.getCreditBalance()); } - logger.debug(String.format("The aggregation of the account [%s] credit entries before [%s] resulted in the value [%s].", accountToString, endDate, aggregatedUsage)); + logger.debug("The aggregation of the account [{}] credit entries before [{}] resulted in the value [{}].", + accountToString, DateUtil.displayDateInTimezone(usageAggregationTimeZone, endDate), aggregatedUsage); return aggregatedUsage; } @@ -306,7 +301,7 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager { protected List<QuotaUsageVO> createQuotaUsagesAccordingToQuotaTariffs(AccountVO account, List<UsageVO> usageRecords, Map<Integer, Pair<List<QuotaTariffVO>, Boolean>> mapQuotaTariffsPerUsageType) { String accountToString = account.reflectionToString(); - logger.info(String.format("Calculating quota usage of [%s] usage records for account [%s].", usageRecords.size(), accountToString)); + logger.info("Calculating quota usage of [{}] usage records for account [{}].", usageRecords.size(), accountToString); List<Pair<UsageVO, QuotaUsageVO>> pairsUsageAndQuotaUsage = new ArrayList<>(); @@ -314,7 +309,7 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager { for (UsageVO usageRecord : usageRecords) { int usageType = usageRecord.getUsageType(); - if (Boolean.FALSE.equals(shouldCalculateUsageRecord(account,usageRecord))) { + if (!shouldCalculateUsageRecord(account, usageRecord)) { pairsUsageAndQuotaUsage.add(new Pair<>(usageRecord, null)); continue; } @@ -339,8 +334,8 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager { protected boolean shouldCalculateUsageRecord(AccountVO accountVO, UsageVO usageRecord) { if (Boolean.FALSE.equals(QuotaConfig.QuotaAccountEnabled.valueIn(accountVO.getAccountId()))) { - logger.debug(String.format("Considering usage record [%s] as calculated and skipping it because account [%s] has the quota plugin disabled.", - usageRecord, accountVO.reflectionToString())); + logger.debug("Considering usage record [{}] as calculated and skipping it because account [{}] has the quota plugin disabled.", + usageRecord.toString(usageAggregationTimeZone), accountVO.reflectionToString()); return false; } return true; @@ -366,9 +361,8 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager { protected BigDecimal aggregateQuotaTariffsValues(UsageVO usageRecord, List<QuotaTariffVO> quotaTariffs, boolean hasAnyQuotaTariffWithActivationRule, JsInterpreter jsInterpreter, String accountToString) { - String usageRecordToString = usageRecord.toString(); - logger.debug(String.format("Validating usage record [%s] for account [%s] against [%s] quota tariffs.", usageRecordToString, accountToString, - quotaTariffs.size())); + String usageRecordToString = usageRecord.toString(usageAggregationTimeZone); + logger.debug("Validating usage record [{}] for account [{}] against [{}] quota tariffs.", usageRecordToString, accountToString, quotaTariffs.size()); PresetVariables presetVariables = getPresetVariables(hasAnyQuotaTariffWithActivationRule, usageRecord); BigDecimal aggregatedQuotaTariffsValue = BigDecimal.ZERO; @@ -406,7 +400,7 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager { protected BigDecimal getQuotaTariffValueToBeApplied(QuotaTariffVO quotaTariff, JsInterpreter jsInterpreter, PresetVariables presetVariables) { String activationRule = quotaTariff.getActivationRule(); BigDecimal quotaTariffValue = quotaTariff.getCurrencyValue(); - String quotaTariffToString = quotaTariff.toString(); + String quotaTariffToString = quotaTariff.toString(usageAggregationTimeZone); if (StringUtils.isEmpty(activationRule)) { logger.debug(String.format("Quota tariff [%s] does not have an activation rule, therefore we will use the quota tariff value [%s] in the calculation.", @@ -468,10 +462,11 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager { Date quotaTariffEndDate = quotaTariff.getEndDate(); if ((quotaTariffEndDate != null && usageRecordStartDate.after(quotaTariffEndDate)) || usageRecordEndDate.before(quotaTariffStartDate)) { - logger.debug(String.format("Not applying quota tariff [%s] in usage record [%s] of account [%s] due to it is out of the period to be applied. Period of the usage" - + " record [startDate: %s, endDate: %s], period of the quota tariff [startDate: %s, endDate: %s].", quotaTariff, usageRecord.toString(), accountToString, - DateUtil.getOutputString(usageRecordStartDate), DateUtil.getOutputString(usageRecordEndDate), DateUtil.getOutputString(quotaTariffStartDate), - DateUtil.getOutputString(quotaTariffEndDate))); + logger.debug("Not applying quota tariff [{}] in usage record [{}] of account [{}] due to it is out of the period to be applied. Period of the usage" + + " record [startDate: {}, endDate: {}], period of the quota tariff [startDate: {}, endDate: {}].", quotaTariff.toString(usageAggregationTimeZone), + usageRecord.toString(usageAggregationTimeZone), accountToString, DateUtil.displayDateInTimezone(usageAggregationTimeZone, usageRecordStartDate), + DateUtil.displayDateInTimezone(usageAggregationTimeZone, usageRecordEndDate), DateUtil.displayDateInTimezone(usageAggregationTimeZone, quotaTariffStartDate), + DateUtil.displayDateInTimezone(usageAggregationTimeZone, quotaTariffEndDate)); return false; } @@ -497,11 +492,11 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager { } protected QuotaUsageVO createQuotaUsageAccordingToUsageUnit(UsageVO usageRecord, BigDecimal aggregatedQuotaTariffsValue, String accountToString) { - String usageRecordToString = usageRecord.toString(); + String usageRecordToString = usageRecord.toString(usageAggregationTimeZone); if (aggregatedQuotaTariffsValue.equals(BigDecimal.ZERO)) { - logger.debug(String.format("Usage record [%s] for account [%s] does not have quota tariffs to be calculated, therefore we will mark it as calculated.", - usageRecordToString, accountToString)); + logger.debug("No tariffs were applied to usage record [{}] of account [{}] or they resulted in 0; We will only mark the usage record as calculated.", + usageRecordToString, accountToString); return null; } diff --git a/framework/quota/src/main/java/org/apache/cloudstack/quota/vo/QuotaTariffVO.java b/framework/quota/src/main/java/org/apache/cloudstack/quota/vo/QuotaTariffVO.java index 7bc2870e36a..5b07cadb94a 100644 --- a/framework/quota/src/main/java/org/apache/cloudstack/quota/vo/QuotaTariffVO.java +++ b/framework/quota/src/main/java/org/apache/cloudstack/quota/vo/QuotaTariffVO.java @@ -16,11 +16,13 @@ //under the License. package org.apache.cloudstack.quota.vo; +import com.cloud.utils.DateUtil; import org.apache.cloudstack.api.InternalIdentity; import org.apache.cloudstack.quota.constant.QuotaTypes; import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils; import com.cloud.utils.db.GenericDao; +import org.apache.commons.lang3.StringUtils; import javax.persistence.Column; import javax.persistence.Entity; @@ -33,6 +35,7 @@ import javax.persistence.TemporalType; import java.math.BigDecimal; import java.util.Date; +import java.util.TimeZone; import java.util.UUID; @Entity @@ -261,6 +264,12 @@ public class QuotaTariffVO implements InternalIdentity { @Override public String toString() { - return ReflectionToStringBuilderUtils.reflectOnlySelectedFields(this, "uuid", "name", "effectiveOn", "endDate"); - }; + return ReflectionToStringBuilderUtils.reflectOnlySelectedFields(this, "uuid", "name", "usageName"); + } + + public String toString(TimeZone timeZone) { + String startDateString = DateUtil.displayDateInTimezone(timeZone, getEffectiveOn()); + String endDateString = DateUtil.displayDateInTimezone(timeZone, getEndDate()); + return String.format("%s,\"startDate\":\"%s\",\"endDate\":\"%s\"}", StringUtils.chop(this.toString()), startDateString, endDateString); + } } diff --git a/plugins/database/quota/src/main/java/org/apache/cloudstack/api/response/QuotaResponseBuilderImpl.java b/plugins/database/quota/src/main/java/org/apache/cloudstack/api/response/QuotaResponseBuilderImpl.java index eb667b00c3b..d7f2832831a 100644 --- a/plugins/database/quota/src/main/java/org/apache/cloudstack/api/response/QuotaResponseBuilderImpl.java +++ b/plugins/database/quota/src/main/java/org/apache/cloudstack/api/response/QuotaResponseBuilderImpl.java @@ -34,6 +34,7 @@ import java.util.function.Consumer; import javax.inject.Inject; +import com.cloud.utils.DateUtil; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.command.QuotaBalanceCmd; @@ -44,6 +45,7 @@ import org.apache.cloudstack.api.command.QuotaTariffCreateCmd; import org.apache.cloudstack.api.command.QuotaTariffListCmd; import org.apache.cloudstack.api.command.QuotaTariffUpdateCmd; import org.apache.cloudstack.quota.QuotaManager; +import org.apache.cloudstack.quota.QuotaManagerImpl; import org.apache.cloudstack.quota.QuotaService; import org.apache.cloudstack.quota.QuotaStatement; import org.apache.cloudstack.quota.constant.QuotaConfig; @@ -470,12 +472,14 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder { } if (endDate.compareTo(startDate) < 0) { - throw new InvalidParameterValueException(String.format("The quota tariff's end date [%s] cannot be less than the start date [%s]", endDate, startDate)); + throw new InvalidParameterValueException(String.format("The quota tariff's end date [%s] cannot be less than the start date [%s].", + endDate, startDate)); } Date now = _quotaService.computeAdjustedTime(new Date()); if (endDate.compareTo(now) < 0) { - throw new InvalidParameterValueException(String.format("The quota tariff's end date [%s] cannot be less than now [%s].", endDate, now)); + throw new InvalidParameterValueException(String.format("The quota tariff's end date [%s] cannot be less than now [%s].", + endDate, now)); } newQuotaTariff.setEndDate(endDate); @@ -487,7 +491,8 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder { QuotaBalanceVO qb = _quotaBalanceDao.findLaterBalanceEntry(accountId, domainId, despositedOn); if (qb != null) { - throw new InvalidParameterValueException("Incorrect deposit date: " + despositedOn + " there are balance entries after this date"); + throw new InvalidParameterValueException(String.format("Incorrect deposit date [%s], as there are balance entries after this date.", + despositedOn)); } QuotaCreditsVO credits = new QuotaCreditsVO(accountId, domainId, new BigDecimal(amount), updatedBy); @@ -500,9 +505,8 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder { } final boolean lockAccountEnforcement = "true".equalsIgnoreCase(QuotaConfig.QuotaEnableEnforcement.value()); final BigDecimal currentAccountBalance = _quotaBalanceDao.lastQuotaBalance(accountId, domainId, startOfNextDay(new Date(despositedOn.getTime()))); - if (logger.isDebugEnabled()) { - logger.debug("AddQuotaCredits: Depositing " + amount + " on adjusted date " + despositedOn + ", current balance " + currentAccountBalance); - } + logger.debug("Depositing [{}] credits on adjusted date [{}]; current balance is [{}].", amount, + DateUtil.displayDateInTimezone(QuotaManagerImpl.getUsageAggregationTimeZone(), despositedOn), currentAccountBalance); // update quota account with the balance _quotaService.saveQuotaAccount(account, currentAccountBalance, despositedOn); if (lockAccountEnforcement) { @@ -581,9 +585,10 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder { QuotaBalanceResponse resp = new QuotaBalanceResponse(); BigDecimal lastCredits = new BigDecimal(0); for (QuotaBalanceVO entry : quotaBalance) { - if (logger.isDebugEnabled()) { - logger.debug("createQuotaLastBalanceResponse Date=" + entry.getUpdatedOn() + " balance=" + entry.getCreditBalance() + " credit=" + entry.getCreditsId()); - } + logger.debug("createQuotaLastBalanceResponse Date={} balance={} credit={}", + DateUtil.displayDateInTimezone(QuotaManagerImpl.getUsageAggregationTimeZone(), entry.getUpdatedOn()), + entry.getCreditBalance(), entry.getCreditsId()); + lastCredits = lastCredits.add(entry.getCreditBalance()); } resp.setStartQuota(lastCredits); @@ -638,7 +643,8 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder { } if (startDate.compareTo(now) < 0) { - throw new InvalidParameterValueException(String.format("The quota tariff's start date [%s] cannot be less than now [%s]", startDate, now)); + throw new InvalidParameterValueException(String.format("The value passed as Quota tariff's start date is in the past: [%s]. " + + "Please, inform a date in the future or do not pass the parameter to use the current date and time.", startDate)); } return persistNewQuotaTariff(null, name, usageType, startDate, cmd.getEntityOwnerId(), endDate, value, description, activationRule); diff --git a/plugins/database/quota/src/main/java/org/apache/cloudstack/quota/QuotaServiceImpl.java b/plugins/database/quota/src/main/java/org/apache/cloudstack/quota/QuotaServiceImpl.java index bd08f6afd7e..88a69c47e05 100644 --- a/plugins/database/quota/src/main/java/org/apache/cloudstack/quota/QuotaServiceImpl.java +++ b/plugins/database/quota/src/main/java/org/apache/cloudstack/quota/QuotaServiceImpl.java @@ -51,7 +51,7 @@ import org.apache.cloudstack.quota.dao.QuotaUsageDao; import org.apache.cloudstack.quota.vo.QuotaAccountVO; import org.apache.cloudstack.quota.vo.QuotaBalanceVO; import org.apache.cloudstack.quota.vo.QuotaUsageVO; -import org.apache.cloudstack.utils.usage.UsageUtils; +import org.apache.commons.lang3.ObjectUtils; import org.springframework.stereotype.Component; import com.cloud.configuration.Config; @@ -83,7 +83,6 @@ public class QuotaServiceImpl extends ManagerBase implements QuotaService, Confi private QuotaResponseBuilder _respBldr; private TimeZone _usageTimezone; - private int _aggregationDuration = 0; public QuotaServiceImpl() { super(); @@ -92,21 +91,10 @@ public class QuotaServiceImpl extends ManagerBase implements QuotaService, Confi @Override public boolean configure(String name, Map<String, Object> params) throws ConfigurationException { super.configure(name, params); - String timeZoneStr = _configDao.getValue(Config.UsageAggregationTimezone.toString()); - String aggregationRange = _configDao.getValue(Config.UsageStatsJobAggregationRange.toString()); - if (timeZoneStr == null) { - timeZoneStr = "GMT"; - } + + String timeZoneStr = ObjectUtils.defaultIfNull(_configDao.getValue(Config.UsageAggregationTimezone.toString()), "GMT"); _usageTimezone = TimeZone.getTimeZone(timeZoneStr); - _aggregationDuration = Integer.parseInt(aggregationRange); - if (_aggregationDuration < UsageUtils.USAGE_AGGREGATION_RANGE_MIN) { - logger.warn("Usage stats job aggregation range is to small, using the minimum value of " + UsageUtils.USAGE_AGGREGATION_RANGE_MIN); - _aggregationDuration = UsageUtils.USAGE_AGGREGATION_RANGE_MIN; - } - if (logger.isDebugEnabled()) { - logger.debug("Usage timezone = " + _usageTimezone + " AggregationDuration=" + _aggregationDuration); - } return true; } diff --git a/plugins/database/quota/src/test/java/org/apache/cloudstack/quota/QuotaServiceImplTest.java b/plugins/database/quota/src/test/java/org/apache/cloudstack/quota/QuotaServiceImplTest.java index 0b9d34daa70..fa58c35ea5d 100644 --- a/plugins/database/quota/src/test/java/org/apache/cloudstack/quota/QuotaServiceImplTest.java +++ b/plugins/database/quota/src/test/java/org/apache/cloudstack/quota/QuotaServiceImplTest.java @@ -99,7 +99,6 @@ public class QuotaServiceImplTest extends TestCase { QuotaResponseBuilderField.set(quotaService, respBldr); Mockito.when(configDao.getValue(Mockito.eq(Config.UsageAggregationTimezone.toString()))).thenReturn("IST"); - Mockito.when(configDao.getValue(Mockito.eq(Config.UsageStatsJobAggregationRange.toString()))).thenReturn("1"); quotaService.configure("randomName", null); } diff --git a/server/src/main/java/com/cloud/usage/UsageServiceImpl.java b/server/src/main/java/com/cloud/usage/UsageServiceImpl.java index 6d6a05cac19..3398e3ba571 100644 --- a/server/src/main/java/com/cloud/usage/UsageServiceImpl.java +++ b/server/src/main/java/com/cloud/usage/UsageServiceImpl.java @@ -27,6 +27,7 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; import com.cloud.domain.Domain; +import com.cloud.utils.DateUtil; import org.apache.cloudstack.api.command.admin.usage.GenerateUsageRecordsCmd; import org.apache.cloudstack.api.command.admin.usage.ListUsageRecordsCmd; import org.apache.cloudstack.api.command.admin.usage.RemoveRawUsageRecordsCmd; @@ -36,6 +37,7 @@ import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.usage.Usage; import org.apache.cloudstack.usage.UsageService; import org.apache.cloudstack.usage.UsageTypes; +import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; import org.springframework.stereotype.Component; @@ -97,7 +99,7 @@ public class UsageServiceImpl extends ManagerBase implements UsageService, Manag private ConfigurationDao _configDao; @Inject private ProjectManager _projectMgr; - private TimeZone _usageTimezone; + private TimeZone _usageTimezone = TimeZone.getTimeZone("GMT"); @Inject private AccountService _accountService; @Inject @@ -127,10 +129,7 @@ public class UsageServiceImpl extends ManagerBase implements UsageService, Manag @Override public boolean configure(String name, Map<String, Object> params) throws ConfigurationException { super.configure(name, params); - String timeZoneStr = _configDao.getValue(Config.UsageAggregationTimezone.toString()); - if (timeZoneStr == null) { - timeZoneStr = "GMT"; - } + String timeZoneStr = ObjectUtils.defaultIfNull(_configDao.getValue(Config.UsageAggregationTimezone.toString()), "GMT"); _usageTimezone = TimeZone.getTimeZone(timeZoneStr); return true; } @@ -211,10 +210,10 @@ public class UsageServiceImpl extends ManagerBase implements UsageService, Manag Date adjustedStartDate = computeAdjustedTime(startDate, usageTZ); Date adjustedEndDate = computeAdjustedTime(endDate, usageTZ); - if (logger.isDebugEnabled()) { - logger.debug("getting usage records for account: " + accountId + ", domainId: " + domainId + ", between " + adjustedStartDate + " and " + adjustedEndDate + - ", using pageSize: " + cmd.getPageSizeVal() + " and startIndex: " + cmd.getStartIndex()); - } + logger.debug("Getting usage records for account ID [{}], domain ID [{}] between [{}] and [{}] using page size [{}] and start index [{}].", + accountId, domainId, DateUtil.displayDateInTimezone(_usageTimezone, adjustedStartDate), + DateUtil.displayDateInTimezone(_usageTimezone, adjustedEndDate), cmd.getPageSizeVal(), + cmd.getStartIndex()); Filter usageFilter = new Filter(UsageVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal()); diff --git a/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java b/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java index 10ca798a82c..a21fe6251de 100644 --- a/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java +++ b/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java @@ -61,6 +61,7 @@ import com.cloud.user.VmDiskStatisticsVO; import com.cloud.user.dao.AccountDao; import com.cloud.user.dao.UserStatisticsDao; import com.cloud.user.dao.VmDiskStatisticsDao; +import com.cloud.utils.DateUtil; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.concurrency.NamedThreadFactory; import com.cloud.utils.db.DB; @@ -172,7 +173,6 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna private boolean _runQuota=false; String _hostname = null; int _pid = 0; - TimeZone _usageTimezone = TimeZone.getTimeZone("GMT");; private final GlobalLock _heartbeatLock = GlobalLock.getInternLock("usage.job.heartbeat.check"); private final List<UsageNetworkVO> usageNetworks = new ArrayList<UsageNetworkVO>(); private final List<UsageVmDiskVO> usageVmDisks = new ArrayList<UsageVmDiskVO>(); @@ -184,6 +184,7 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna private Future _heartbeat = null; private Future _sanity = null; private boolean usageSnapshotSelection = false; + private static TimeZone usageAggregationTimeZone = TimeZone.getTimeZone("GMT"); public UsageManagerImpl() { } @@ -226,7 +227,7 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna String execTime = configs.get("usage.stats.job.exec.time"); String aggregationRange = configs.get("usage.stats.job.aggregation.range"); String execTimeZone = configs.get("usage.execution.timezone"); - String aggreagationTimeZone = configs.get("usage.aggregation.timezone"); + String aggregationTimeZone = configs.get("usage.aggregation.timezone"); String sanityCheckInterval = configs.get("usage.sanity.check.interval"); String quotaEnable = configs.get("quota.enable.service"); _runQuota = Boolean.valueOf(quotaEnable == null ? "false" : quotaEnable ); @@ -235,10 +236,9 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna _sanityCheckInterval = Integer.parseInt(sanityCheckInterval); } - if (aggreagationTimeZone != null && !aggreagationTimeZone.isEmpty()) { - _usageTimezone = TimeZone.getTimeZone(aggreagationTimeZone); + if (aggregationTimeZone != null && !aggregationTimeZone.isEmpty()) { + usageAggregationTimeZone = TimeZone.getTimeZone(aggregationTimeZone); } - logger.debug("Usage stats aggregation time zone: " + aggreagationTimeZone); try { if ((execTime == null) || (aggregationRange == null)) { @@ -254,25 +254,27 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna } int hourOfDay = Integer.parseInt(execTimeSegments[0]); int minutes = Integer.parseInt(execTimeSegments[1]); - _jobExecTime.setTime(new Date()); + + Date currentDate = new Date(); + _jobExecTime.setTime(currentDate); _jobExecTime.set(Calendar.HOUR_OF_DAY, hourOfDay); _jobExecTime.set(Calendar.MINUTE, minutes); _jobExecTime.set(Calendar.SECOND, 0); _jobExecTime.set(Calendar.MILLISECOND, 0); - if (execTimeZone != null && !execTimeZone.isEmpty()) { - _jobExecTime.setTimeZone(TimeZone.getTimeZone(execTimeZone)); - } + + TimeZone jobExecTimeZone = execTimeZone != null ? TimeZone.getTimeZone(execTimeZone) : Calendar.getInstance().getTimeZone(); + _jobExecTime.setTimeZone(jobExecTimeZone); // if the hour to execute the job has already passed, roll the day forward to the next day - Date execDate = _jobExecTime.getTime(); - if (execDate.before(new Date())) { + if (_jobExecTime.getTime().before(currentDate)) { _jobExecTime.roll(Calendar.DAY_OF_YEAR, true); } - logger.debug("Execution Time: " + execDate.toString()); - Date currentDate = new Date(System.currentTimeMillis()); - logger.debug("Current Time: " + currentDate.toString()); + logger.info("Usage is configured to execute in time zone [{}], at [{}], each [{}] minutes; the current time in that timezone is [{}] and the " + + "next job is scheduled to execute at [{}]. During its execution, Usage will aggregate stats according to the time zone [{}] defined in global setting [usage.aggregation.timezone].", + jobExecTimeZone.getID(), execTime, aggregationRange, DateUtil.displayDateInTimezone(jobExecTimeZone, currentDate), + DateUtil.displayDateInTimezone(jobExecTimeZone, _jobExecTime.getTime()), usageAggregationTimeZone.getID()); _aggregationDuration = Integer.parseInt(aggregationRange); if (_aggregationDuration < UsageUtils.USAGE_AGGREGATION_RANGE_MIN) { @@ -298,6 +300,10 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna return true; } + public static TimeZone getUsageAggregationTimeZone() { + return usageAggregationTimeZone; + } + @Override public boolean start() { if (logger.isInfoEnabled()) { @@ -380,7 +386,7 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna // For executing the job, we treat hourly and daily as special time ranges, using the previous full hour or the previous // full day. Otherwise we just subtract off the aggregation range from the current time and use that as start date with // current time as end date. - Calendar cal = Calendar.getInstance(_usageTimezone); + Calendar cal = Calendar.getInstance(usageAggregationTimeZone); cal.setTime(new Date()); long startDate = 0; long endDate = 0; @@ -488,9 +494,8 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna } Date startDate = new Date(startDateMillis); Date endDate = new Date(endDateMillis); - if (logger.isInfoEnabled()) { - logger.info("Parsing usage records between " + startDate + " and " + endDate); - } + logger.info("Parsing usage records between [{}] and [{}].", DateUtil.displayDateInTimezone(usageAggregationTimeZone, startDate), + DateUtil.displayDateInTimezone(usageAggregationTimeZone, endDate)); List<AccountVO> accounts = null; List<UserStatisticsVO> userStats = null; @@ -705,7 +710,7 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna // get user stats in order to compute network usage networkStats = _usageNetworkDao.getRecentNetworkStats(); - Calendar recentlyDeletedCal = Calendar.getInstance(_usageTimezone); + Calendar recentlyDeletedCal = Calendar.getInstance(usageAggregationTimeZone); recentlyDeletedCal.setTimeInMillis(startDateMillis); recentlyDeletedCal.add(Calendar.MINUTE, -1 * THREE_DAYS_IN_MINUTES); Date recentlyDeletedDate = recentlyDeletedCal.getTime(); @@ -814,7 +819,7 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna Date currentEndDate = endDate; Date tempDate = endDate; - Calendar aggregateCal = Calendar.getInstance(_usageTimezone); + Calendar aggregateCal = Calendar.getInstance(usageAggregationTimeZone); while ((tempDate.after(startDate)) && ((tempDate.getTime() - startDate.getTime()) > 60000)) { currentEndDate = tempDate; @@ -1850,8 +1855,9 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna deleteUsageVpnUser(event, account); break; default: - logger.debug(String.format("The event [type=%s, zoneId=%s, accountId=%s, userId=%s, resourceName=%s, createDate=%s] is neither of type [%s] nor [%s]", - event.getType(), zoneId, accountId, userId, event.getResourceName(), event.getCreateDate(), EventTypes.EVENT_VPN_USER_ADD, EventTypes.EVENT_VPN_USER_REMOVE)); + logger.debug("The event [type={}, zoneId={}, accountId={}, userId={}, resourceName={}, createDate={}] is neither of type [{}] nor [{}].", + event.getType(), zoneId, accountId, userId, event.getResourceName(), DateUtil.displayDateInTimezone(usageAggregationTimeZone, event.getCreateDate()), + EventTypes.EVENT_VPN_USER_ADD, EventTypes.EVENT_VPN_USER_REMOVE); } } @@ -1967,8 +1973,10 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna deleteUsageVMSnapshot(event); break; default: - logger.debug(String.format("The event [type=%s, zoneId=%s, accountId=%s, resourceName=%s, diskOfferingId=%s, createDate=%s] is neither of type [%s] nor [%s]", - event.getType(), event.getZoneId(), event.getAccountId(), event.getResourceName(), event.getOfferingId(), event.getCreateDate(), EventTypes.EVENT_VM_SNAPSHOT_CREATE, EventTypes.EVENT_VM_SNAPSHOT_DELETE)); + logger.debug("The event [type={}, zoneId={}, accountId={}, resourceName={}, diskOfferingId={}, createDate={}] is neither of type [{}] nor [{}].", + event.getType(), event.getZoneId(), event.getAccountId(), event.getResourceName(), event.getOfferingId(), + DateUtil.displayDateInTimezone(usageAggregationTimeZone, event.getCreateDate()), EventTypes.EVENT_VM_SNAPSHOT_CREATE, + EventTypes.EVENT_VM_SNAPSHOT_DELETE); } } @@ -1992,8 +2000,8 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna String snapId = detailVO.getValue(); vmSnapshotId = Long.valueOf(snapId); } - logger.debug(String.format("Creating usage VM Snapshot for VM id [%s] assigned to account [%s] domain [%s], zone [%s], and created at [%s]", vmId, accountId, domainId, zoneId, - event.getCreateDate())); + logger.debug("Creating usage VM Snapshot for VM id [{}] assigned to account [{}] domain [{}], zone [{}], and created at [{}].", + vmId, accountId, domainId, zoneId, DateUtil.displayDateInTimezone(usageAggregationTimeZone, event.getCreateDate())); UsageVMSnapshotVO vsVO = new UsageVMSnapshotVO(volumeId, zoneId, accountId, domainId, vmId, offeringId, size, created, null); vsVO.setVmSnapshotId(vmSnapshotId); _usageVMSnapshotDao.persist(vsVO); diff --git a/usage/src/main/java/com/cloud/usage/parser/IPAddressUsageParser.java b/usage/src/main/java/com/cloud/usage/parser/IPAddressUsageParser.java index 5e516231f0d..516f58a0a7b 100644 --- a/usage/src/main/java/com/cloud/usage/parser/IPAddressUsageParser.java +++ b/usage/src/main/java/com/cloud/usage/parser/IPAddressUsageParser.java @@ -25,6 +25,8 @@ import java.util.Map; import javax.annotation.PostConstruct; import javax.inject.Inject; +import com.cloud.usage.UsageManagerImpl; +import com.cloud.utils.DateUtil; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; import org.springframework.stereotype.Component; @@ -149,10 +151,9 @@ public class IPAddressUsageParser { DecimalFormat dFormat = new DecimalFormat("#.######"); String usageDisplay = dFormat.format(usage); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Creating IP usage record with id: " + ipId + ", usage: " + usageDisplay + ", startDate: " + startDate + ", endDate: " + endDate + - ", for account: " + account.getId()); - } + LOGGER.debug("Creating IP usage record with id [{}], usage [{}], startDate [{}], and endDate [{}], for account [{}].", + ipId, usageDisplay, DateUtil.displayDateInTimezone(UsageManagerImpl.getUsageAggregationTimeZone(), startDate), + DateUtil.displayDateInTimezone(UsageManagerImpl.getUsageAggregationTimeZone(), endDate), account.getId()); String usageDesc = "IPAddress: " + ipAddress; diff --git a/usage/src/main/java/com/cloud/usage/parser/LoadBalancerUsageParser.java b/usage/src/main/java/com/cloud/usage/parser/LoadBalancerUsageParser.java index 77cdbfb8a4e..3d02419aec8 100644 --- a/usage/src/main/java/com/cloud/usage/parser/LoadBalancerUsageParser.java +++ b/usage/src/main/java/com/cloud/usage/parser/LoadBalancerUsageParser.java @@ -25,6 +25,8 @@ import java.util.Map; import javax.annotation.PostConstruct; import javax.inject.Inject; +import com.cloud.usage.UsageManagerImpl; +import com.cloud.utils.DateUtil; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; import org.springframework.stereotype.Component; @@ -146,10 +148,9 @@ public class LoadBalancerUsageParser { DecimalFormat dFormat = new DecimalFormat("#.######"); String usageDisplay = dFormat.format(usage); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Creating Volume usage record for load balancer: " + lbId + ", usage: " + usageDisplay + ", startDate: " + startDate + ", endDate: " + - endDate + ", for account: " + account.getId()); - } + LOGGER.debug("Creating usage record for load balancer with id [{}], usage [{}], startDate [{}], and endDate [{}], for account [{}].", + lbId, usageDisplay, DateUtil.displayDateInTimezone(UsageManagerImpl.getUsageAggregationTimeZone(), startDate), + DateUtil.displayDateInTimezone(UsageManagerImpl.getUsageAggregationTimeZone(), endDate), account.getId()); // Create the usage record String usageDesc = "Load Balancing Policy: " + lbId + " usage time"; diff --git a/usage/src/main/java/com/cloud/usage/parser/NetworkOfferingUsageParser.java b/usage/src/main/java/com/cloud/usage/parser/NetworkOfferingUsageParser.java index 8ec46416272..b0fc6c2df95 100644 --- a/usage/src/main/java/com/cloud/usage/parser/NetworkOfferingUsageParser.java +++ b/usage/src/main/java/com/cloud/usage/parser/NetworkOfferingUsageParser.java @@ -25,6 +25,8 @@ import java.util.Map; import javax.annotation.PostConstruct; import javax.inject.Inject; +import com.cloud.usage.UsageManagerImpl; +import com.cloud.utils.DateUtil; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; import org.springframework.stereotype.Component; @@ -148,10 +150,9 @@ public class NetworkOfferingUsageParser { DecimalFormat dFormat = new DecimalFormat("#.######"); String usageDisplay = dFormat.format(usage); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Creating network offering:" + noId + " usage record for Vm : " + vmId + ", usage: " + usageDisplay + ", startDate: " + startDate + - ", endDate: " + endDate + ", for account: " + account.getId()); - } + LOGGER.debug("Creating network offering usage record for id [{}], vm [{}], usage [{}], startDate [{}], and endDate [{}], for account [{}].", + noId, vmId, usageDisplay, DateUtil.displayDateInTimezone(UsageManagerImpl.getUsageAggregationTimeZone(), startDate), + DateUtil.displayDateInTimezone(UsageManagerImpl.getUsageAggregationTimeZone(), endDate), account.getId()); // Create the usage record String usageDesc = "Network offering:" + noId + " for Vm : " + vmId + " usage time"; diff --git a/usage/src/main/java/com/cloud/usage/parser/NetworkUsageParser.java b/usage/src/main/java/com/cloud/usage/parser/NetworkUsageParser.java index 7b530b9a3b3..912c2b58cb8 100644 --- a/usage/src/main/java/com/cloud/usage/parser/NetworkUsageParser.java +++ b/usage/src/main/java/com/cloud/usage/parser/NetworkUsageParser.java @@ -25,6 +25,8 @@ import java.util.Map; import javax.annotation.PostConstruct; import javax.inject.Inject; +import com.cloud.usage.UsageManagerImpl; +import com.cloud.utils.DateUtil; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; import org.springframework.stereotype.Component; @@ -103,10 +105,10 @@ public class NetworkUsageParser { long totalBytesReceived = networkInfo.getBytesRcvd(); if ((totalBytesSent > 0L) || (totalBytesReceived > 0L)) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Creating usage record, total bytes sent: " + toHumanReadableSize(totalBytesSent) + ", total bytes received: " + toHumanReadableSize(totalBytesReceived) + " for account: " + - account.getId() + " in availability zone " + networkInfo.getZoneId() + ", start: " + startDate + ", end: " + endDate); - } + LOGGER.debug("Creating usage record, total bytes sent [{}], total bytes received [{}], startDate [{}], and endDate [{}], for account [{}] in " + + "availability zone [{}].", toHumanReadableSize(totalBytesSent), toHumanReadableSize(totalBytesReceived), + DateUtil.displayDateInTimezone(UsageManagerImpl.getUsageAggregationTimeZone(), startDate), + DateUtil.displayDateInTimezone(UsageManagerImpl.getUsageAggregationTimeZone(), endDate), account.getId(), networkInfo.getZoneId()); Long hostId = null; diff --git a/usage/src/main/java/com/cloud/usage/parser/PortForwardingUsageParser.java b/usage/src/main/java/com/cloud/usage/parser/PortForwardingUsageParser.java index e746284b3a3..fce2f6f8a9c 100644 --- a/usage/src/main/java/com/cloud/usage/parser/PortForwardingUsageParser.java +++ b/usage/src/main/java/com/cloud/usage/parser/PortForwardingUsageParser.java @@ -25,6 +25,8 @@ import java.util.Map; import javax.annotation.PostConstruct; import javax.inject.Inject; +import com.cloud.usage.UsageManagerImpl; +import com.cloud.utils.DateUtil; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; import org.springframework.stereotype.Component; @@ -146,10 +148,9 @@ public class PortForwardingUsageParser { DecimalFormat dFormat = new DecimalFormat("#.######"); String usageDisplay = dFormat.format(usage); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Creating usage record for port forwarding rule: " + pfId + ", usage: " + usageDisplay + ", startDate: " + startDate + ", endDate: " + - endDate + ", for account: " + account.getId()); - } + LOGGER.debug("Creating usage record for port forwarding rule [{}], usage [{}], startDate [{}], and endDate [{}], for account [{}].", + pfId, usageDisplay, DateUtil.displayDateInTimezone(UsageManagerImpl.getUsageAggregationTimeZone(), startDate), + DateUtil.displayDateInTimezone(UsageManagerImpl.getUsageAggregationTimeZone(), endDate), account.getId()); // Create the usage record String usageDesc = "Port Forwarding Rule: " + pfId + " usage time"; diff --git a/usage/src/main/java/com/cloud/usage/parser/SecurityGroupUsageParser.java b/usage/src/main/java/com/cloud/usage/parser/SecurityGroupUsageParser.java index bec14bae230..4bb146b7763 100644 --- a/usage/src/main/java/com/cloud/usage/parser/SecurityGroupUsageParser.java +++ b/usage/src/main/java/com/cloud/usage/parser/SecurityGroupUsageParser.java @@ -25,6 +25,8 @@ import java.util.Map; import javax.annotation.PostConstruct; import javax.inject.Inject; +import com.cloud.usage.UsageManagerImpl; +import com.cloud.utils.DateUtil; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; import org.springframework.stereotype.Component; @@ -147,10 +149,9 @@ public class SecurityGroupUsageParser { DecimalFormat dFormat = new DecimalFormat("#.######"); String usageDisplay = dFormat.format(usage); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Creating security group:" + sgId + " usage record for Vm : " + vmId + ", usage: " + usageDisplay + ", startDate: " + startDate + - ", endDate: " + endDate + ", for account: " + account.getId()); - } + LOGGER.debug("Creating security group usage record for id [{}], vm [{}], usage [{}], startDate [{}], and endDate [{}], for account [{}].", + sgId, vmId, usageDisplay, DateUtil.displayDateInTimezone(UsageManagerImpl.getUsageAggregationTimeZone(), startDate), + DateUtil.displayDateInTimezone(UsageManagerImpl.getUsageAggregationTimeZone(), endDate), account.getId()); // Create the usage record String usageDesc = "Security Group: " + sgId + " for Vm : " + vmId + " usage time"; diff --git a/usage/src/main/java/com/cloud/usage/parser/StorageUsageParser.java b/usage/src/main/java/com/cloud/usage/parser/StorageUsageParser.java index 6684ae03e43..62d1a429ae3 100644 --- a/usage/src/main/java/com/cloud/usage/parser/StorageUsageParser.java +++ b/usage/src/main/java/com/cloud/usage/parser/StorageUsageParser.java @@ -25,6 +25,8 @@ import java.util.Map; import javax.annotation.PostConstruct; import javax.inject.Inject; +import com.cloud.usage.UsageManagerImpl; +import com.cloud.utils.DateUtil; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; import org.springframework.stereotype.Component; @@ -159,10 +161,9 @@ public class StorageUsageParser { DecimalFormat dFormat = new DecimalFormat("#.######"); String usageDisplay = dFormat.format(usage); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Creating Storage usage record for type: " + type + " with id: " + storageId + ", usage: " + usageDisplay + ", startDate: " + startDate + - ", endDate: " + endDate + ", for account: " + account.getId()); - } + LOGGER.debug("Creating Storage usage record for type [{}], with id [{}], usage [{}], startDate [{}], and endDate [{}], for account [{}].", + type, storageId, usageDisplay, DateUtil.displayDateInTimezone(UsageManagerImpl.getUsageAggregationTimeZone(), startDate), + DateUtil.displayDateInTimezone(UsageManagerImpl.getUsageAggregationTimeZone(), endDate), account.getId()); String usageDesc = ""; Long tmplSourceId = null; diff --git a/usage/src/main/java/com/cloud/usage/parser/VMInstanceUsageParser.java b/usage/src/main/java/com/cloud/usage/parser/VMInstanceUsageParser.java index 56ee3282afc..b261cc717e6 100644 --- a/usage/src/main/java/com/cloud/usage/parser/VMInstanceUsageParser.java +++ b/usage/src/main/java/com/cloud/usage/parser/VMInstanceUsageParser.java @@ -25,6 +25,8 @@ import java.util.Map; import javax.annotation.PostConstruct; import javax.inject.Inject; +import com.cloud.usage.UsageManagerImpl; +import com.cloud.utils.DateUtil; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; import org.springframework.stereotype.Component; @@ -173,10 +175,9 @@ public class VMInstanceUsageParser { DecimalFormat dFormat = new DecimalFormat("#.######"); String usageDisplay = dFormat.format(usage); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Creating VM usage record for vm: " + vmName + ", type: " + type + ", usage: " + usageDisplay + ", startDate: " + startDate + ", endDate: " + - endDate + ", for account: " + account.getId()); - } + LOGGER.debug("Creating VM usage record for vm [{}], type [{}], usage [{}], startDate [{}], and endDate [{}], for account [{}].", + vmName, type, usageDisplay, DateUtil.displayDateInTimezone(UsageManagerImpl.getUsageAggregationTimeZone(), startDate), + DateUtil.displayDateInTimezone(UsageManagerImpl.getUsageAggregationTimeZone(), endDate), account.getId()); // Create the usage record String usageDesc = vmName; diff --git a/usage/src/main/java/com/cloud/usage/parser/VMSnapshotOnPrimaryParser.java b/usage/src/main/java/com/cloud/usage/parser/VMSnapshotOnPrimaryParser.java index ad2fdd93cfa..d59d3c741f1 100644 --- a/usage/src/main/java/com/cloud/usage/parser/VMSnapshotOnPrimaryParser.java +++ b/usage/src/main/java/com/cloud/usage/parser/VMSnapshotOnPrimaryParser.java @@ -25,6 +25,8 @@ import java.util.Map; import javax.annotation.PostConstruct; import javax.inject.Inject; +import com.cloud.usage.UsageManagerImpl; +import com.cloud.utils.DateUtil; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; import org.springframework.stereotype.Component; @@ -115,10 +117,9 @@ public class VMSnapshotOnPrimaryParser { DecimalFormat dFormat = new DecimalFormat("#.######"); String usageDisplay = dFormat.format(usage); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Creating VMSnapshot Id: " + vmSnapshotId + " On Primary usage record for vm: " + vmId + ", usage: " + usageDisplay + ", startDate: " + startDate + ", endDate: " + endDate - + ", for account: " + account.getId()); - } + LOGGER.debug("Creating usage record for VMSnapshot with id [{}] in primary, vm [{}], usage [{}], startDate [{}], and endDate [{}], for account [{}].", + vmSnapshotId, vmId, usageDisplay, DateUtil.displayDateInTimezone(UsageManagerImpl.getUsageAggregationTimeZone(), startDate), + DateUtil.displayDateInTimezone(UsageManagerImpl.getUsageAggregationTimeZone(), endDate), account.getId()); // Create the usage record String usageDesc = "VMSnapshot Id: " + vmSnapshotId + " On Primary Usage: VM Id: " + vmId; diff --git a/usage/src/main/java/com/cloud/usage/parser/VMSnapshotUsageParser.java b/usage/src/main/java/com/cloud/usage/parser/VMSnapshotUsageParser.java index 2cf538cc31a..63fc213f4aa 100644 --- a/usage/src/main/java/com/cloud/usage/parser/VMSnapshotUsageParser.java +++ b/usage/src/main/java/com/cloud/usage/parser/VMSnapshotUsageParser.java @@ -25,6 +25,8 @@ import java.util.Map; import javax.annotation.PostConstruct; import javax.inject.Inject; +import com.cloud.usage.UsageManagerImpl; +import com.cloud.utils.DateUtil; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; import org.springframework.stereotype.Component; @@ -134,10 +136,9 @@ public class VMSnapshotUsageParser { DecimalFormat dFormat = new DecimalFormat("#.######"); String usageDisplay = dFormat.format(usage); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Creating VMSnapshot Id:" + vmSnapshotId + " Volume usage record for vol: " + volId + ", usage: " + usageDisplay + ", startDate: " + startDate + ", endDate: " + - endDate + ", for account: " + account.getId()); - } + LOGGER.debug("Creating usage record for VMSnapshot with id [{}], vol [{}], usage [{}], startDate [{}], and endDate [{}], for account [{}].", + vmSnapshotId, volId, usageDisplay, DateUtil.displayDateInTimezone(UsageManagerImpl.getUsageAggregationTimeZone(), startDate), + DateUtil.displayDateInTimezone(UsageManagerImpl.getUsageAggregationTimeZone(), endDate), account.getId()); // Create the usage record String usageDesc = "VMSnapshot Id: " + vmSnapshotId + " Usage: " + "VM Id: " + vmId + " Volume Id: " + volId + " "; diff --git a/usage/src/main/java/com/cloud/usage/parser/VPNUserUsageParser.java b/usage/src/main/java/com/cloud/usage/parser/VPNUserUsageParser.java index c983457cf59..d5eac4fea20 100644 --- a/usage/src/main/java/com/cloud/usage/parser/VPNUserUsageParser.java +++ b/usage/src/main/java/com/cloud/usage/parser/VPNUserUsageParser.java @@ -25,6 +25,8 @@ import java.util.Map; import javax.annotation.PostConstruct; import javax.inject.Inject; +import com.cloud.usage.UsageManagerImpl; +import com.cloud.utils.DateUtil; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; import org.springframework.stereotype.Component; @@ -142,10 +144,9 @@ public class VPNUserUsageParser { DecimalFormat dFormat = new DecimalFormat("#.######"); String usageDisplay = dFormat.format(usage); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Creating VPN user:" + userId + " usage record, usage: " + usageDisplay + ", startDate: " + startDate + ", endDate: " + endDate + - ", for account: " + account.getId()); - } + LOGGER.debug("Creating usage record for VPN user [{}], usage [{}], startDate [{}], and endDate [{}], for account [{}].", + userId, usageDisplay, DateUtil.displayDateInTimezone(UsageManagerImpl.getUsageAggregationTimeZone(), startDate), + DateUtil.displayDateInTimezone(UsageManagerImpl.getUsageAggregationTimeZone(), endDate), account.getId()); // Create the usage record String usageDesc = "VPN User: " + userName + ", Id: " + userId + " usage time"; diff --git a/usage/src/main/java/com/cloud/usage/parser/VmDiskUsageParser.java b/usage/src/main/java/com/cloud/usage/parser/VmDiskUsageParser.java index 0d04fe39339..a5b537b8ffd 100644 --- a/usage/src/main/java/com/cloud/usage/parser/VmDiskUsageParser.java +++ b/usage/src/main/java/com/cloud/usage/parser/VmDiskUsageParser.java @@ -25,6 +25,8 @@ import java.util.Map; import javax.annotation.PostConstruct; import javax.inject.Inject; +import com.cloud.usage.UsageManagerImpl; +import com.cloud.utils.DateUtil; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; import org.springframework.stereotype.Component; @@ -108,11 +110,10 @@ public class VmDiskUsageParser { long bytesWrite = vmDiskInfo.getBytesWrite(); if ((ioRead > 0L) || (ioWrite > 0L) || (bytesRead > 0L) || (bytesWrite > 0L)) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Creating vm disk usage record, io read:" + toHumanReadableSize(ioRead) + ", io write: " + toHumanReadableSize(ioWrite) + ", bytes read:" + toHumanReadableSize(bytesRead) + ", bytes write: " + - toHumanReadableSize(bytesWrite) + " for account: " + account.getId() + " in availability zone " + vmDiskInfo.getZoneId() + ", start: " + startDate + ", end: " + - endDate); - } + LOGGER.debug("Creating vm disk usage record, io read [{}], io write [{}], bytes read [{}], bytes write [{}], startDate [{}], and endDate [{}], " + + "for account [{}] in availability zone [{}].", toHumanReadableSize(ioRead), toHumanReadableSize(ioWrite), toHumanReadableSize(bytesRead), + toHumanReadableSize(bytesWrite), DateUtil.displayDateInTimezone(UsageManagerImpl.getUsageAggregationTimeZone(), startDate), + DateUtil.displayDateInTimezone(UsageManagerImpl.getUsageAggregationTimeZone(), endDate), account.getId(), vmDiskInfo.getZoneId()); Long vmId = null; Long volumeId = null; diff --git a/usage/src/main/java/com/cloud/usage/parser/VolumeUsageParser.java b/usage/src/main/java/com/cloud/usage/parser/VolumeUsageParser.java index a63d0df00bd..a5b6d77e9ab 100644 --- a/usage/src/main/java/com/cloud/usage/parser/VolumeUsageParser.java +++ b/usage/src/main/java/com/cloud/usage/parser/VolumeUsageParser.java @@ -25,6 +25,8 @@ import java.util.Map; import javax.annotation.PostConstruct; import javax.inject.Inject; +import com.cloud.usage.UsageManagerImpl; +import com.cloud.utils.DateUtil; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; import org.springframework.stereotype.Component; @@ -153,10 +155,9 @@ public class VolumeUsageParser { DecimalFormat dFormat = new DecimalFormat("#.######"); String usageDisplay = dFormat.format(usage); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Creating Volume usage record for vol: " + volId + ", usage: " + usageDisplay + ", startDate: " + startDate + ", endDate: " + endDate + - ", for account: " + account.getId()); - } + LOGGER.debug("Creating Volume usage record for vol [{}], usage [{}], startDate [{}], and endDate [{}], for account [{}].", + volId, usageDisplay, DateUtil.displayDateInTimezone(UsageManagerImpl.getUsageAggregationTimeZone(), startDate), + DateUtil.displayDateInTimezone(UsageManagerImpl.getUsageAggregationTimeZone(), endDate), account.getId()); // Create the usage record String usageDesc = "Volume Id: " + volId + " usage time"; diff --git a/utils/src/main/java/com/cloud/utils/DateUtil.java b/utils/src/main/java/com/cloud/utils/DateUtil.java index 39ea60dae18..fdf2ba8fe01 100644 --- a/utils/src/main/java/com/cloud/utils/DateUtil.java +++ b/utils/src/main/java/com/cloud/utils/DateUtil.java @@ -48,11 +48,12 @@ public class DateUtil { public static final TimeZone GMT_TIMEZONE = TimeZone.getTimeZone("GMT"); public static final String YYYYMMDD_FORMAT = "yyyyMMddHHmmss"; - private static final DateFormat s_outputFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); + private static final String ZONED_DATETIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ssZ"; + private static final DateFormat ZONED_DATETIME_SIMPLE_FORMATTER = new SimpleDateFormat(ZONED_DATETIME_FORMAT); private static final DateTimeFormatter[] parseFormats = new DateTimeFormatter[]{ DateTimeFormatter.ISO_OFFSET_DATE_TIME, - DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ"), + DateTimeFormatter.ofPattern(ZONED_DATETIME_FORMAT), DateTimeFormatter.ISO_INSTANT, // with milliseconds DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSSX"), @@ -95,7 +96,7 @@ public class DateUtil { } public static String displayDateInTimezone(TimeZone tz, Date time) { - return getDateDisplayString(tz, time, "yyyy-MM-dd HH:mm:ss z"); + return getDateDisplayString(tz, time, ZONED_DATETIME_FORMAT); } public static String getDateDisplayString(TimeZone tz, Date time) { @@ -103,6 +104,10 @@ public class DateUtil { } public static String getDateDisplayString(TimeZone tz, Date time, String formatString) { + if (time == null) { + return null; + } + DateFormat df = new SimpleDateFormat(formatString); df.setTimeZone(tz); @@ -113,9 +118,9 @@ public class DateUtil { if (date == null) { return ""; } - String formattedString = null; - synchronized (s_outputFormat) { - formattedString = s_outputFormat.format(date); + String formattedString; + synchronized (ZONED_DATETIME_SIMPLE_FORMATTER) { + formattedString = ZONED_DATETIME_SIMPLE_FORMATTER.format(date); } return formattedString; }