diff options
author | Harald Musum <musum@oath.com> | 2018-04-12 13:12:49 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-04-12 13:12:49 +0200 |
commit | 787d8e243f59c1c93a9de4edb7f8e8852e5f6ccf (patch) | |
tree | da1ef98a1b7ffb1edacd9f12457645f306183bae /configserver | |
parent | eac5237fb03725d42556f1a54558411a5ee178ab (diff) |
Revert "Return empty string from grabLog()"
Diffstat (limited to 'configserver')
4 files changed, 132 insertions, 11 deletions
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java b/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java index 6aba6d12751..2443e56b2d9 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java @@ -26,6 +26,7 @@ import com.yahoo.vespa.config.server.application.ApplicationConvergenceChecker; import com.yahoo.vespa.config.server.application.ApplicationSet; import com.yahoo.vespa.config.server.application.FileDistributionStatus; import com.yahoo.vespa.config.server.application.HttpProxy; +import com.yahoo.vespa.config.server.application.LogServerLogGrabber; import com.yahoo.vespa.config.server.application.TenantApplications; import com.yahoo.vespa.config.server.configchange.ConfigChangeActions; import com.yahoo.vespa.config.server.configchange.RefeedActions; @@ -79,6 +80,7 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye private final Tenants tenants; private final Optional<Provisioner> hostProvisioner; + private final LogServerLogGrabber logServerLogGrabber; private final ApplicationConvergenceChecker convergeChecker; private final HttpProxy httpProxy; private final Clock clock; @@ -90,10 +92,11 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye @Inject public ApplicationRepository(Tenants tenants, HostProvisionerProvider hostProvisionerProvider, + LogServerLogGrabber logServerLogGrabber, ApplicationConvergenceChecker applicationConvergenceChecker, HttpProxy httpProxy, ConfigserverConfig configserverConfig) { - this(tenants, hostProvisionerProvider.getHostProvisioner(), + this(tenants, hostProvisionerProvider.getHostProvisioner(), logServerLogGrabber, applicationConvergenceChecker, httpProxy, configserverConfig, Clock.systemUTC(), new FileDistributionStatus()); } @@ -101,13 +104,14 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye public ApplicationRepository(Tenants tenants, Provisioner hostProvisioner, Clock clock) { - this(tenants, Optional.of(hostProvisioner), + this(tenants, Optional.of(hostProvisioner), new LogServerLogGrabber(), new ApplicationConvergenceChecker(), new HttpProxy(new SimpleHttpFetcher()), new ConfigserverConfig(new ConfigserverConfig.Builder()), clock, new FileDistributionStatus()); } private ApplicationRepository(Tenants tenants, Optional<Provisioner> hostProvisioner, + LogServerLogGrabber logServerLogGrabber, ApplicationConvergenceChecker applicationConvergenceChecker, HttpProxy httpProxy, ConfigserverConfig configserverConfig, @@ -115,6 +119,7 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye FileDistributionStatus fileDistributionStatus) { this.tenants = tenants; this.hostProvisioner = hostProvisioner; + this.logServerLogGrabber = logServerLogGrabber; this.convergeChecker = applicationConvergenceChecker; this.httpProxy = httpProxy; this.clock = clock; @@ -212,6 +217,11 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye return true; } + public String grabLog(Tenant tenant, ApplicationId applicationId) { + Application application = getApplication(tenant, applicationId); + return logServerLogGrabber.grabLog(application); + } + public HttpResponse serviceConvergenceCheck(Tenant tenant, ApplicationId applicationId, String hostname, URI uri) { Application application = getApplication(tenant, applicationId); return convergeChecker.serviceConvergenceCheck(application, hostname, uri); diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/application/LogServerLogGrabber.java b/configserver/src/main/java/com/yahoo/vespa/config/server/application/LogServerLogGrabber.java new file mode 100644 index 00000000000..b29953187e5 --- /dev/null +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/application/LogServerLogGrabber.java @@ -0,0 +1,94 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.config.server.application; + +import com.yahoo.component.AbstractComponent; +import com.yahoo.config.model.api.PortInfo; +import com.yahoo.config.model.api.ServiceInfo; +import com.yahoo.log.LogLevel; +import com.yahoo.vespa.config.server.http.InternalServerException; +import com.yahoo.yolean.Exceptions; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.Socket; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +/** + * Fetches log entries from logserver with level errors and fatal. The logserver only returns + * a log entry once over this API so doing repeated calls will not give the same results. + * + * @author dybis + */ +public class LogServerLogGrabber extends AbstractComponent { + private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogServerLogGrabber.class.getName()); + + public LogServerLogGrabber() {} + + public String grabLog(Application application) { + LogServerInfo logServerConnectionInfo = findLogserverConnectionInfo(application); + log.log(LogLevel.DEBUG, "Requested error logs, pulling from logserver on " + logServerConnectionInfo); + try { + return readLog(logServerConnectionInfo.hostName, logServerConnectionInfo.port); + } catch (IOException e) { + throw new InternalServerException(Exceptions.toMessageString(e)); + } + } + + private LogServerInfo findLogserverConnectionInfo(Application application) { + List<LogServerInfo> logServerConnectionInfos = new ArrayList<>(); + application.getModel().getHosts() + .forEach(host -> host.getServices().stream() + .filter(service -> service.getServiceType().equals("logserver")) + .forEach(logService -> { + Optional<Integer> logPort = getErrorLogPort(logService); + logPort.ifPresent(port -> logServerConnectionInfos.add(new LogServerInfo(host.getHostname(), port))); + })); + + if (logServerConnectionInfos.size() > 1) throw new RuntimeException("Found several log server ports"); + if (logServerConnectionInfos.size() == 0) throw new InternalServerException("Did not find any log server in config model"); + + return logServerConnectionInfos.get(0); + } + + // Protected to be able to test + protected String readLog(String host, int port) throws IOException { + Socket socket = new Socket(host, port); + BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); + StringBuilder data = new StringBuilder(); + + int bufferSize = 4096; + int charsRead; + do { + char[] buffer = new char[bufferSize]; + charsRead = in.read(buffer); + data.append(new String(buffer, 0, charsRead)); + } while (charsRead == bufferSize); + in.close(); + socket.close(); + return data.toString(); + } + + private Optional<Integer> getErrorLogPort(ServiceInfo service) { + return service.getPorts().stream() + .filter(port -> port.getTags().contains("last-errors-holder")) + .map(PortInfo::getPort) + .findFirst(); + } + + private class LogServerInfo { + String hostName; + int port; + + LogServerInfo(String hostName, int port) { + this.hostName = hostName; + this.port = port; + } + + public String toString() { + return hostName + ":" + port; + } + } +} diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandler.java index 5bcf5da3e90..7be7bfb47e1 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandler.java @@ -120,12 +120,11 @@ public class ApplicationHandler extends HttpHandler { return new JSONResponse(Response.Status.OK); // return empty } - // TODO: Deprecated, will soon be removed, will always return empty string in payload private HttpResponse grabLog(HttpRequest request, ApplicationId applicationId, Tenant tenant) { if (getBindingMatch(request).groupCount() != 7) throw new NotFoundException("Illegal POST log request '" + request.getUri() + "': Must have 6 arguments but had " + ( getBindingMatch(request).groupCount()-1 ) ); - final String response = ""; + final String response = applicationRepository.grabLog(tenant, applicationId); return new HttpResponse(200) { @Override public void render(OutputStream outputStream) throws IOException { diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java index e5f2cc271e3..ef53baf821d 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java @@ -22,6 +22,7 @@ import com.yahoo.vespa.config.server.SuperModelGenerationCounter; import com.yahoo.vespa.config.server.TestComponentRegistry; import com.yahoo.vespa.config.server.application.ApplicationConvergenceChecker; import com.yahoo.vespa.config.server.application.HttpProxy; +import com.yahoo.vespa.config.server.application.LogServerLogGrabber; import com.yahoo.vespa.config.server.http.HandlerTest; import com.yahoo.vespa.config.server.http.HttpErrorResponse; import com.yahoo.vespa.config.server.http.StaticResponse; @@ -86,20 +87,27 @@ public class ApplicationHandlerTest { tenants = testBuilder.createTenants(); provisioner = new SessionHandlerTest.MockProvisioner(); - mockHandler = createApplicationHandler(provisioner, new ApplicationConvergenceChecker(stateApiFactory), mockHttpProxy); + mockHandler = createMockApplicationHandler( + provisioner, + new ApplicationConvergenceChecker(stateApiFactory), + mockHttpProxy, + new MockLogServerLogGrabber()); listApplicationsHandler = new ListApplicationsHandler( ListApplicationsHandler.testOnlyContext(), tenants, Zone.defaultZone()); } - private ApplicationHandler createApplicationHandler(Provisioner provisioner, - ApplicationConvergenceChecker convergeChecker, - HttpProxy httpProxy) { + private ApplicationHandler createMockApplicationHandler( + Provisioner provisioner, + ApplicationConvergenceChecker convergeChecker, + HttpProxy httpProxy, + LogServerLogGrabber logServerLogGrabber) { return new ApplicationHandler( ApplicationHandler.testOnlyContext(), Zone.defaultZone(), new ApplicationRepository(tenants, HostProvisionerProvider.withProvisioner(provisioner), + logServerLogGrabber, convergeChecker, httpProxy, new ConfigserverConfig(new ConfigserverConfig.Builder()))); @@ -111,6 +119,7 @@ public class ApplicationHandlerTest { Zone.defaultZone(), new ApplicationRepository(tenants, HostProvisionerProvider.withProvisioner(provisioner), + new LogServerLogGrabber(), new ApplicationConvergenceChecker(stateApiFactory), new HttpProxy(new SimpleHttpFetcher()), new ConfigserverConfig(new ConfigserverConfig.Builder()))); @@ -205,13 +214,12 @@ public class ApplicationHandlerTest { converge(application, Zone.defaultZone()); } - // TODO: Deprecated, will soon be removed, implementation always returns empty string @Test public void testGrabLog() throws Exception { long sessionId = 1; ApplicationId application = new ApplicationId.Builder().applicationName(ApplicationName.defaultName()).tenant(mytenantName).build(); addMockApplication(tenants.getTenant(mytenantName), application, sessionId, Clock.systemUTC()); - assertEquals("", grabLog(application, Zone.defaultZone())); + assertEquals("log line", grabLog(application, Zone.defaultZone())); } @Test @@ -238,7 +246,11 @@ public class ApplicationHandlerTest { @Ignore public void testFailingProvisioner() throws Exception { provisioner = new SessionHandlerTest.FailingMockProvisioner(); - mockHandler = createApplicationHandler(provisioner, new ApplicationConvergenceChecker(stateApiFactory), new HttpProxy(new SimpleHttpFetcher())); + mockHandler = createMockApplicationHandler( + provisioner, + new ApplicationConvergenceChecker(stateApiFactory), + new HttpProxy(new SimpleHttpFetcher()), + new LogServerLogGrabber()); final ApplicationId applicationId = ApplicationId.defaultId(); addMockApplication(tenants.getTenant(mytenantName), applicationId, 1, Clock.systemUTC()); assertApplicationExists(mytenantName, applicationId, Zone.defaultZone()); @@ -420,4 +432,10 @@ public class ApplicationHandlerTest { } } + private static class MockLogServerLogGrabber extends LogServerLogGrabber { + @Override + protected String readLog(String host, int port) throws IOException { + return "log line"; + } + } } |