/**
* Copyright 2014 Eediom 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.araqne.logdb.metadata;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.felix.ipojo.annotations.Component;
import org.apache.felix.ipojo.annotations.Invalidate;
import org.apache.felix.ipojo.annotations.Requires;
import org.apache.felix.ipojo.annotations.Validate;
import org.araqne.log.api.Log;
import org.araqne.log.api.LogPipe;
import org.araqne.log.api.Logger;
import org.araqne.log.api.MultilineLogExtractor;
import org.araqne.logdb.AccountService;
import org.araqne.logdb.MetadataCallback;
import org.araqne.logdb.MetadataProvider;
import org.araqne.logdb.MetadataService;
import org.araqne.logdb.QueryContext;
import org.araqne.logdb.QueryParseException;
import org.araqne.logdb.Row;
@Component(name = "logdb-log-metadata")
public class LogMetadataProvider implements MetadataProvider {
@Requires
private AccountService accountService;
@Requires
private MetadataService metadataService;
@Validate
public void start() {
metadataService.addProvider(this);
}
@Invalidate
public void stop() {
if (metadataService != null)
metadataService.removeProvider(this);
}
@Override
public String getType() {
return "logs";
}
@Override
public void verify(QueryContext context, String queryString) {
if (!context.getSession().isAdmin()){
// throw new QueryParseException("no-read-permission", -1);
throw new QueryParseException("95020", -1, -1, null);
}
}
@Override
public void query(QueryContext context, String queryString, MetadataCallback callback) {
File dir = new File(System.getProperty("araqne.log.dir"));
List<File> files = new ArrayList<File>();
for (File f : dir.listFiles()) {
if (f.getName().startsWith("araqne.log") && !f.getName().equals("araqne.log"))
files.add(f);
}
Collections.sort(files);
RowPipe pipe = new RowPipe(callback);
// rolled files
for (File f : files) {
loadFile(pipe, f);
}
// today log file
loadFile(pipe, new File(dir, "araqne.log"));
}
private void loadFile(RowPipe pipe, File f) {
FileInputStream is = null;
try {
is = new FileInputStream(f);
MultilineLogExtractor extractor = new MultilineLogExtractor(null, pipe);
extractor.setBeginMatcher(Pattern.compile("^\\[\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2},\\d{3}\\]").matcher(""));
extractor.setDateMatcher(Pattern.compile("\\[(.*)\\]").matcher(""));
extractor.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS"));
extractor.setCharset(Charset.defaultCharset().name());
extractor.extract(is, new AtomicLong());
} catch (IOException e) {
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
}
}
}
}
private static class RowPipe implements LogPipe {
private Matcher matcher;
private MetadataCallback output;
public RowPipe(MetadataCallback output) {
this.output = output;
matcher = Pattern.compile("(?sm)\\[.*?\\]\\s+(\\S+) \\((\\S+)\\) - (.*)").matcher("");
}
@Override
public void onLog(Logger logger, Log log) {
Row row = buildRow(log);
output.onPush(row);
}
@Override
public void onLogBatch(Logger logger, Log[] logs) {
for (Log log : logs) {
if (log == null)
continue;
Row row = buildRow(log);
output.onPush(row);
}
}
private Row buildRow(Log log) {
String line = (String) log.getParams().get("line");
Row row = new Row();
row.put("_time", log.getDate());
if (line != null) {
matcher.reset(line);
if (matcher.matches()) {
row.put("level", matcher.group(1));
row.put("class", matcher.group(2));
row.put("msg", matcher.group(3));
} else {
row.put("line", line);
}
}
return row;
}
}
}