# Streaming io.Connect Desktop Logs to a Remote Server (Splunk) with a Custom log4js UDP Appender

**URL:** <https://community.interop.io/t/streaming-io-connect-desktop-logs-to-a-remote-server-splunk-with-a-custom-log4js-udp-appender/672>\
**Category:** io.Connect Desktop\
**Tags:** logs, iocd-9\
**Created:** [August 27, 2026, 4:30am UTC](https://community.interop.io/t/streaming-io-connect-desktop-logs-to-a-remote-server-splunk-with-a-custom-log4js-udp-appender/672 "2026-08-27T04:30:15Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![toni.petrov](https://yyz2.discourse-cdn.com/flex028/user_avatar/community.interop.io/toni.petrov/32/17_2.png) [@toni.petrov](https://community.interop.io/u/toni.petrov)\
**Post date:** [August 27, 2026, 4:30am UTC](https://community.interop.io/t/streaming-io-connect-desktop-logs-to-a-remote-server-splunk-with-a-custom-log4js-udp-appender/672/1 "2026-08-27T04:30:15Z")

</div>

> The example below comes from a pre-10.0 setup and uses the `logger.json` file - see the section for 10.0 and later at the end of this article.

* * *

The io.Connect Desktop logging mechanism is based on [log4js-node](https://log4js-node.github.io/log4js-node/), and its appenders and categories are defined in an external JSON configuration file. This means you can add your own log appender to forward io.Connect logs to a remote collector such as Splunk, without a change to io.Connect Desktop itself.

### Q: Is there a built-in Splunk integration?

No. There is no Splunk-specific appender shipped with io.Connect Desktop. You forward logs to Splunk by adding a custom log4js appender to the io.Connect Desktop logging configuration. More about logs here: [Understanding logs in io.Connect](https://community.interop.io/t/understanding-logs-in-io-connect/36)

### Q: How do I add a custom UDP appender that forwards logs to Splunk?

The setup below wraps the `log4js-udp-appender` package so that you can add your own logic before the event is sent.

1. `npm install log4js-udp-appender` in the folder where you are hosting it e.g.: `\Desktop\assets\log4js-udp-appender`.

2. Set an `index.js` file in the same folder with the following code:

```auto
const createUdpAppender = require("log4js-udp-appender");

function customUdpAppender(config, layouts) {
  const udpAppender = createUdpAppender.configure(config, layouts);

  const appender = (loggingEvent) => {
    // Add your custom logic here
    udpAppender(loggingEvent);
  };

  appender.shutdown = (done) => {
    udpAppender.shutdown(done);
  };

  return appender;
}

function configure(config, layouts) {
  // Append the custom appender to the log4js configuration
  config.layout.tokens.user = process.env.USER || process.env.USERNAME || 'unknown';
  return customUdpAppender(config, layouts);
}

exports.configure = configure;

```

1. In the `logger.json` located in `Desktop\config`, configure your custom appender as needed:

```json
{
    "appenders": {
        "splunk": {
            "type": "%GDDIR%/assets/log4js-udp-appender",
            "host": "127.0.0.1",
            "port": 12345,
            "level": "info",
            "layout": {
                "type": "pattern",
                "tokens": {
                  "user": "%USERNAME%",
                  "appName": "MyApp",
                  "env": "%GLUE-ENV%"
                },
                "pattern":"%d{ISO8601_WITH_TZ_OFFSET} [app=%x{appName}] [env=%x{env}] [user=%x{user}] [host=%h] %p:[%f{1}-%M] %m %n"
            },
            "endMsg": "\t"
        },
        "out": {
            "type": "stdout"
        }
    },
  "categories": {
        "default": {
            "appenders": [
                "splunk"
            ],
            "level": "info"
        }
    }

```

> **Note on the environment variables in the example.** `%GDDIR%` and `%GLUE-ENV%` are legacy environment variables. They are still supported, but if running io.Connect Desktop 10.0 please migrate to `%IO_CD_ROOT_DIR%` and `%IO_CD_ENV%`. See [Configuration — Overview](https://docs.interop.io/desktop/developers/configuration/overview/index.html).

### Q: Which logs get forwarded?

The logging configuration has two parts: **appenders** (where log entries go) and **categories** (the different logs). Each category can have one or more appenders. You can either add your custom appender to an existing category’s appender list, or replace the appenders of a category entirely.

### Q: Can I forward the logs of one specific app only?

Yes. Since io.Connect Desktop 9.5, you can define a separate log appender per app. Define the appender, then create a **category named after your app** and assign the appender to it.

```json
{
    "appenders": {
        "my-app-appender": {
            "type": "file",
            "filename": "%GLUE-USER-DATA%/logs/my-app.log",
            "maxLogSize": 10485760,
            "backups": 5,
            "minLevel": "info",
            "keepFileExt": true,
            "compress": true
        }
    }
}

```

```json
{
    "categories": {
        "my-app": {
            "appenders": [
                "my-app-appender"
            ],
            "level": "trace"
        }
    }
}

```

### Q: How do I control the log level of what is forwarded?

Set the `level` property on the category to control its logging threshold. The UDP example above also sets `"level": "info"` on the appender.

### Q: Where is the format of what is sent coming from?

The format is controlled by the log4js layout `pattern` and `tokens` on the appender. This is standard log4js, not io.Connect-specific: see the log4js [Layouts](https://log4js-node.github.io/log4js-node/layouts.html) and [Writing Appenders](https://log4js-node.github.io/log4js-node/writing-appenders.html) documentation.

## io.Connect Desktop 10.0 and later

The example above uses `logger.json`, which is the pre-10.0 location of the logging configuration.

- **`logger.json` is deprecated as of io.Connect Desktop 10.0.** Custom log appenders and categories are now defined under the `"configuration"` property of the `"logging"` top-level key in `system.json`:

```json
{
    "logging": {
        "configuration": {
            "appenders": {},
            "categories": {}
        }
    }
}

```

See the [io.Connect Desktop 10.0 changelog](https://docs.interop.io/desktop/getting-started/changelog/10-0/index.html).

## Alternative on 10.1 and later: io.Insights log publishing

Since io.Connect Desktop 10.1, the Logs module of io.Insights bridges the existing io.Connect logging mechanisms with the OpenTelemetry log exporter, so platform and client app logs can be published as standard OpenTelemetry log records to an OpenTelemetry-compatible backend. See [io.Insights — Logs](https://docs.interop.io/insights/signals/logs/index.html).

## See also

- log4js — [Writing Appenders](https://log4js-node.github.io/log4js-node/writing-appenders.html)
- log4js — [Layouts](https://log4js-node.github.io/log4js-node/layouts.html)
- [io.Connect Desktop Documentation — Logging Overview](https://docs.interop.io/desktop/capabilities/logging/overview/index.html)
- [Understanding logs in io.Connect](https://community.interop.io/t/understanding-logs-in-io-connect/36)
- [Forwarding Logs from a Specific Application to Logstash in io.Connect Desktop](https://community.interop.io/t/faq-forwarding-logs-from-a-specific-application-to-logstash-in-io-connect-desktop/565)
