Implementing System Logs in SUSI.AI Admin Panel

The admin panel of SUSI.AI provides a lot of features required by system maintainers and admins to administer and maintain various activities of SUSI. Therefore system logs have been implemented on the admin panel so that admins can check whether SUSI server is working fine or throwing some errors. In this blog we will discuss about how logs are implemented on server and accounts.

 

LogServlet.java

The LogServlet.java file is the api used to fetch logs from the server. The API endpoint is

/log.txt

 

This API call has a parameter count which is optional and is used to fetch logs with custom count. If you don’t pass the count parameter then the default value of count is set to 1000. After settings the value of count variable, it then fetch the list of logs from the log appender using the DAO.logAppender using the getLines() method. Then the number of lines of the logs are compared with the count value and minimum of both the values is then taken as the final value of count which is used to fetch last ‘count’ lines of logs from the server. Then we create the final list of logs by appending them line by line while looping from 0 to count value.

Query post = RemoteAccess.evaluate(request);

int count = post.get("count", 1000);

final StringBuilder buffer = new StringBuilder(1000);

List < String > lines = DAO.logAppender.getLines();

count = Math.min(count, lines.size());

for (int i = Math.max(0, lines.size() - count); i < lines.size(); i++) buffer.append(lines.get(i));

 

After the iteration is completed the ‘buffer’ list is then type casted to string and passed as the final response to the client with type “text/plain”.

FileHandler.setCaching(response, 10);

post.setResponse(response, "text/plain");

AbstractAPIHandler.setCORS(response);

response.getOutputStream().write(buffer.toString().getBytes(StandardCharsets.UTF_8));

post.finalize();

 

SystemLogs.react

The client side implementation of system logs is done in the SystemLogs.react in the admin panel in the accounts.susi.ai repo along with other admin components. The load SystemLogs function is used to send the API request along with count value to the server. The response fetched from the server is then set as the logs variable of the state of the react component.

loadSystemLogs = count => {

  let url;

  url = `${urls.API_URL}/log.txt?count=${count}`;

  $.ajax({

    url: url,

    dataType: 'text',

    crossDomain: true,

    success: function(response) {

      let error = false;

      if (response.indexOf('WARN root') !== -1) {

        error = true;

      }

      this.setState({

        error: error,

        logs: response,

        loading: false,

      });

    }.bind(this),

    error: function(errorThrown) {

      console.log(errorThrown);

    },

  });

};

 

When the component loads, the above function is called with the default count 1000 during the mounting of the component.

 componentDidMount() {

   this.loadSystemLogs(1000);

 }

 

A dropdown is used to change the count value and its value is always set to the current value of currentCount variable of the state and calls the handleCountChange function as discussed above

<DropDownMenu onChange={this.handleCountChange} value={this.state.currentCount} />

 

The handleCountChange function is called whenever the value of count is changed in the dropdown menu. The new value of count is updated on the state and loadSystemLogs is called with the new count value to update the log variable of the state which then updates the value displayed in the log div

handleCountChange = (event, index, value) => {

  this.setState({

    currentCount: value,

    loading: true,

  });

  this.loadSystemLogs(value);

};

 

The logs from the server are of two types:

  • INFO root
  • WARN root

INFO root is used to define the log which is free from error and was executed successfully on the server. The WARN root is used to define error occurred during execution of some request or command along with the file or package responsible.

Therefore whenever the loadSystemLogs is called, it fetches the logs from the server and search for the term WARN root and if it finds it in the logs then the value of error variable of the state is set true, indicating the there is(are) some errors in the given logs.

let error = false;

if (response.indexOf('WARN root') !== -1) {

  error = true;

}

this.setState({

  error: error,

  logs: response,

  loading: false,

});

 

The alert box which is used to display the logs also has a type attribute whose value is set to error or success depending to the status on this.state.error and displays either a success div or a error div accordingly.

type = {
  this.state.error === true ? 'error' : 'success'
}

 

Resources