> ## Documentation Index
> Fetch the complete documentation index at: https://docs.appsignal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Logging from Node.js

export const VersionRequirements = ({versions = []}) => {
  if (!Array.isArray(versions) || versions.length === 0) {
    return null;
  }
  const boundaries = {
    upper: " or lower",
    exact: "",
    lower: " or higher"
  };
  const containerStyle = {
    marginTop: "0.5rem",
    marginBottom: "1.5rem"
  };
  const lineStyle = {
    display: "block",
    margin: "0 0 0.35rem 0",
    fontSize: "0.875rem",
    lineHeight: "1.4"
  };
  const pillBaseStyle = {
    display: "inline-block",
    padding: "0.1em 0.4em",
    borderRadius: "0.25rem",
    border: "1px solid",
    fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
    fontSize: "0.85em",
    fontWeight: 500
  };
  const pillColors = {
    "AppSignal for Elixir": {
      background: "#f3e8ff",
      borderColor: "#e9d5ff",
      color: "#9333ea"
    },
    "AppSignal for Front-end": {
      background: "#fef9c3",
      borderColor: "#fde68a",
      color: "#ca8a04"
    },
    "AppSignal for Go": {
      background: "#ccfbf1",
      borderColor: "#99f6e4",
      color: "#0d9488"
    },
    "AppSignal for JavaScript": {
      background: "#fef9c3",
      borderColor: "#fde68a",
      color: "#ca8a04"
    },
    "AppSignal for Node.js": {
      background: "#dcfce7",
      borderColor: "#bbf7d0",
      color: "#16a34a"
    },
    "AppSignal for Python": {
      background: "#dbeafe",
      borderColor: "#bfdbfe",
      color: "#2563eb"
    },
    "AppSignal for Ruby": {
      background: "#fee2e2",
      borderColor: "#fecaca",
      color: "#dc2626"
    },
    "AppSignal for Rust": {
      background: "#ffedd5",
      borderColor: "#fed7aa",
      color: "#ea580c"
    }
  };
  const defaultPillColor = {
    background: "#f4f4f5",
    borderColor: "#e4e4e7",
    color: "#52525b"
  };
  const getPillStyle = name => ({
    ...pillBaseStyle,
    ...pillColors[name] || defaultPillColor
  });
  const getBoundText = bound => {
    return boundaries[bound] || boundaries.lower;
  };
  return <div style={containerStyle}>
      {versions.map((v, i) => <p key={`${v.name}-${v.version}-${v.bound || "lower"}-${i}`} style={lineStyle}>
          This feature requires{" "}
          <code style={getPillStyle(v.name)}>{v.name}</code> version {v.version}
          {getBoundText(v.bound)}.
        </p>)}
    </div>;
};

export const Compatibility = ({versions = [], label = "Available in"}) => {
  if (!Array.isArray(versions) || versions.length === 0) {
    return null;
  }
  const defaultPillStyle = {
    borderColor: "#d4d4d8",
    background: "#f4f4f5",
    color: "#3f3f46"
  };
  const pillStyles = {
    "AppSignal for Elixir": {
      background: "#f3e8ff",
      borderColor: "#d8b4fe",
      color: "#6b21a8"
    },
    "AppSignal for Front-end": {
      background: "#fef9c3",
      borderColor: "#fde047",
      color: "#854d0e"
    },
    "AppSignal for Go": {
      background: "#ccfbf1",
      borderColor: "#5eead4",
      color: "#115e59"
    },
    "AppSignal for JavaScript": {
      background: "#fef9c3",
      borderColor: "#fde047",
      color: "#854d0e"
    },
    "AppSignal for Node.js": {
      background: "#dcfce7",
      borderColor: "#86efac",
      color: "#166534"
    },
    "AppSignal for Python": {
      background: "#dbeafe",
      borderColor: "#93c5fd",
      color: "#1e40af"
    },
    "AppSignal for Ruby": {
      background: "#fee2e2",
      borderColor: "#fca5a5",
      color: "#991b1b"
    },
    "AppSignal for Rust": {
      background: "#ffedd5",
      borderColor: "#fdba74",
      color: "#9a3412"
    }
  };
  const getPillStyle = name => ({
    ...defaultPillStyle,
    ...pillStyles[name] || ({})
  });
  return <div className="not-prose my-4 rounded-lg border border-zinc-200 bg-zinc-50 px-4 py-3 text-sm dark:border-white/10 dark:bg-white/5">
      <div className="flex flex-wrap items-center gap-x-2 gap-y-1">
        <span className="font-semibold text-zinc-700 dark:text-zinc-200">
          {label}:
        </span>
        {versions.map((v, i) => <span key={`${v.name}-${v.version}-${i}`} className="inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-xs font-medium" style={getPillStyle(v.name)}>
            <span>{v.name}</span>
            <span className="opacity-70">
              {v.version}
              {v.exact ? "" : "+"}
            </span>
          </span>)}
      </div>
    </div>;
};

<VersionRequirements
  versions={[
{ name: "AppSignal for Node.js", version: "3.0.1" }
]}
/>

This documentation outlines how to configure logging with the AppSignal for Node.js integration.

## Configure Logging

<Warning>
  🔐 Do not send <strong>Personal Identifiable Information (PII)</strong> to AppSignal. Filter PII (e.g., names, emails) from logs and use an ID, hash, or pseudonymized identifier instead. <br /> <br /> For **HIPAA-covered entities**, more information about signing a Business Associate Agreement (BAA) can be found in our [Business Add-Ons documentation](/support/business-add-ons).
</Warning>

You do not need to create a log source to send logs from the AppSignal for Node.js integration. An "application" log source will be created automatically.

### Stand-alone usage

To use the logger, you need to import AppSignal and set up the logger using the `.logger()` function.

The `.logger()` function accepts two arguments: `group` and optionally `severityThreshold`. If `severityThreshold` is not provided, it will default to `info`.

<CodeGroup>
  ```javascript Node.js theme={null}
  const { Appsignal } = require("@appsignal/nodejs");

  const logger = Appsignal.logger("app");

  // with a severity threshold:
  const logger = Appsignal.logger("app", "info");
  ```
</CodeGroup>

There are six severity levels available `trace`, `debug`, `info`, `log`, `warn`, and `error`, each of them with its own function with the same name. These functions accept two arguments `message` and `attributes`. Attributes is used for metadata and is optional.

Messages will only be logged if their severity level is above the severity threshold.

<CodeGroup>
  ```javascript Node.js theme={null}
  logger.info("Log message line");
  logger.debug("User logged in", { user_id: 123 });
  ```
</CodeGroup>

Note that if the message's severity is below the severity threshold set up when initializing the logger, it will not be sent to AppSignal.

You can query and filter on message contents and attribute values using our [query syntax](/logging/query-syntax).

#### Using multiple logging backends

It's currently not possible to send logs to multiple backends using Node.js' standard logger. For more complex setups, we recommend using a logging library like Winston or Pino.

### Usage with Winston

<Compatibility versions={[{ name: "AppSignal for Node.js", version: "3.0.3" }]} />

If you use Winston to log messages throughout your application, you can use our Winston transport to send those logs to AppSignal. After importing the transport from the AppSignal integration, add it to the list of transports in your Winston logger:

<CodeGroup>
  ```javascript Node.js theme={null}
  const winston = require("winston");
  const { WinstonTransport } = require("@appsignal/nodejs");

  const logger = winston.createLogger({
    transports: [new WinstonTransport({ group: "app" })],
  });
  ```
</CodeGroup>

#### Child Logger

You can use a child logger to add additional tags to log messages. You define tags when creating the child logger constant or pass tags as metadata when writing a log message. Say we want greater context in our logs of the actions of a particular user within a specific session. In the below example, a child logger for the `background` group is used to add `sessionID` with the additional `drinkID`, and `paymentID` tags are provided as metadata when creating a log message, and if a group is given to the child, it'll override the one set up in the transport.

<CodeGroup>
  ```javascript Node.js theme={null}
  const logger = winston.createLogger({...});

  const sessionLogger = logger.child({
    group: "background",
    sessionID: user.id,
  });

  sessionLogger.debug("User logged in");
  sessionLogger.info("User ordered coffee", { drinkID: 30, paymentID: 20082 });
  sessionLogger.debug("User logged out");
  ```
</CodeGroup>

#### Using multiple logging backends

To send logs to both AppSignal's logger and `STDOUT`, add another transport:

<CodeGroup>
  ```javascript JavaScript theme={null}
  const winston = require("winston");
  const { WinstonTransport } = require("@appsignal/nodejs");

  const logger = winston.createLogger({
    transports: [
      new WinstonTransport({ group: "app" }),
      new winston.transports.Console(),
    ],
  });
  ```
</CodeGroup>

### Usage with Pino

<Compatibility versions={[{ name: "AppSignal for Node.js", version: "3.5.4" }]} />

If Pino is your preferred logging library, you can use the AppSignal Pino transport to send logs to AppSignal.

The group argument will default to "app" if not provided.

<CodeGroup>
  ```javascript Node.js theme={null}
  import pino from "pino";

  const logger = pino({
    transport: {
      targets: [
        { target: "@appsignal/nodejs/pino", options: { group: "my-group" } }
      ],
    },
  });
  ```
</CodeGroup>

#### Using multiple logging backends

To send logs to both AppSignal's logger and `STDOUT`, add another target:

<CodeGroup>
  ```javascript Node.js theme={null}
  import pino from "pino";

  const logger = pino({
    transport: {
      targets: [
          { target: "@appsignal/nodejs/pino", options: { group: "my-group" } },
          { target: 'pino/file', options: {destination: 1} }
      ],
    },
  });
  ```
</CodeGroup>

## Formats

### Auto detected format

<Compatibility versions={[{ name: "AppSignal for Node.js", version: "3.7.2" }]} />

The AppSignal for Node.js package will automatically detect the log line's format as JSON, Logfmt or plaintext by default, and parse attributes from it.
You don't need to manually set the log format, unless it's not being detected properly.
Please also [notify us](mailto:support@appsignal.com?subject=Log%20format%20auto%20detection%20not%20working) if this isn't working automatically.

<CodeGroup>
  ```javascript Node.js theme={null}
  const { Appsignal } = require("@appsignal/nodejs");

  // Plaintext format
  const logger = Appsignal.logger("app", "info");
  logger.info("This is about the blog");

  // Logfmt format
  const logger = Appsignal.logger("app", "info");
  logger.info("category=blog This is about the blog");

  // JSON format
  const logger = Appsignal.logger("app", "info");
  logger.info('{"category": "blog", "message": "This is about the blog"}');
  ```
</CodeGroup>

### Logfmt

<Compatibility versions={[{ name: "AppSignal for Node.js", version: "3.0.11" }]} />

The AppSignal Logger can be explicitly configured to expect the line to be formatted as Logfmt and parse attributes from it.
Use this option when using an older AppSignal for Node.js package version, which does not support [automatic format detection](#auto-detected-format).

The log format can be specified when creating a logger.
When initializing the AppSignal logger pass the `"logfmt"` value as the third argument.

<CodeGroup>
  ```javascript Node.js theme={null}
  const { Appsignal } = require("@appsignal/nodejs");

  const logger = Appsignal.logger("app", "info", "logfmt");
  logger.info("category=blog this is about the blog");
  ```
</CodeGroup>

In the example above, a filterable category attribute with the value "blog" will be logged.

### JSON

<Compatibility versions={[{ name: "AppSignal for Node.js", version: "3.0.11" }]} />

The AppSignal Logger can be explicitly configured to expect the line to be formatted as JSON and parse attributes from it.
Use this option when using an older AppSignal for Node.js package version, which does not support [automatic format detection](#auto-detected-format).

The log format can be specified when creating a logger.
When initializing the AppSignal logger pass the `"json"` value as the third argument.

<CodeGroup>
  ```javascript Node.js theme={null}
  const { Appsignal } = require("@appsignal/nodejs");

  const logger = Appsignal.logger("app", "info", "json");
  logger.info('{"category": "blog", "message": "this is about the blog"}');
  ```
</CodeGroup>

In the example above, a filterable category attribute with the value "blog" will be logged.

## Filtering Logs

You can use [the `ignoreLogs` configuration option](/nodejs/3.x/configuration/options#option-ignorelogs) to ignore log lines based on their message. See [our Ignore Logs guide](/guides/filter-data/ignore-logs) to learn more.

## Need Help?

After configuring your Node.js application to send logs, logs should appear in AppSignal. If you are unsure about this step or AppSignal is not receiving any logs, you can always [reach out](mailto:support@appsignal.com) for assistance. We'll help get you back on track!
