
br.com.ingenieux.mojo.cloudwatch.TailMojo Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cloudwatch-maven-plugin Show documentation
Show all versions of cloudwatch-maven-plugin Show documentation
Beanstalker's support for Amazon CloudWatch Logs
The newest version!
/*
* Copyright (c) 2016 ingenieux Labs
*
* 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 or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package br.com.ingenieux.mojo.cloudwatch;
import com.amazonaws.services.logs.model.DescribeLogGroupsRequest;
import com.amazonaws.services.logs.model.DescribeLogGroupsResult;
import com.amazonaws.services.logs.model.DescribeLogStreamsRequest;
import com.amazonaws.services.logs.model.DescribeLogStreamsResult;
import com.amazonaws.services.logs.model.FilterLogEventsRequest;
import com.amazonaws.services.logs.model.FilterLogEventsResult;
import com.amazonaws.services.logs.model.GetLogEventsRequest;
import com.amazonaws.services.logs.model.GetLogEventsResult;
import com.amazonaws.services.logs.model.LogStream;
import com.amazonaws.services.logs.model.OrderBy;
import com.amazonaws.services.logs.model.OutputLogEvent;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.CompareToBuilder;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;
import java.awt.*;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalLong;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Function;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import br.com.ingenieux.mojo.aws.util.GlobUtil;
import static java.util.Arrays.asList;
/**
* Represents Tailing a set of CloudWatch Log Streams Together
*/
@Mojo(name = "tail")
public class TailMojo extends AbstractCloudWatchMojo {
private static final DateTimeFormatter DATE_TIME_FORMATTER = ISODateTimeFormat.basicDateTime();
/**
* Set of Log Groups to Use
*/
@Parameter(property = "cloudwatch.logGroups", defaultValue = "*")
Set logGroups = new LinkedHashSet<>(Collections.singletonList("*"));
protected Set logGroupPatterns;
public void setLogGroups(String logGroups) {
this.logGroups = new LinkedHashSet<>(asList(logGroups.split(",")));
}
@Override
protected Object executeInternal() throws Exception {
this.logGroupPatterns = createLogGroupPatterns();
AtomicLong baseOffset = new AtomicLong(System.currentTimeMillis() - 60 * 1000);
Set foundLogGroups = findLogGroups();
getLog().info("Log Groups Found:");
foundLogGroups.forEach(logGroupName -> getLog().info(" * " + logGroupName));
while (true) {
OptionalLong nextMessageOffset = foundLogGroups.parallelStream().mapToLong(logGroup -> doLogMessages(logGroup, baseOffset.get())).max();
if (nextMessageOffset.isPresent()) {
baseOffset.set(Math.max(baseOffset.get(), nextMessageOffset.getAsLong()));
}
Thread.sleep(5000L);
}
//return null;
}
private Long doLogMessages(String logGroup, Long baseOffset) {
String nextToken = null;
FilterLogEventsRequest req = new FilterLogEventsRequest().withStartTime(baseOffset).withLogGroupName(logGroup);
AtomicLong result = new AtomicLong(-1L);
do {
final FilterLogEventsResult response = getService().filterLogEvents(req.withNextToken(nextToken));
response
.getEvents()
.forEach(
logEvent -> {
result.set(Math.max(logEvent.getTimestamp(), result.get()));
String message =
String.format(
"%s %s %s %s\n%s",
DATE_TIME_FORMATTER.print(logEvent.getTimestamp()),
StringUtils.abbreviateMiddle(logGroup, "..", 40),
StringUtils.abbreviateMiddle(logEvent.getLogStreamName(), "..", 40),
StringUtils.abbreviateMiddle(logEvent.getEventId(), "..", 40),
logEvent.getMessage().trim());
getLog().info(message);
});
nextToken = response.getNextToken();
} while (null != nextToken);
return result.get();
}
private Set findLogGroups() {
LinkedHashSet result = new LinkedHashSet<>();
String nextToken = null;
DescribeLogGroupsRequest req = new DescribeLogGroupsRequest();
do {
req.setNextToken(nextToken);
DescribeLogGroupsResult response = getService().describeLogGroups(req);
result.addAll(
response
.getLogGroups()
.stream()
.filter(x -> hasMatchingName(x.getLogGroupName(), logGroupPatterns))
.map(x -> x.getLogGroupName())
.collect(Collectors.toList()));
nextToken = response.getNextToken();
} while (null != nextToken);
return result;
}
protected boolean hasMatchingName(String logGroupName, Set logGroupPatterns) {
final Optional foundFirst = logGroupPatterns.stream().filter(x -> x.matcher(logGroupName).matches()).findFirst();
return foundFirst.isPresent();
}
private Set createLogGroupPatterns() {
return logGroups.stream().map(x -> GlobUtil.asPattern(x)).collect(Collectors.toCollection(LinkedHashSet::new));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy