npm package: @soundworks/plugin-logger
Description: soundworks plugin for recording arbitrary data into files
Latest version: 5.0.0

# soundworks | plugin logger

[![npm version](https://badge.fury.io/js/@soundworks%2Fplugin-logger.svg)](https://badge.fury.io/js/@soundworks%2Fplugin-logger)

[`soundworks`](https://github.com/collective-soundworks/soundworks) plugin for recording arbitrary data from any node of the network into plain old files.

## Table of Contents

<!-- toc -->

- [Installation](#installation)
- [Usage](#usage)
- [Notes & Recipes](#notes--recipes)
- [API](#api)
- [ClientPluginLogger](#clientpluginlogger)
- [ClientWriter](#clientwriter)
- [ServerPluginLogger](#serverpluginlogger)
- [ServerWriter](#serverwriter)
- [Credits](#credits)
- [License](#license)

<!-- tocstop -->

## Installation

```sh
npm install @soundworks/plugin-logger --save
```

## Usage

### Server

```js
// index.js
import { Server } from '@soundworks/core/server.js';
import ServerPluginLogger from '@soundworks/plugin-logger/server.js';

const server = new Server(config);
server.pluginManager.register('logger', ServerPluginLogger, {
  // define directory in which the files will be written,
  // defaults to `null`, i.e. kind of "idle" plugin state
  dirname: 'logs',
});

await server.start();
// create a logger
const logger = await server.pluginManager.get('logger');
const writer = await logger.createWriter('my-server-log');
writer.write('hello server');
```

### Client

```js
// index.js
import { Client } from '@soundworks/core/client.js';
import ClientPluginLogger from '@soundworks/plugin-logger/client.js';

const client = new Client(config);
client.pluginManager.register('logger', ClientPluginLogger);

await client.start();
// create a logger
const logger = await client.pluginManager.get('logger');
const writer = await logger.createWriter('my-client-log');
writer.write('hello client');
```

## Notes & Recipes

_In the following examples, we assume the server-side logger as been configured to use the `logs` directory._

### Default extension

If a writer is created with no extension in its name, the `.txt` extension is added by default, otherwise the given extension is kept intact:

```js
const writer = await logger.createWriter('first-log.txt');
console.log(writer.pathname);
> 'logs/2023.07.3_16.39.43_0001_first-log.txt';

const writer = await logger.createWriter('second-log.md');
console.log(writer.pathname);
> 'logs/2023.07.3_16.39.43_0002_second-log.txt';
```

### Prefix in log files

By default all log files (client-side and server-side) are prefixed following a format: `yyyy.mm.dd_hh.mm.ss_id_${basename}`. This behavior can be turned of
by setting the `usePrefix` option to false when creating a writer.

With `usePrefix = true` (default):

```js
const writer = await logger.createWriter('my-log.txt');
console.log(writer.pathname);
> 'logs/2023.07.3_16.39.43_0001_my-log.txt';
```

With `usePrefix = false`:

```js
const writer = await logger.createWriter('my-log.txt', { usePrefix: false });
console.log(writer.pathname);
> 'logs/my-log.txt';
```

While useful in some situations, this option can lead to errors if two writers are created with the same name.

### Creating log files in sub-directories

If a path is given in the name, e.g. `my-dir/my-log`, sub-directories will be automatically created:

```js
const writer = await logger.createWriter(`my-dir/my-log`);
console.log(writer.pathname);
> 'logs/my-dir/my-log.txt';
```

### Share a writer between several clients

In a similar way as the shared state (while most simple), clients can attach to a writer created by the server. This can be used for example to create global logs information where all clients contribute. Create a writer server as usual:

```js
// server-side
const sharedWrite = await logger.createWriter('shared-writer');
```

Attach to the writer on the client-size, note the `attachWriter` method:

```js
// client-side
const sharedWriter = await logger.attachWriter('shared-writer');
```

All writers created by the server can be attached by clients.

### Client-side buffering

In many cases you may want to buffer the data client-side and batch the sends to the server to avoid network congestion. This can be done on writers created or attach by the client by defining the `bufferSize` option.

```js
// client-side
const myWriter = await logger.createWriter('buffered-writer', { bufferSize: 10 });
// data is buffered on the client side
myWriter.write('1');
myWriter.write('2');
// ...
myWriter.write('10');
// data is sent to the server
```

## API

<!-- api -->
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->

### Table of Contents

*   [ClientPluginLogger][1]
    *   [Examples][2]
    *   [createWriter][3]
    *   [attachWriter][4]
*   [ClientWriter][5]
    *   [Parameters][6]
    *   [name][7]
    *   [pathname][8]
    *   [write][9]
    *   [flush][10]
    *   [close][11]
    *   [onPacketSend][12]
    *   [onClose][13]
*   [ServerPluginLogger][14]
    *   [Examples][15]
    *   [switch][16]
    *   [createWriter][17]
*   [ServerWriter][18]
    *   [Parameters][19]
    *   [name][20]
    *   [pathname][21]
    *   [write][22]
    *   [close][23]
    *   [onClose][24]

## ClientPluginLogger

**Extends ClientPlugin**

Client-side representation of the soundworks sync plugin.

The constructor should never be called manually. The plugin will be
instantiated by soundworks when registered in the `pluginManager`

### Examples

```javascript
client.pluginManager.register('logger', ClientPluginLogger);
```

### createWriter

Create a writer.

#### Parameters

*   `name` **[String][25]** Name of the writer. Used to generate the log file
    pathname.
*   `options` **[Object][26]** Options for the writer. (optional, default `{}`)

    *   `options.bufferSize` **[Number][27]** Number of writes buffered before
        sending the logs to the server. (optional, default `1`)
    *   `options.usePrefix` **[Boolean][28]** Whether the writer file should
        be prefixed with a `YYYY.MM.DD_hh.mm.ss_uid_` string. (optional, default `true`)
    *   `options.allowReuse` **[Boolean][28]** If `usePrefix` is false, allow
        to reuse an existing underlying file for the writer. New data will be
        appended to the file.
        Can be useful to log global information in the same file amongst different
        sessions. (optional, default `false`)

### attachWriter

Attach to a shared writer created by the server. Can be useful to create
files that gather information from multiple nodes.

#### Parameters

*   `name` **[String][25]** Name of the writer. Used to generate the log file
    pathname.
*   `options` **[Object][26]** Options for the writer. (optional, default `{}`)

    *   `options.bufferSize` **[Number][27]** Number of writes buffered before
        sending the logs to the server. (optional, default `1`)

## ClientWriter

Client-side stream writer.

Created and retrieved by the client-side `logger.createWriter(name, bufferSize)` and
`logger.attachWriter(name, bufferSize)` methods.

### Parameters

*   `plugin` &#x20;
*   `state` &#x20;
*   `bufferSize`   (optional, default `1`)

### name

Name of the Writer.

### pathname

Pathname of the Writer.

### write

Format and write data.

*   Successive write calls are added to a new line
*   Data can be of any type, it will be stringified before write.
*   TypedArrays are converted to Array before being stringified.

#### Parameters

*   `data` **Any** Data to be written

### flush

Flush the buffer, only applies if `bufferSize` option is set.

### close

Close the writer.

Returns **[Promise][29]** Promise that resolves when the stream is closed

### onPacketSend

Register a function to be executed when a packet is sent on the network.,
i.e. when the buffer is full or flushed on close.

#### Parameters

*   `callback` **[Function][30]** Function to execute on close.

Returns **[Function][30]** that unregister the listener when executed.

### onClose

Register a function to be executed when the Writer is closed. The function
will be executed after the buffer has been flushed and underlying state has
been deleted, and before the `close` Promise resolves.

#### Parameters

*   `callback` **[Function][30]** Function to execute on close.

Returns **[Function][30]** that unregister the listener when executed.

## ServerPluginLogger

**Extends ServerPlugin**

Server-side representation of the soundworks logger plugin.

The constructor should never be called manually. The plugin will be
instantiated by soundworks when registered in the `pluginManager`

Available options:

*   `[dirname=null]` {String} - The directory in which the log files should
    be created. If `null` the plugin is in some "idle" state, and any call
    to `createWriter` (or client-side `attachWriter`) will throw an error.
    The directory can be changed at runtime using the `switch` method.

### Examples

```javascript
server.pluginManager.register('logger', ServerPluginLogger, {
  dirname: 'my-logs',
});
```

### switch

Change the directory in which the log files are created. Closes all existing writers.

#### Parameters

*   `dirname` **([String][25] | [Object][26])** Path to the new directory. As a convenience
    to match the plugin filesystem API, an object containing the 'dirname' key
    can also be passed.

### createWriter

Create a writer.

#### Parameters

*   `name` **[String][25]** Name of the writer. Used to generate the log file
    pathname.
*   `options` **[Object][26]** Options for the writer. (optional, default `{}`)

    *   `options.usePrefix` **[Boolean][28]** Whether the writer file should
        be prefixed with a `YYYY.MM.DD_hh.mm.ss_uid_` string. (optional, default `true`)
    *   `options.allowReuse` **[Boolean][28]** If `usePrefix` is false, allow
        to reuse an existing underlying file for the writer. New data will be
        appended to the file.
        Can be useful to log global information in the same file amongst different
        sessions. (optional, default `false`)

## ServerWriter

Server-side stream writer.

Created and retrieved by the server-side `logger.createWriter(name)` method.

### Parameters

*   `state` &#x20;
*   `format`   (optional, default `null`)

### name

Name of the Writer.

### pathname

Pathname of the Writer.

### write

Format and write data.

*   Successive write calls are added to a new line
*   Data can be of any type, it will be stringified before write.
*   TypedArrays are converted to Array before being stringified.

#### Parameters

*   `data` **Any** Data to be written

### close

Close the writer and the underlying stream.

Returns **[Promise][29]** Promise that resolves when the stream is closed

### onClose

Register a function to be executed when the Writer is closed. The function
will be executed when the underlying stream is closed and before the `close()`
Promise is resolved.

#### Parameters

*   `callback` **[Function][30]** Function to execute on close.

Returns **[Function][30]** that unregister the listener when executed.

[1]: #clientpluginlogger

[2]: #examples

[3]: #createwriter

[4]: #attachwriter

[5]: #clientwriter

[6]: #parameters-2

[7]: #name

[8]: #pathname

[9]: #write

[10]: #flush

[11]: #close

[12]: #onpacketsend

[13]: #onclose

[14]: #serverpluginlogger

[15]: #examples-1

[16]: #switch

[17]: #createwriter-1

[18]: #serverwriter

[19]: #parameters-8

[20]: #name-1

[21]: #pathname-1

[22]: #write-1

[23]: #close-1

[24]: #onclose-1

[25]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String

[26]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object

[27]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number

[28]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean

[29]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise

[30]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function

<!-- apistop -->

## Credits

The code has been initiated in the framework of the WAVE and CoSiMa research projects, funded by the French National Research Agency (ANR).

## License

BSD-3-Clause