forked from apache/druid
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Filtered and Composing request loggers (apache#3469)
* Add Filtered and Composing request loggers Add Filtered and Composite Request loggers - enables users to filter request logs for slow queries. fix test * review comments * review comment * remove unused import
- Loading branch information
1 parent
5e39578
commit 8cfcb95
Showing
5 changed files
with
248 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
84 changes: 84 additions & 0 deletions
84
server/src/main/java/io/druid/server/log/ComposingRequestLoggerProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
/* | ||
* Licensed to Metamarkets Group Inc. (Metamarkets) under one | ||
* or more contributor license agreements. See the NOTICE file | ||
* distributed with this work for additional information | ||
* regarding copyright ownership. Metamarkets licenses this file | ||
* to you 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 io.druid.server.log; | ||
|
||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import com.fasterxml.jackson.annotation.JsonTypeName; | ||
import com.google.common.base.Throwables; | ||
import com.google.common.collect.Lists; | ||
import io.druid.server.RequestLogLine; | ||
|
||
import javax.validation.constraints.NotNull; | ||
import java.io.IOException; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
/** | ||
*/ | ||
@JsonTypeName("composing") | ||
public class ComposingRequestLoggerProvider implements RequestLoggerProvider | ||
{ | ||
@JsonProperty | ||
@NotNull | ||
private final List<RequestLoggerProvider> loggerProviders = Lists.newArrayList(); | ||
|
||
@Override | ||
public RequestLogger get() | ||
{ | ||
final List<RequestLogger> loggers = new ArrayList<>(); | ||
for (RequestLoggerProvider loggerProvider : loggerProviders) { | ||
loggers.add(loggerProvider.get()); | ||
} | ||
return new ComposingRequestLogger(loggers); | ||
} | ||
|
||
public static class ComposingRequestLogger implements RequestLogger | ||
{ | ||
private final List<RequestLogger> loggers; | ||
|
||
public ComposingRequestLogger(List<RequestLogger> loggers) | ||
{ | ||
this.loggers = loggers; | ||
} | ||
|
||
@Override | ||
public void log(RequestLogLine requestLogLine) throws IOException | ||
{ | ||
Exception exception = null; | ||
for (RequestLogger logger : loggers) { | ||
try { | ||
logger.log(requestLogLine); | ||
} | ||
catch (Exception e) { | ||
if (exception == null) { | ||
exception = e; | ||
} else { | ||
exception.addSuppressed(e); | ||
} | ||
} | ||
} | ||
if (exception != null) { | ||
Throwables.propagateIfInstanceOf(exception, IOException.class); | ||
throw Throwables.propagate(exception); | ||
} | ||
} | ||
} | ||
|
||
} |
69 changes: 69 additions & 0 deletions
69
server/src/main/java/io/druid/server/log/FilteredRequestLoggerProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
/* | ||
* Licensed to Metamarkets Group Inc. (Metamarkets) under one | ||
* or more contributor license agreements. See the NOTICE file | ||
* distributed with this work for additional information | ||
* regarding copyright ownership. Metamarkets licenses this file | ||
* to you 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 io.druid.server.log; | ||
|
||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import com.fasterxml.jackson.annotation.JsonTypeName; | ||
import io.druid.server.RequestLogLine; | ||
|
||
import javax.validation.constraints.NotNull; | ||
import java.io.IOException; | ||
|
||
/** | ||
*/ | ||
@JsonTypeName("filtered") | ||
public class FilteredRequestLoggerProvider implements RequestLoggerProvider | ||
{ | ||
@JsonProperty | ||
@NotNull | ||
private RequestLoggerProvider delegate = null; | ||
|
||
@JsonProperty | ||
private long queryTimeThresholdMs = 0; | ||
|
||
@Override | ||
public RequestLogger get() | ||
{ | ||
return new FilteredRequestLogger(delegate.get(), queryTimeThresholdMs); | ||
} | ||
|
||
public static class FilteredRequestLogger implements RequestLogger | ||
{ | ||
|
||
private final long queryTimeThresholdMs; | ||
private final RequestLogger logger; | ||
|
||
public FilteredRequestLogger(RequestLogger logger, long queryTimeThresholdMs) | ||
{ | ||
this.logger = logger; | ||
this.queryTimeThresholdMs = queryTimeThresholdMs; | ||
} | ||
|
||
@Override | ||
public void log(RequestLogLine requestLogLine) throws IOException | ||
{ | ||
Object queryTime = requestLogLine.getQueryStats().getStats().get("query/time"); | ||
if (queryTime != null && ((Number) queryTime).longValue() >= queryTimeThresholdMs) { | ||
logger.log(requestLogLine); | ||
} | ||
} | ||
} | ||
|
||
} |
73 changes: 73 additions & 0 deletions
73
server/src/test/java/io/druid/server/log/FilteredRequestLoggerTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
/* | ||
* Licensed to Metamarkets Group Inc. (Metamarkets) under one | ||
* or more contributor license agreements. See the NOTICE file | ||
* distributed with this work for additional information | ||
* regarding copyright ownership. Metamarkets licenses this file | ||
* to you 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 io.druid.server.log; | ||
|
||
import com.google.common.collect.ImmutableMap; | ||
import io.druid.server.QueryStats; | ||
import io.druid.server.RequestLogLine; | ||
import org.easymock.EasyMock; | ||
import org.junit.Test; | ||
|
||
import java.io.IOException; | ||
|
||
public class FilteredRequestLoggerTest | ||
{ | ||
@Test | ||
public void testFilterBelowThreshold() throws IOException | ||
{ | ||
RequestLogger delegate = EasyMock.createStrictMock(RequestLogger.class); | ||
delegate.log((RequestLogLine) EasyMock.anyObject()); | ||
EasyMock.expectLastCall().andThrow(new IOException()); | ||
FilteredRequestLoggerProvider.FilteredRequestLogger logger = new FilteredRequestLoggerProvider.FilteredRequestLogger( | ||
delegate, | ||
1000 | ||
); | ||
RequestLogLine requestLogLine = EasyMock.createMock(RequestLogLine.class); | ||
EasyMock.expect(requestLogLine.getQueryStats()) | ||
.andReturn(new QueryStats(ImmutableMap.<String, Object>of("query/time", 100))) | ||
.once(); | ||
EasyMock.replay(requestLogLine, delegate); | ||
logger.log(requestLogLine); | ||
} | ||
|
||
@Test | ||
public void testNotFilterAboveThreshold() throws IOException | ||
{ | ||
RequestLogger delegate = EasyMock.createStrictMock(RequestLogger.class); | ||
delegate.log((RequestLogLine) EasyMock.anyObject()); | ||
EasyMock.expectLastCall().times(2); | ||
FilteredRequestLoggerProvider.FilteredRequestLogger logger = new FilteredRequestLoggerProvider.FilteredRequestLogger( | ||
delegate, | ||
1000 | ||
); | ||
RequestLogLine requestLogLine = EasyMock.createMock(RequestLogLine.class); | ||
EasyMock.expect(requestLogLine.getQueryStats()) | ||
.andReturn(new QueryStats(ImmutableMap.<String, Object>of("query/time", 10000))) | ||
.once(); | ||
EasyMock.expect(requestLogLine.getQueryStats()) | ||
.andReturn(new QueryStats(ImmutableMap.<String, Object>of("query/time", 1000))) | ||
.once(); | ||
EasyMock.replay(requestLogLine, delegate); | ||
logger.log(requestLogLine); | ||
logger.log(requestLogLine); | ||
|
||
EasyMock.verify(requestLogLine, delegate); | ||
} | ||
} |