Skip to content

sswayney/seq-logback-appender

Repository files navigation

seq-logback-appender

Send logback log events to a seq server

Build Status

Install

Maven

Add Repo

	<repositories>
		<repository>
		    <id>jitpack.io</id>
		    <url>https://jitpack.io</url>
		</repository>
	</repositories>

Add Dependency

	<dependency>
	    <groupId>com.github.sswayney</groupId>
	    <artifactId>seq-logback-appender</artifactId>
	    <version>VERSION</version>
	</dependency>

Gradle

Add Repo

	allprojects {
		repositories {
			...
			maven { url 'https://jitpack.io' }
		}
	}

Add Dependency

	dependencies {
	        implementation 'com.github.sswayney:seq-logback-appender:VERSION'
	}

Usage

Add the required properties to your application.yaml file. Note, batchCount defaults to 1.

Also Note (Issue #12) if you set a large batch count then applications that log infrequently may be holding messages in the buffer for an extended period of time. A scheduled job that runs once per day for example may have finished processing, but you won't see the final messages until the job starts the following day.

seq:
  batchCount: 5
  apiKey: YOURAPIKEY
  server: http://URLTOYOURSEQSERVER
  port: 80

For each project, include the seq logback settings file in your main logback settings file, and you must include a project name property which will be used for the logging filename

    <property name="PROJECT_NAME" value="my-service"/>
    <include resource="seq-logback-settings.xml" />

Then, you can add the appenders to your profiles. "SEQ" sends logs to server and "FILE" logs to a file under applogs/PROJECT_NAME.log and CONSOLE to the console

    <springProfile name="dev">
        <root level="INFO">
            <appender-ref ref="SEQ" />
            <appender-ref ref="FILE" />
            <appender-ref ref="CONSOLE" />
        </root>
    </springProfile>

You should also add this to your .gitignore file

    ### logs folder ###
    applogs

To use the logs in Java you can do something like this:

    import lombok.extern.slf4j.Slf4j;
    import static ses.seq.logback.marker.ObjectAppendingMarker.append;
    
    @Slf4j
    public class MyClass {
    
        public void myMethod(String input, JsonPojo pojo) {
            //basic logs message
            log.info("Entering test method, input: {}", input);
    
            //json object logging for debugging
            log.info(append(pojo), "Object state");
    
            try {
                Integer.parseInt("FAIL");
            } catch (NumberFormatException e) {
                //exception logging
                log.error("Exception in complex method", e);
            }
        }
    }

Done... It should log basic messages.

Adding more data to log

The base Seq Log Event Layout SeqLogEventLayout will map the basic logging data to the base SeqLogEntry object and send it to the specified seq server. To add more, extend SeqLogEventLayout and SeqLogEntry to add more data. Then set the seq layout class to use in your logback settings file.

Example:

1: Extend SeqLogEntry to add your fields. Note, I'm using lombok to create my getter/setters. You could do the same or create your own getter setters.

@Getter
@Setter
public class MyCustomSeqLogEntry extends SeqLogEntry {

    @JsonProperty("User")
    private String user;

    @JsonProperty("Method")
    private String method;

    @JsonProperty("Pid")
    private String pid;

    @JsonProperty("Query")
    private String query;

    @JsonProperty("Referer")
    private String referer;

    @JsonProperty("IP")
    private String ip;

    @JsonProperty("Url")
    private String url;

    @JsonProperty("Token")
    private String token;

    /**
     * Constructor
     * @param eventObject The logback event
     * @param dateFormat Date format for timestamp
     */
    public MyCustomSeqLogEntry(ILoggingEvent eventObject, Format dateFormat) {
        super(eventObject, dateFormat);
        Map<String, String> mdc = eventObject.getMDCPropertyMap();
        this.setUser(mdc.get(Constants.LOGGED_ON_USER_NAME));
        this.setMethod(mdc.get(Constants.REQUEST_METHOD));
        this.setPid(mdc.get(Constants.ADMIN_PID));
        this.setQuery(mdc.get(Constants.REQUEST_QUERY));
        this.setReferer(mdc.get(Constants.REQUEST_REFERER));
        this.setIp(mdc.get(Constants.REQUEST_IP_ADDRESS));
        this.setUrl(mdc.get(Constants.REQUEST_URL));
        this.setToken(mdc.get(Constants.AUTH_TOKEN));
    }
}

2: Extend SeqLogEventLayout to use your new MyCustomSeqLogEntry class

public class MyCustomSeqLogEventLayout extends SeqLogEventLayout {

    @Override
    public String doLayout(ILoggingEvent event) {
        return this.getLogEntryJsonString(new MyCustomSeqLogEntry(event, this.dateFormat));
    }
}

3: Add SEQ_LAYOUT property to your base logback settings xml file to use your new extended layout class. Make sure the namespace to your layout is correct.

    <property scope="context" name="SEQ_LAYOUT" value="com.your.namespace.MyCustomSeqLogEventLayout"/>
    <include resource="seq-logback-settings.xml" />

Done. Now these new fields will be added to all your logging events.

Logging request info using MDCWebReqInsertingFilter

Fields: ReqRemoteHost, ReqUserAgent, ReqURI, ReqURL, ReqQueryString, ReqMethod, ReqForwardedFor, ReqReferer, ReqToken, AppHostName

Set up is much like above, but instead of extending the basic SeqLogEntry, you would just extend MDCWebReqSeqLogEntry. And instead of extending SeqLogEventLayout you would extend MDCWebReqSeqLogLayout. But first you need to add LogBack's MDCWebReqInsertingFilter to your project.

1: Add MDCWebReqInsertingFilter to your project. See https://logback.qos.ch/manual/mdc.html#mis if you use a web.xml. If not just do the below.

import ch.qos.logback.classic.helpers.MDCInsertingServletFilter;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Order(Ordered.HIGHEST_PRECEDENCE)
@Component
public class MyMDCInsertingServletFilter extends MDCWebReqInsertingFilter {
    // you could override the doFilter method to add more to the mdc here if you wanted
}

2: Extend MDCWebReqSeqLogEntry to add your fields. Note, I'm using lombok to create my getter/setters. You could do the same or create your own getter setters.

@Getter
@Setter
public class MyCustomSeqLogEntry extends MDCWebReqSeqLogEntry { 

    // add your own custom fields here if you would like
    
    /**
     * Constructor
     * @param eventObject The logback event
     * @param dateFormat Date format for timestamp
     */
    public MyCustomSeqLogEntry(ILoggingEvent eventObject, Format dateFormat) {
        super(eventObject, dateFormat);
	// set any custom fields here you may have place in the mdc via the overridden doFilter
    }
}

3: Extend MDCWebReqSeqLogLayout to use your new MyCustomSeqLogEntry class

public class MyCustomSeqLogEventLayout extends MDCWebReqSeqLogLayout {

    @Override
    public String doLayout(ILoggingEvent event) {
        return this.getLogEntryJsonString(new MyCustomSeqLogEntry(event, this.dateFormat));
    }
}

4: Add SEQ_LAYOUT property to your base logback settings xml file to use your new extended layout class. Make sure the namespace to your layout is correct.

    <property scope="context" name="SEQ_LAYOUT" value="com.your.namespace.MyCustomSeqLogEventLayout"/>
    <property name="PROJECT_NAME" value="my-service"/>
    <include resource="seq-logback-settings.xml" />

Tips

Remember to use debug="true" in main logback configuration file when trying to set up.