/* * Copyright 2014-2016 CyberVision, Inc. * * 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 org.kaaproject.kaa.server.appenders.file.appender; import org.kaaproject.kaa.common.dto.logs.LogAppenderDto; import org.kaaproject.kaa.common.dto.logs.LogEventDto; import org.kaaproject.kaa.server.appenders.file.config.gen.FileConfig; import org.kaaproject.kaa.server.common.log.shared.appender.AbstractLogAppender; import org.kaaproject.kaa.server.common.log.shared.appender.LogDeliveryCallback; import org.kaaproject.kaa.server.common.log.shared.appender.LogEventPack; import org.kaaproject.kaa.server.common.log.shared.avro.gen.RecordHeader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.nio.file.Paths; import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; public class FileSystemLogAppender extends AbstractLogAppender<FileConfig> { private static final Logger LOG = LoggerFactory.getLogger(FileSystemLogAppender.class); private FileSystemLogEventService fileSystemLogEventService; private FileSystemLogger logger; private String logsRootPath; private String tenantDirName; private String applicationDirName; private boolean closed = false; public FileSystemLogAppender() { super(FileConfig.class); } @Override public void doAppend(LogEventPack logEventPack, RecordHeader header, LogDeliveryCallback listener) { if (!closed) { try { String path = logsRootPath + "/" + tenantDirName + "/" + applicationDirName; LOG.debug("[{}] appending {} logs to directory", path, logEventPack.getEvents().size()); List<String> dtos = eventsToStrings(generateLogEvent(logEventPack, header)); LOG.debug("[{}] saving {} objects", path, dtos.size()); for (String event : dtos) { logger.append(event); } LOG.debug("[{}] appended {} logs to directory", path, logEventPack.getEvents().size()); listener.onSuccess(); } catch (Exception ex) { LOG.error(MessageFormat.format("[{0}] Attempted to append logs failed", getName()), ex); listener.onInternalError(); } } else { LOG.info("Attempted to append to closed appender named [{}].", getName()); listener.onInternalError(); } } private List<String> eventsToStrings(List<LogEventDto> dtos) { List<String> events = new ArrayList<>(); for (LogEventDto logEventDto : dtos) { String event = new StringBuilder("{\"Log Header\": \"") .append(logEventDto.getHeader()) .append("\", \"Event\": ") .append(logEventDto.getEvent()) .append("}").toString(); events.add(event); } return events; } @Override protected void initFromConfiguration(LogAppenderDto appenderDto, FileConfig configuration) { LOG.debug("Initializing new instance of file system log appender"); try { logsRootPath = configuration.getLogsRootPath(); if (fileSystemLogEventService == null) { fileSystemLogEventService = new FileSystemLogEventServiceImpl(); } if (logger == null) { logger = new LogbackFileSystemLogger(); } initLogDirectories(appenderDto); logger.init(appenderDto, configuration, Paths.get(logsRootPath, tenantDirName, applicationDirName, "application.log")); fileSystemLogEventService.createUserAndGroup(appenderDto, configuration, Paths.get(logsRootPath, tenantDirName, applicationDirName).toAbsolutePath().toString()); } catch (Exception ex) { LOG.error("Failed to init file system log appender: ", ex); } } private void createTenantLogDirectory(String tenantId) { tenantDirName = "tenant_" + tenantId; fileSystemLogEventService.createDirectory(logsRootPath + "/" + tenantDirName); } private void createApplicationLogDirectory(String applicationToken) { applicationDirName = "application_" + applicationToken; fileSystemLogEventService .createDirectory(logsRootPath + "/" + tenantDirName + "/" + applicationDirName); } private void initLogDirectories(LogAppenderDto appender) { fileSystemLogEventService.createRootLogDirCommand(logsRootPath); createTenantLogDirectory(appender.getTenantId()); createApplicationLogDirectory(appender.getApplicationToken()); } @Override public void close() { if (!closed) { closed = true; if (logger != null) { try { logger.close(); } catch (IOException ex) { LOG.warn("IO Exception catched: ", ex); } } fileSystemLogEventService = null; logger = null; } LOG.debug("Stoped filesystem log appender."); } }