# Track users’ logs with morgan

Morgan is a logging middleware used to handle the logging of your admin backend. It is called this way in your `app.js` file:

{% code title="app.js" %}

```javascript
const morgan = require('morgan')
...
app.use(morgan('tiny'))
...
```

{% endcode %}

The logs are printed in this format:

![Screenshot 2020-07-21 at 18.17.25.png](https://storage.googleapis.com/slite-api-files-production/files/c1aff565-854f-45b5-9519-53196044ea29/Screenshot%202020-07-21%20at%2018.17.25.png)

You can choose to have more verbose logs, add new information, and customize the log format using [morgan](https://github.com/expressjs/morgan).

You can take a look at the package documentation [here](https://www.npmjs.com/package/morgan).

{% hint style="info" %}
This can be especially useful if you store your logs and use them to track user activities.
{% endhint %}

## Add new information

You could add in your logging data like:

* user IP (IP of the request),
* user name & team from the Forest Admin token

You can adjust the code in your `app.js` file using the snippet below.

The logs printed will include information about the user IP, the user connected with Forest and his team.

{% code title="app.js" %}

```javascript
const morgan = require('morgan')
...
morgan.token('ip', (req) => req.headers['x-forwarded-for'] || req.connection.remoteAddress);
morgan.token('user', (req) => {
  if (req.user) { return req.user.email; }
  return 'no user info';
});
morgan.token('team', (req) => {
  if (req.user) { return req.user.team; }
  return '-';
});

app.use(morgan(':ip :user :team [:date[clf]] :method :url :response-time'));
...

```

{% endcode %}

This will give you the following log output:

![Screenshot 2020-07-21 at 18.17.45.png](https://storage.googleapis.com/slite-api-files-production/files/fc2dcd48-f7ed-40a4-b4a5-cf1b206506c4/Screenshot%202020-07-21%20at%2018.17.45.png)

## Customize the format of the logs

You can also use a custom format like a JSON to output your logs.

{% code title="app.js" %}

```javascript
const morgan = require('morgan')
...

morgan.token('ip', (req) => req.headers['x-forwarded-for'] || req.connection.remoteAddress);
morgan.token('user', (req) => {
  if (req.user) { return req.user.email; }
  return 'no user info';
});
morgan.token('team', (req) => {
  if (req.user) { return req.user.team; }
  return '-';
});

function jsonFormat(tokens, req, res) {
  return JSON.stringify({
    ip: tokens.ip(req, res),
    user: tokens.user(req, res),
    team: tokens.team(req, res),
    time: tokens.date(req, res, 'iso'),
    method: tokens.method(req, res),
    url: tokens.url(req, res),
    'http-version': tokens['http-version'](req, res),
    'status-code': tokens.status(req, res),
    'content-length': tokens.res(req, res, 'content-length'),
    referrer: tokens.referrer(req, res),
    'user-agent': tokens['user-agent'](req, res),
  });
}

app.use(morgan(jsonFormat));
...
```

{% endcode %}

This will give you the following log output:

![Screenshot 2020-07-21 at 17.58.38.png](https://storage.googleapis.com/slite-api-files-production/files/45445589-7721-4c6c-b7e2-a985514b73a2/Screenshot%202020-07-21%20at%2017.58.38.png)

## Store logs via a stream

You can also choose to store your logs using a stream. The following example shows how you can store your logs into a CSV file.

{% code title="app.js" %}

```javascript
const morgan = require('morgan')
...

morgan.token('ip', (req) => req.headers['x-forwarded-for'] || req.connection.remoteAddress);
morgan.token('user', (req) => {
  if (req.user) { return req.user.email; }
  return 'no user info';
});
morgan.token('team', (req) => {
  if (req.user) { return req.user.team; }
  return '-';
});

let accessLogStream = fs.createWriteStream(path.join(__dirname, 'access.csv'), { flags: 'a' });

app.use(morgan(':ip,:user,:team,[:date[clf]],:method,:url,:response-time', { stream: accessLogStream }));
...
```

{% endcode %}
