Skip to content

Commit

Permalink
[pinpoint-apm#10605] Added cleanup inactive applications batch job
Browse files Browse the repository at this point in the history
  • Loading branch information
youngjin.kim2 committed Jan 23, 2024
1 parent ce264f6 commit 0eef8c7
Show file tree
Hide file tree
Showing 12 changed files with 424 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import com.navercorp.pinpoint.batch.alarm.AlarmSenderConfiguration;
import com.navercorp.pinpoint.batch.configuration.AlarmJobModule;
import com.navercorp.pinpoint.batch.configuration.CleanupInactiveApplicationsJobConfig;
import com.navercorp.pinpoint.common.server.config.CommonCacheManagerConfiguration;
import com.navercorp.pinpoint.common.server.config.RestTemplateConfiguration;
import com.navercorp.pinpoint.common.server.util.DefaultTimeSlot;
Expand All @@ -31,6 +32,7 @@
import com.navercorp.pinpoint.web.component.config.ComponentConfiguration;
import com.navercorp.pinpoint.web.hyperlink.HyperLinkConfiguration;
import com.navercorp.pinpoint.web.webhook.WebhookModule;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
Expand Down Expand Up @@ -67,7 +69,9 @@
UriStatAlarmConfiguration.class,
AlarmSenderConfiguration.class,
CommonCacheManagerConfiguration.class,
CleanupInactiveApplicationsJobConfig.class,
})
@EnableBatchProcessing
public class BatchModule {

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@

package com.navercorp.pinpoint.batch.common;

import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.configuration.JobLocator;
Expand All @@ -36,8 +36,11 @@ public class BatchJobLauncher extends JobLaunchSupport {

private final BatchProperties batchProperties;

public BatchJobLauncher(@Qualifier("jobRegistry") JobLocator locator,
@Qualifier("jobLauncher") JobLauncher launcher, BatchProperties batchProperties) {
public BatchJobLauncher(
@Qualifier("jobRegistry") JobLocator locator,
@Qualifier("jobLauncher") JobLauncher launcher,
BatchProperties batchProperties
) {
super(locator, launcher);
this.batchProperties = Objects.requireNonNull(batchProperties, "batchProperties");
}
Expand Down Expand Up @@ -89,4 +92,13 @@ public void cleanupInactiveAgentsJob() {
logger.debug("Skip cleanupInactiveAgentsJob, because 'enableCleanupInactiveAgentsJob' is disabled.");
}
}

public void cleanApplicationListJob() {
if (batchProperties.isCleanupInactiveApplicationsJobEnable()) {
run("cleanupInactiveApplicationsJob", createTimeParameter());
} else {
logger.debug("Skip applicationCleanJob, because 'enableCleanupInactiveApplicationsJob' is disabled.");
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ public class BatchProperties {
@Value("${job.cleanup.inactive.agents.duration.days:30}")
private int cleanupInactiveAgentsDurationDays;

@Value("${job.cleanup.inactive.applications.enable:false}")
private boolean cleanupInactiveApplicationsJobEnable;

@Value("${job.cleanup.inactive.applications.cron}")
private String cleanupInactiveApplicationsJobCron;

private static final int MINIMUM_CLEANUP_INACTIVE_AGENTS_DURATION_DAYS = 7;

@PostConstruct
Expand Down Expand Up @@ -156,6 +162,14 @@ public int getCleanupInactiveAgentsDurationDays() {
return cleanupInactiveAgentsDurationDays;
}

public boolean isCleanupInactiveApplicationsJobEnable() {
return cleanupInactiveApplicationsJobEnable;
}

public String getCleanupInactiveApplicationsJobCron() {
return cleanupInactiveApplicationsJobCron;
}

@Override
public String toString() {
return "BatchProperties{" +
Expand All @@ -174,6 +188,8 @@ public String toString() {
", uriStatAlarmJobEnable=" + uriStatAlarmJobEnable +
", uriStatAlarmJobCron='" + uriStatAlarmJobCron + '\'' +
", cleanupInactiveAgentsDurationDays=" + cleanupInactiveAgentsDurationDays +
", cleanupInactiveApplicationsJobEnable=" + cleanupInactiveApplicationsJobEnable +
", cleanupInactiveApplicationsJobCron='" + cleanupInactiveApplicationsJobCron + '\'' +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* Copyright 2024 NAVER Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.navercorp.pinpoint.batch.configuration;

import com.navercorp.pinpoint.batch.job.ApplicationEmptyFilter;
import com.navercorp.pinpoint.batch.job.ApplicationReader;
import com.navercorp.pinpoint.batch.job.ApplicationRemover;
import com.navercorp.pinpoint.batch.service.ApplicationService;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Objects;

/**
* @author youngjin.kim2
*/
@Configuration(proxyBeanMethods = false)
public class CleanupInactiveApplicationsJobConfig {

private final JobBuilderFactory jobBuilderFactory;
private final StepBuilderFactory stepBuilderFactory;

public CleanupInactiveApplicationsJobConfig(
JobBuilderFactory jobBuilderFactory,
StepBuilderFactory stepBuilderFactory
) {
this.jobBuilderFactory = Objects.requireNonNull(jobBuilderFactory, "jobBuilderFactory");
this.stepBuilderFactory = Objects.requireNonNull(stepBuilderFactory, "stepBuilderFactory");
}

@Bean
public Job cleanupInactiveApplicationsJob(
@Qualifier("applicationCleanStep") Step applicationCleanStep
) {
return this.jobBuilderFactory.get("cleanupInactiveApplicationsJob")
.start(applicationCleanStep)
.build();
}

@Bean("applicationCleanStep")
public Step applicationCleanStep(
@Qualifier("applicationReader") ItemReader<String> applicationReader,
@Qualifier("applicationEmptyFilter") ItemProcessor<String, String> applicationEmptyFilter,
@Qualifier("applicationRemover") ItemWriter<String> applicationRemover
) {
return this.stepBuilderFactory.get("applicationCleanStep")
.<String, String>chunk(10)
.reader(applicationReader)
.processor(applicationEmptyFilter)
.writer(applicationRemover)
.build();
}

@Bean("applicationReader")
public ItemReader<String> applicationReader(ApplicationService applicationService) {
return new ApplicationReader(applicationService);
}

@Bean("applicationEmptyFilter")
public ItemProcessor<String, String> applicationEmptyFilter(ApplicationService applicationService) {
return new ApplicationEmptyFilter(applicationService);
}

@Bean("applicationRemover")
public ItemWriter<String> applicationRemover(ApplicationService applicationService) {
return new ApplicationRemover(applicationService);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,16 @@

import com.navercorp.pinpoint.web.dao.ApplicationIndexDao;
import com.navercorp.pinpoint.web.vo.Application;
import jakarta.annotation.Nonnull;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.StepExecutionListener;
import org.springframework.batch.item.ItemReader;

import jakarta.annotation.Nonnull;
import java.util.List;
import java.util.Objects;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.stream.Collectors;

/**
* @author youngjin.kim2
Expand All @@ -48,7 +47,7 @@ public void beforeStep(@Nonnull StepExecution stepExecution) {
List<String> applicationNames = applicationIndexDao.selectAllApplicationNames()
.stream()
.map(Application::getName)
.collect(Collectors.toUnmodifiableList());
.toList();
this.applicationNameQueue = new ConcurrentLinkedQueue<>(applicationNames);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright 2024 NAVER Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.navercorp.pinpoint.batch.job;

import com.navercorp.pinpoint.batch.service.ApplicationService;
import jakarta.annotation.Nonnull;
import org.springframework.batch.item.ItemProcessor;

import java.util.Objects;

/**
* @author youngjin.kim2
*/
public class ApplicationEmptyFilter implements ItemProcessor<String, String> {

private final ApplicationService applicationService;

public ApplicationEmptyFilter(ApplicationService applicationService) {
this.applicationService = Objects.requireNonNull(applicationService, "applicationService");
}

@Override
public String process(@Nonnull String s) throws Exception {
if (isApplicationEmpty(s)) {
return s;
}
return null;
}

private boolean isApplicationEmpty(String applicationName) {
return this.applicationService.isApplicationEmpty(applicationName);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright 2024 NAVER Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.navercorp.pinpoint.batch.job;

import com.navercorp.pinpoint.batch.service.ApplicationService;
import jakarta.annotation.Nonnull;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.ItemStreamException;
import org.springframework.batch.item.ItemStreamReader;

import java.util.List;
import java.util.Objects;

/**
* @author youngjin.kim2
*/
public class ApplicationReader implements ItemStreamReader<String> {

private static final String CURRENT_INDEX = "current.index";

private final ApplicationService applicationService;

private List<String> applicationNames;
int currentIndex = 0;

public ApplicationReader(ApplicationService applicationService) {
this.applicationService = Objects.requireNonNull(applicationService, "applicationService");
}

@Override
public String read() {
if (currentIndex < applicationNames.size()) {
return applicationNames.get(currentIndex++);
} else {
return null;
}
}

@Override
public void open(@Nonnull ExecutionContext executionContext) throws ItemStreamException {
this.applicationNames = getAllApplications();
if (executionContext.containsKey(CURRENT_INDEX)) {
this.currentIndex = executionContext.getInt(CURRENT_INDEX);
} else {
this.currentIndex = 0;
}
}

@Override
public void update(@Nonnull ExecutionContext executionContext) throws ItemStreamException {
executionContext.putInt(CURRENT_INDEX, this.currentIndex);
}

@Override
public void close() throws ItemStreamException {
}

private List<String> getAllApplications() {
return this.applicationService.getApplicationNames()
.stream()
.sorted()
.toList();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright 2024 NAVER Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.navercorp.pinpoint.batch.job;

import com.navercorp.pinpoint.batch.service.ApplicationService;
import org.springframework.batch.item.ItemWriter;

import java.util.List;
import java.util.Objects;

/**
* @author youngjin.kim2
*/
public class ApplicationRemover implements ItemWriter<String> {

private final ApplicationService applicationService;

public ApplicationRemover(ApplicationService applicationService) {
this.applicationService = Objects.requireNonNull(applicationService, "applicationService");
}

@Override
public void write(List<? extends String> list) throws Exception {
for (String applicationName : list) {
this.applicationService.removeApplication(applicationName);
}
}
}
Loading

0 comments on commit 0eef8c7

Please sign in to comment.