Skip to content

Commit

Permalink
Accessing log file via REST.
Browse files Browse the repository at this point in the history
  • Loading branch information
mederly committed Sep 7, 2016
1 parent ed74a80 commit 1894b2d
Show file tree
Hide file tree
Showing 4 changed files with 197 additions and 1 deletion.
Expand Up @@ -12177,4 +12177,32 @@
</xsd:complexType>
<xsd:element name="MappingEvaluationResponse" type="tns:MappingEvaluationResponseType"/>

<xsd:complexType name="LogFileContentType">
<xsd:sequence>
<xsd:element name="content" type="xsd:string"/>
<xsd:element name="at" type="xsd:long">
<xsd:annotation>
<xsd:documentation>
Position of this fragment in the log file.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="complete" type="xsd:boolean">
<xsd:annotation>
<xsd:documentation>
Is the fragment we are returning the complete content of the log file (starting from the given position)?
I.e. if false, there are some data after this fragment.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="logFileSize" type="xsd:long">
<xsd:annotation>
<xsd:documentation>
Current log file size, in bytes.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>

</xsd:schema>
Expand Up @@ -15,6 +15,7 @@
*/
package com.evolveum.midpoint.model.api;

import java.io.IOException;
import java.util.Collection;

import com.evolveum.midpoint.schema.ProvisioningDiag;
Expand All @@ -24,6 +25,7 @@
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.exception.*;
import com.evolveum.midpoint.xml.ns._public.common.common_3.LogFileContentType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.MappingEvaluationRequestType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.MappingEvaluationResponseType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType;
Expand All @@ -45,8 +47,10 @@ public interface ModelDiagnosticService {
String REPOSITORY_SELF_TEST = CLASS_NAME_WITH_DOT + "repositorySelfTest";
String REPOSITORY_TEST_ORG_CLOSURE_CONSISTENCY = CLASS_NAME_WITH_DOT + "repositoryTestOrgClosureConsistency";
String EXECUTE_REPOSITORY_QUERY = CLASS_NAME_WITH_DOT + "executeRepositoryQuery";
String EXECUTE_MAPPING = CLASS_NAME_WITH_DOT + "evaluateMapping";
String EVALUATE_MAPPING = CLASS_NAME_WITH_DOT + "evaluateMapping";
String PROVISIONING_SELF_TEST = CLASS_NAME_WITH_DOT + "provisioningSelfTest";
String GET_LOG_FILE_CONTENT = CLASS_NAME_WITH_DOT + "getLogFileContent";
String GET_LOG_FILE_SIZE = CLASS_NAME_WITH_DOT + "getLogFileSize";

/**
* Provide repository run-time configuration and diagnostic information.
Expand Down Expand Up @@ -113,4 +117,19 @@ String exportDataModel(Collection<String> resourceOids, Task task, OperationResu

String exportDataModel(ResourceType resource, Task task, OperationResult parentResult)
throws SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, SecurityViolationException;

// EXPERIMENTAL

/**
* Returns the contents of the log file.
*
* @param fromPosition From absolute log file position (if non-negative); or counted from the end (if negative).
* @param maxSize Max number of bytes to return.
* @param task
* @param parentResult
*/
LogFileContentType getLogFileContent(Long fromPosition, Long maxSize, Task task, OperationResult parentResult)
throws SecurityViolationException, IOException, SchemaException;

long getLogFileSize(Task task, OperationResult parentResult) throws SchemaException, SecurityViolationException;
}
Expand Up @@ -44,6 +44,7 @@
import com.evolveum.midpoint.schema.GetOperationOptions;
import com.evolveum.midpoint.schema.SelectorOptions;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.logging.LoggingUtils;
import com.evolveum.midpoint.xml.ns._public.common.api_types_3.*;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import com.evolveum.midpoint.xml.ns._public.model.model_3.ExecuteScriptsResponseType;
Expand Down Expand Up @@ -99,6 +100,8 @@ public class ModelRestService {
public static final String OPERATION_SCHEDULE_TASKS_NOW = CLASS_DOT + "scheduleTasksNow";
public static final String OPERATION_EXECUTE_SCRIPT = CLASS_DOT + "executeScript";
public static final String OPERATION_COMPARE = CLASS_DOT + "compare";
public static final String OPERATION_GET_LOG_FILE_CONTENT = CLASS_DOT + "getLogFileContent";
public static final String OPERATION_GET_LOG_FILE_SIZE = CLASS_DOT + "getLogFileSize";


@Autowired
Expand All @@ -110,6 +113,9 @@ public class ModelRestService {
@Autowired
private ModelService modelService;

@Autowired
private ModelDiagnosticService modelDiagnosticService;

@Autowired
private ModelInteractionService modelInteraction;

Expand Down Expand Up @@ -696,6 +702,59 @@ public <T extends ObjectType> Response compare(PrismObject<T> clientObject,
return response;
}

@GET
@Path("/log/size")
@Produces({"text/plain"})
public Response getLogFileSize(@Context MessageContext mc) {

Task task = RestServiceUtil.initRequest(mc);
OperationResult result = task.getResult().createSubresult(OPERATION_GET_LOG_FILE_SIZE);

Response response;
try {
long size = modelDiagnosticService.getLogFileSize(task, result);

ResponseBuilder builder = Response.ok();
builder.entity(String.valueOf(size));
response = builder.build();
} catch (Exception ex) {
response = RestServiceUtil.handleException(ex);
}

result.computeStatus();
finishRequest(task);
return response;
}

@GET
@Path("/log")
@Produces({"text/plain"})
public Response getLog(@QueryParam("fromPosition") Long fromPosition, @QueryParam("maxSize") Long maxSize, @Context MessageContext mc) {

Task task = RestServiceUtil.initRequest(mc);
OperationResult result = task.getResult().createSubresult(OPERATION_GET_LOG_FILE_CONTENT);

Response response;
try {
LogFileContentType content = modelDiagnosticService.getLogFileContent(fromPosition, maxSize, task, result);

ResponseBuilder builder = Response.ok();
builder.entity(content.getContent());
builder.header("ReturnedDataPosition", content.getAt());
builder.header("ReturnedDataComplete", content.isComplete());
builder.header("CurrentLogFileSize", content.getLogFileSize());

response = builder.build();
} catch (Exception ex) {
LoggingUtils.logUnexpectedException(LOGGER, "Cannot get log file content: fromPosition={}, maxSize={}", ex, fromPosition, maxSize);
response = RestServiceUtil.handleException(ex);
}

result.computeStatus();
finishRequest(task);
return response;
}


// @GET
// @Path("tasks/{oid}")
Expand Down
Expand Up @@ -15,17 +15,23 @@
*/
package com.evolveum.midpoint.model.impl.controller;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Collection;
import java.util.List;

import javax.xml.namespace.QName;

import com.evolveum.midpoint.common.configuration.api.MidpointConfiguration;
import com.evolveum.midpoint.model.impl.dataModel.DataModelVisualizer;
import com.evolveum.midpoint.schema.*;
import com.evolveum.midpoint.security.api.AuthorizationConstants;
import com.evolveum.midpoint.security.api.SecurityEnforcer;
import com.evolveum.midpoint.util.exception.*;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
Expand Down Expand Up @@ -74,6 +80,7 @@ public class ModelDiagController implements ModelDiagnosticService {
private static final String INSANE_NATIONAL_STRING = "Pørúga ném nå väšȍm apârátula";

private static final Trace LOGGER = TraceManager.getTrace(ModelDiagController.class);
private static final String LOG_FILE_CONFIG_KEY = "logFile";

@Autowired
private DataModelVisualizer dataModelVisualizer;
Expand All @@ -94,6 +101,9 @@ public class ModelDiagController implements ModelDiagnosticService {
@Autowired
private MappingDiagEvaluator mappingDiagEvaluator;

@Autowired
private MidpointConfiguration midpointConfiguration;

private RandomString randomString;

ModelDiagController() {
Expand Down Expand Up @@ -599,4 +609,84 @@ public String exportDataModel(ResourceType resource, Task task, OperationResult
}
}

@Override
public LogFileContentType getLogFileContent(Long fromPosition, Long maxSize, Task task, OperationResult parentResult)
throws SecurityViolationException, IOException, SchemaException {
OperationResult result = parentResult.createSubresult(GET_LOG_FILE_CONTENT);
try {
securityEnforcer.authorize(AuthorizationConstants.AUTZ_ALL_URL, null, null, null, null, null, result);
File logFile = getLogFile();
LogFileContentType rv = getLogFileFragment(logFile, fromPosition, maxSize);
result.recordSuccess();
return rv;
} catch (Throwable t) {
result.recordFatalError(t.getMessage(), t);
throw t;
}
}

private LogFileContentType getLogFileFragment(File logFile, Long fromPosition, Long maxSize) throws IOException {
LogFileContentType rv = new LogFileContentType();
RandomAccessFile log = null;
try {
log = new RandomAccessFile(logFile, "r");
long currentLength = log.length();
rv.setLogFileSize(currentLength);

long start;
if (fromPosition == null) {
start = 0;
} else if (fromPosition >= 0) {
start = fromPosition;
} else {
start = Math.max(currentLength + fromPosition, 0);
}
rv.setAt(start);
log.seek(start);
long bytesToRead = Math.max(currentLength - start, 0);
if (maxSize != null && maxSize < bytesToRead) {
bytesToRead = maxSize;
rv.setComplete(false);
} else {
rv.setComplete(true);
}
if (bytesToRead == 0) {
return rv;
} else if (bytesToRead > Integer.MAX_VALUE) {
throw new IllegalStateException("Too many bytes to read from log file: " + bytesToRead);
}
byte[] buffer = new byte[(int) bytesToRead];
log.readFully(buffer);
rv.setContent(new String(buffer));
return rv;
} finally {
if (log != null) {
IOUtils.closeQuietly(log);
}
}
}

@Override
public long getLogFileSize(Task task, OperationResult parentResult) throws SchemaException, SecurityViolationException {
OperationResult result = parentResult.createSubresult(GET_LOG_FILE_SIZE);
try {
securityEnforcer.authorize(AuthorizationConstants.AUTZ_ALL_URL, null, null, null, null, null, result);
File logFile = getLogFile();
long size = logFile.length();
result.recordSuccess();
return size;
} catch (Throwable t) {
result.recordFatalError(t.getMessage(), t);
throw t;
}
}

private File getLogFile() throws SchemaException {
Configuration c = midpointConfiguration.getConfiguration(MidpointConfiguration.SYSTEM_CONFIGURATION_SECTION);
if (c == null || !c.containsKey(LOG_FILE_CONFIG_KEY)) {
throw new SchemaException("No log file specified in system configuration. Please set logFile in <midpoint><system> section.");
}
return new File(c.getString(LOG_FILE_CONFIG_KEY));
}

}

0 comments on commit 1894b2d

Please sign in to comment.