Parse log file while with between lines relation - file

I have long log file that contents looks like
2015-06-13 20:58:32,278 60157353 [Thread-1] DEBUG ccc - start PROC, will wait 30
2015-06-13 20:58:32,302 60157377 [Thread-1] DEBUG ccc - stoping PROC 0
2015-06-13 20:58:42,339 60167414 [Thread-1] DEBUG ccc - start PROC, will wait 30
2015-06-13 20:58:42,363 60167438 [Thread-1] DEBUG ccc - stoping PROC 0
2015-06-13 20:58:52,378 60177453 [Thread-1] DEBUG ccc - start PROC, will wait 30
2015-06-13 20:58:52,404 60177479 [Thread-1] DEBUG ccc - stoping PROC 0
2015-06-13 20:58:52,430 60177506 [Thread-1] DEBUG ccc - start PROC, will wait 30
I need to check time between start PROC and stoping PROC is not longer than 30 seconds.
Is it somehow possible do this with any log parser software?

Using a LogMX Parser, you can mark each start/stop couple as "Too long" (if there is more than 30s between start PROC and stoping PROC).
In the following Parser example, when the elapsed time is greater than 30s:
The user-defined log entry field named "TooLong" is set to "x" (else, it is empty) => can easily filter/sort/search using this field
The stoping PROC entry is marked as ERROR to appear in red => can quickly see it
Of course, you can adjust this code according to your needs.
To use this parser:
Copy the following code in a new file <LogMX_dir>/parsers/src/sample/parser/VicoParser.java
Compile it using Eclipse, IntelliJ IDEA, Maven, Gradle, or Ant using files in <LogMX_dir>/parsers (see LogMX documentation)
Add this Parser in LogMX using menu "Tools" > "Options" > "Parsers" > green "+" button > "Java class Parser" tab > choose <LogMX_dir>/parsers/classes/sample.parser/VicoParser
VicoParser.java:
package sample.parser;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.lightysoft.logmx.business.ParsedEntry;
import com.lightysoft.logmx.mgr.LogFileParser;
/**
* Sample LogMX Parser able to parse a log file with multi-line support, Absolute/Relative Date support,
* and detection of too-long elapsed time between too specific entries.<BR/>
*
* Log4j Pattern for this log format is:
* %d %-4r [%t] %-5p %c %x - %m%n
*
* Here is an example of log file suitable for this parser:<BR/>
* 2015-06-13 20:58:32,278 60157353 [Thread-1] DEBUG ccc - start PROC, will wait 30
* 2015-06-13 20:58:32,302 60157377 [Thread-1] DEBUG ccc - stoping PROC 0
* 2015-06-13 20:58:42,339 60167414 [Thread-1] DEBUG ccc - start PROC, will wait 30
* 2015-06-13 20:58:42,363 60167438 [Thread-1] DEBUG ccc - stoping PROC 0
* 2015-06-13 20:58:52,378 60177453 [Thread-1] DEBUG ccc - start PROC, will wait 30
* 2015-06-13 20:58:52,404 60177479 [Thread-1] DEBUG ccc - stoping PROC 0
* 2015-06-13 20:58:52,430 60177506 [Thread-1] DEBUG ccc - start PROC, will wait 30
*/
public class VicoParser extends LogFileParser {
/** Current parsed log entry */
private ParsedEntry entry = null;
/** Entry date format (this is Log4j default ISO-8601) */
private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS");
/** Mutex to avoid that multiple threads use the same Date formatter at the same time */
private final Object DATE_FORMATTER_MUTEX = new Object();
/** Pattern for entry begin */
private final static Pattern ENTRY_BEGIN_PATTERN = Pattern.compile(
// %d
"^(\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2},\\d+?)\\s+?"
// %-4r [%t] %-5p
+ "(\\d+?)\\s+?\\[(.*?)\\]\\s+?(.*?)\\s+?"
// %c %x - %m
+ "(.*?) (.*?) - (.*)$");
/** Buffer for Entry message (improves performance for multi-lines entries) */
private StringBuilder entryMsgBuffer = null;
///////////// Elapsed-Time computation ////////////
/** Log entry message used for T0 (elapsed time calculation) */
private static final String LOG_MESSAGE_T0 = "start PROC";
/** Log entry message used for T1 (elapsed time calculation) */
private static final String LOG_MESSAGE_T1 = "stoping PROC";
/** Last encountered T0 entry */
private ParsedEntry prevT0Entry = null;
/** Max allowed time between entries, before raising "TooLong" flag */
private static final long MAXIMUM_DELTA_T = 30000L; // 30s (30,000 ms)
/////////////////////////////////////////////////////
/** Key of user-defined field "Timestamp" (internal, not displayed) */
private static final String EXTRA_FIELD_KEY__TIMESTAMP = "Timestamp";
/** Key of user-defined field "NDC" */
private static final String EXTRA_FIELD_KEY__NDC = "NDC";
/** Key of user-defined field "TooLong" */
private static final String EXTRA_FIELD_KEY__TOOLONG = "TooLong";
/** User-defined fields names */
private static final List<String> EXTRA_FIELDS_KEYS = Arrays.asList(EXTRA_FIELD_KEY__NDC,
EXTRA_FIELD_KEY__TOOLONG);
/**
* Returns the name of this parser
* #see com.lightysoft.logmx.mgr.LogFileParser#getParserName()
*/
#Override
public String getParserName() {
return "Vico Parser";
}
/**
* Returns the supported file type for this parser
* #see com.lightysoft.logmx.mgr.LogFileParser#getSupportedFileType()
*/
#Override
public String getSupportedFileType() {
return "Vico log files";
}
/**
* Process the new line of text read from file
* #see com.lightysoft.logmx.mgr.LogFileParser#parseLine(java.lang.String)
*/
#Override
protected void parseLine(String line) throws Exception {
// If end of file, records last entry if necessary, and exits
if (line == null) {
recordPreviousEntryIfExists();
return;
}
Matcher matcher = ENTRY_BEGIN_PATTERN.matcher(line);
if (matcher.matches()) {
// Record previous found entry if exists, then create a new one
prepareNewEntry();
entry.setDate(matcher.group(1));
entry.setThread(matcher.group(3));
entry.setLevel(matcher.group(4));
entry.setEmitter(matcher.group(5));
String logMsg = matcher.group(7);
// Save relative timestamp (in ms), for "getRelativeEntryDate()", but also to compute elapsed
// time between two specific log entries (faster than parsing complete absolute date)
long timestamp = Integer.parseInt(matcher.group(2), 10);
entryMsgBuffer.append(logMsg);
entry.getUserDefinedFields().put(EXTRA_FIELD_KEY__NDC, matcher.group(6)); // save NDC
entry.getUserDefinedFields().put(EXTRA_FIELD_KEY__TIMESTAMP, timestamp); // save Timestamp
if (logMsg.startsWith(LOG_MESSAGE_T0)) {
if (prevT0Entry != null) {
System.err.println("Warning: found [" + LOG_MESSAGE_T0 + "] not followed by ["
+ LOG_MESSAGE_T1 + "]");
}
prevT0Entry = entry;
} else if (logMsg.startsWith(LOG_MESSAGE_T1)) {
if (prevT0Entry == null) {
System.err.println("Warning: found [" + LOG_MESSAGE_T1 + "] not preceded by ["
+ LOG_MESSAGE_T0 + "]");
} else {
long prevT0 = (Long) prevT0Entry.getUserDefinedFields().get(
EXTRA_FIELD_KEY__TIMESTAMP);
if (timestamp - prevT0 > MAXIMUM_DELTA_T) {
entry.getUserDefinedFields().put(EXTRA_FIELD_KEY__TOOLONG, "x"); // Flag this entry as "TooLong"
prevT0Entry.getUserDefinedFields().put(EXTRA_FIELD_KEY__TOOLONG, "x"); // Flag this entry as "TooLong"
// Change log entry Level (note: cannot change Level of T0 entry because it has been already processed by LogMX)
entry.setLevel("ERROR");
}
prevT0Entry = null;
}
}
} else if (entry != null) {
entryMsgBuffer.append('\n').append(line); // appends this line to previous entry's text
}
}
/**
* Returns the ordered list of user-defined fields to display (given by their key), for each entry.
* #see com.lightysoft.logmx.mgr.LogFileParser#getUserDefinedFields()
*/
#Override
public List<String> getUserDefinedFields() {
return EXTRA_FIELDS_KEYS;
}
/**
* Returns a relative Date for the given entry
* #see com.lightysoft.logmx.mgr.LogFileParser#getRelativeEntryDate(com.lightysoft.logmx.business.ParsedEntry)
*/
#Override
public Date getRelativeEntryDate(ParsedEntry pEntry) throws Exception {
Long timestamp = (Long) pEntry.getUserDefinedFields().get(EXTRA_FIELD_KEY__TIMESTAMP);
return new Date(timestamp);
}
/**
* Returns the absolute Date for the given entry
* #see com.lightysoft.logmx.mgr.LogFileParser#getAbsoluteEntryDate(com.lightysoft.logmx.business.ParsedEntry)
*/
#Override
public Date getAbsoluteEntryDate(ParsedEntry pEntry) throws Exception {
synchronized (DATE_FORMATTER_MUTEX) { // Java date formatter is not thread-safe
return dateFormat.parse(pEntry.getDate());
}
}
/**
* Send to LogMX the current parsed log entry
* #throws Exception
*/
private void recordPreviousEntryIfExists() throws Exception {
if (entry != null) {
entry.setMessage(entryMsgBuffer.toString());
addEntry(entry);
}
}
/**
* Send to LogMX the current parsed log entry, then create a new one
* #throws Exception
*/
private void prepareNewEntry() throws Exception {
recordPreviousEntryIfExists();
entry = createNewEntry();
entryMsgBuffer = new StringBuilder(80);
entry.setUserDefinedFields(new HashMap<String, Object>(4));
}
}
And here is what I get:
Note: you can sort/filter log entries using the field named "TooLong" by clicking on its column (mouse left/middle button, or menu "Filter" > "Show filtering bar")

Related

My H2/C3PO/Hibernate setup does not seem to preserving prepared statements?

I am finding my database is the bottleneck in my application, as part of this it looks like Prepared statements are not being reused.
For example here method I use
public static CoverImage findCoverImageBySource(Session session, String src)
{
try
{
Query q = session.createQuery("from CoverImage t1 where t1.source=:source");
q.setParameter("source", src, StandardBasicTypes.STRING);
CoverImage result = (CoverImage)q.setMaxResults(1).uniqueResult();
return result;
}
catch (Exception ex)
{
MainWindow.logger.log(Level.SEVERE, ex.getMessage(), ex);
}
return null;
}
But using Yourkit profiler it says
com.mchange.v2.c3po.impl.NewProxyPreparedStatemtn.executeQuery() Count 511
com.mchnage.v2.c3po.impl.NewProxyConnection.prepareStatement() Count 511
and I assume that the count for prepareStatement() call should be lower, ais it is looks like we create a new prepared statment every time instead of reusing.
https://docs.oracle.com/javase/7/docs/api/java/sql/Connection.html
I am using C3po connecting poolng wehich complicates things a little, but as I understand it I have it configured correctly
public static Configuration getInitializedConfiguration()
{
//See https://www.mchange.com/projects/c3p0/#hibernate-specific
Configuration config = new Configuration();
config.setProperty(Environment.DRIVER,"org.h2.Driver");
config.setProperty(Environment.URL,"jdbc:h2:"+Db.DBFOLDER+"/"+Db.DBNAME+";FILE_LOCK=SOCKET;MVCC=TRUE;DB_CLOSE_ON_EXIT=FALSE;CACHE_SIZE=50000");
config.setProperty(Environment.DIALECT,"org.hibernate.dialect.H2Dialect");
System.setProperty("h2.bindAddress", InetAddress.getLoopbackAddress().getHostAddress());
config.setProperty("hibernate.connection.username","jaikoz");
config.setProperty("hibernate.connection.password","jaikoz");
config.setProperty("hibernate.c3p0.numHelperThreads","10");
config.setProperty("hibernate.c3p0.min_size","1");
//Consider that if we have lots of busy threads waiting on next stages could we possibly have alot of active
//connections.
config.setProperty("hibernate.c3p0.max_size","200");
config.setProperty("hibernate.c3p0.max_statements","5000");
config.setProperty("hibernate.c3p0.timeout","2000");
config.setProperty("hibernate.c3p0.maxStatementsPerConnection","50");
config.setProperty("hibernate.c3p0.idle_test_period","3000");
config.setProperty("hibernate.c3p0.acquireRetryAttempts","10");
//Cancel any connection that is more than 30 minutes old.
//config.setProperty("hibernate.c3p0.unreturnedConnectionTimeout","3000");
//config.setProperty("hibernate.show_sql","true");
//config.setProperty("org.hibernate.envers.audit_strategy", "org.hibernate.envers.strategy.ValidityAuditStrategy");
//config.setProperty("hibernate.format_sql","true");
config.setProperty("hibernate.generate_statistics","true");
//config.setProperty("hibernate.cache.region.factory_class", "org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory");
//config.setProperty("hibernate.cache.use_second_level_cache", "true");
//config.setProperty("hibernate.cache.use_query_cache", "true");
addEntitiesToConfig(config);
return config;
}
Using H2 1.3.172, Hibernate 4.3.11 and the corresponding c3po for that hibernate version
With reproducible test case we have
HibernateStats
HibernateStatistics.getQueryExecutionCount() 28
HibernateStatistics.getEntityInsertCount() 119
HibernateStatistics.getEntityUpdateCount() 39
HibernateStatistics.getPrepareStatementCount() 189
Profiler, method counts
GooGooStaementCache.aquireStatement() 35
GooGooStaementCache.checkInStatement() 189
GooGooStaementCache.checkOutStatement() 189
NewProxyPreparedStatement.init() 189
I don't know what I shoud be counting as creation of prepared statement rather than reusing an existing prepared statement ?
I also tried enabling c3p0 logging by adding a c3p0 logger ands making it use same log file in my LogProperties but had no effect.
String logFileName = Platform.getPlatformLogFolderInLogfileFormat() + "songkong_debug%u-%g.log";
FileHandler fe = new FileHandler(logFileName, LOG_SIZE_IN_BYTES, 10, true);
fe.setEncoding(StandardCharsets.UTF_8.name());
fe.setFormatter(new com.jthink.songkong.logging.LogFormatter());
fe.setLevel(Level.FINEST);
MainWindow.logger.addHandler(fe);
Logger c3p0Logger = Logger.getLogger("com.mchange.v2.c3p0");
c3p0Logger.setLevel(Level.FINEST);
c3p0Logger.addHandler(fe);
Now that I have eventually got c3p0Based logging working and I can confirm the suggestion of #Stevewaldman is correct.
If you enable
public static Logger c3p0ConnectionLogger = Logger.getLogger("com.mchange.v2.c3p0.stmt");
c3p0ConnectionLogger.setLevel(Level.FINEST);
c3p0ConnectionLogger.setUseParentHandlers(false);
Then you get log output of the form
24/08/2019 10.20.12:BST:FINEST: com.mchange.v2.c3p0.stmt.DoubleMaxStatementCache ----> CACHE HIT
24/08/2019 10.20.12:BST:FINEST: checkoutStatement: com.mchange.v2.c3p0.stmt.DoubleMaxStatementCache stats -- total size: 347; checked out: 1; num connections: 13; num keys: 347
24/08/2019 10.20.12:BST:FINEST: checkinStatement(): com.mchange.v2.c3p0.stmt.DoubleMaxStatementCache stats -- total size: 347; checked out: 0; num connections: 13; num keys: 347
making it clear when you get a cache hit. When there is no cache hit yo dont get the first line, but get the other two lines.
This is using C3p0 9.2.1

do we need to write a batchable class to schedule a class

I am trying to generate a report and send a report to email as an attachment in salesforce. I have created a controller, created a class for csv stream and an email template. I want to schedule the class. when I schedule it I am unable to achieve the result. Could anyone help me in achieving this?
The code I tried is created a visualforce component, class, and an email template.
The code I tried is to schedule it for every 5 minutes. but I am getting an error.
Do we need to write a batchable class for this
global class IncrementReport implements Schedulable {
global void execute(SchedulableContext ctx) {
System.debug('Entered Cron trigger');
rptobj__c r = [SELECT Id, Name, reporttrigger__c FROM rptobj__c WHERE Name = 'ThisReport' LIMIT 1];
r.reporttrigger__c += 1;
String s = '0 0 * * * ?' ';
IncrementReport abc = new IncrementReport();
system.schedule('Report Job', s, abc);
System.debug('updating trigger to: ' + r.reporttrigger__c);
update r;
}
}
You only write the logic in your scheduler class.
global class IncrementReport implements Schedulable {
global void execute(SchedulableContext ctx) {
System.debug('Entered Cron trigger');
rptobj__c r = [SELECT Id, Name, reporttrigger__c FROM rptobj__c WHERE Name = 'ThisReport' LIMIT 1];
r.reporttrigger__c += 1;
System.debug('updating trigger to: ' + r.reporttrigger__c);
update r;
}
}
And then, can run this cron expression from Developer Console.
String sch1 = '0 0 * * * ?';
IncrementReport ir1 = new IncrementReport();
system.schedule('Every Hour plus 0 min', sch1, ir1);
String sch2 = '0 5 * * * ?';
IncrementReport ir2 = new IncrementReport();
system.schedule('Every Hour plus 5 min', sch2, ir2);
String sch3 = '0 10 * * * ?';
IncrementReport ir3 = new IncrementReport();
system.schedule('Every Hour plus 10 min', sch3, ir3);
String sch4 = '0 15 * * * ?';
IncrementReport ir4 = new IncrementReport();
system.schedule('Every Hour plus 15 min', sch4, ir4);
// And so on ir5, ir6 .... ir12
As you want to run the scheduler in every 5 minutes, you have to system.schedule 12 times as 12*5 = 60 minutes = 1 hour
You can see whether the job is running or not on
Setup -> Scheduled Jobs

How to remove unnecessary parsing related info from Tika parsing output

I am parsing docx file with Apache Tika. Parsing is working file expect that it also prints some unnecessary texts in the beginning like below:
[Content_Types] .xml _rels / .rels word / _rels / document.xml.rels
word / document.xml
and at the end like below:
word / theme / theme1.xml word / settings.xml word / fontTable.xml
word / webSettings.xml docProps / app.xml Normal 13 3 460 2627
Microsoft Office Word 0 21 6 false XXXX XXXX false 3081 false false
12.0000 docProps / core. xml XXX XXXX 1 2016- 12-16T14: 57: 00Z 2016-12-16T15: 10: 00Z word / styles.xml
Code is :
public static String extractString(File file)
{
BodyContentHandler handler = new BodyContentHandler();
AutoDetectParser parser = new AutoDetectParser();
Metadata metadata = new Metadata();
try (InputStream stream = new FileInputStream(file))
{
parser.parse(stream, handler, metadata);
return handler.toString();
}
catch (IOException | SAXException | TikaException e)
{
e.printStackTrace();
return null;
}
}
How to remove the unnecessary crap from the beginning and end?

Solr 6.0.0 - SolrCloud java example

I have solr installed on my localhost.
I started standard solr cloud example with embedded zookeepr.
collection: gettingstarted
shards: 2
replication : 2
500 records/docs to process time took 115 seconds[localhost tetsing] -
why is this taking this much time to process just 500 records.
is there a way to improve this to some millisecs/nanosecs
NOTE:
I have tested the same on remote machine solr instance, localhost having data index on remote solr [inside java commented]
I started my solr myCloudData collection with Ensemble with single zookeepr.
2 solr nodes,
1 Ensemble zookeeper standalone
collection: myCloudData,
shards: 2,
replication : 2
Solr colud java code
package com.test.solr.basic;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.common.SolrInputDocument;
public class SolrjPopulatorCloudClient2 {
public static void main(String[] args) throws IOException,SolrServerException {
//String zkHosts = "64.101.49.57:2181/solr";
String zkHosts = "localhost:9983";
CloudSolrClient solrCloudClient = new CloudSolrClient(zkHosts, true);
//solrCloudClient.setDefaultCollection("myCloudData");
solrCloudClient.setDefaultCollection("gettingstarted");
/*
// Thread Safe
solrClient = new ConcurrentUpdateSolrClient(urlString, queueSize, threadCount);
*/
// Depreciated - client
//HttpSolrServer server = new HttpSolrServer("http://localhost:8983/solr");
long start = System.nanoTime();
for (int i = 0; i < 500; ++i) {
SolrInputDocument doc = new SolrInputDocument();
doc.addField("cat", "book");
doc.addField("id", "book-" + i);
doc.addField("name", "The Legend of the Hobbit part " + i);
solrCloudClient.add(doc);
if (i % 100 == 0)
System.out.println(" Every 100 records flush it");
solrCloudClient.commit(); // periodically flush
}
solrCloudClient.commit();
solrCloudClient.close();
long end = System.nanoTime();
long seconds = TimeUnit.NANOSECONDS.toSeconds(end - start);
System.out.println(" All records are indexed, took " + seconds + " seconds");
}
}
You are committing every new document, which is not necessary. It will run a lot faster if you change the if (i % 100 == 0) block to read
if (i % 100 == 0) {
System.out.println(" Every 100 records flush it");
solrCloudClient.commit(); // periodically flush
}
On my machine, this indexes your 500 records in 14 seconds. If I remove the commit() call from the for loop, it indexes in 7 seconds.
Alternatively, you can add a commitWithinMs parameter to the solrCloudClient.add() call:
solrCloudClient.add(doc, 15000);
This will guarantee your records are committed within 15 seconds, and also increase your indexing speed.

I cannot set the AM_PM variable in Java 8 Micro Edition

I'm a teaching myself Java and am a beginner. As part of a larger project I am running code to determine, and then later set, the time on a Calendar object. I have scoured the internet for a way to set the AM_PM value but I cannot get it to work. Any suggestions would help.
package timethread;
import javax.microedition.midlet.MIDlet;
import java.util.Calendar;
/**
*
* #author Jaydawg
*/
public class TimeThread extends MIDlet {
#Override
public void startApp() {
Calendar cal = Calendar.getInstance();
System.out.println(cal.get(Calendar.AM_PM)); // Original value: it is '1' or PM
cal.add(Calendar.AM_PM, 0); // Attempt #1
System.out.println(cal.get(Calendar.AM_PM));
cal.set(Calendar.AM_PM, 0); // Attempt #2
System.out.println(cal.get(Calendar.AM_PM));
cal.set(Calendar.AM_PM, Calendar.AM); //Attempt #3
System.out.println(cal.get(Calendar.AM_PM));
cal.add(Calendar.AM_PM, Calendar.AM); //Attempt #4
System.out.println(cal.get(Calendar.AM_PM));
int min = cal.get(Calendar.MINUTE);
int sec = cal.get(Calendar.SECOND);
int hour = cal.get(Calendar.HOUR);
int AMPM = cal.get(Calendar.AM_PM);
System.out.println(AMPM);
String AMPMString = "AM";
if(cal.get(Calendar.AM_PM)==1){
AMPMString = "PM";
}
System.out.println("The time is " + hour + ":" + min + ":" + sec + " " + AMPMString);
}
My results were as follows:
1
1
1
1
1
1
The time is 1:20:42 PM
Maybe a bug with Calendar in Java 8 Micro Edition?
This works for me with Java 7:
Calendar c = Calendar.getInstance();
c.set(Calendar.AM_PM, Calendar.AM);
System.out.println(c.get(Calendar.AM_PM));
c.set(Calendar.AM_PM, Calendar.PM);
System.out.println(c.get(Calendar.AM_PM));
it outputs:
0
1
This was confirmed to be a bug by Oracle.
https://community.oracle.com/thread/3728182?sr=inbox&ru=997534

Resources