> ## 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 Go

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 Collector", version: "0.7.0" }
]}
/>

This documentation outlines how to configure logging with the AppSignal for Go 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 Go integration. An "application" log source will be created automatically.

The Go integration uses OpenTelemetry's logging capabilities to send logs to AppSignal.

### Stand-alone usage

To use logging with OpenTelemetry in Go, you need to set up the logger using OpenTelemetry's logger provider.

<CodeGroup>
  ```go Go theme={null}
  package main

  import (
  	"context"
  	"go.opentelemetry.io/otel"
  	"go.opentelemetry.io/otel/log"
  )

  func main() {
  	// Get the logger from the global logger provider
  	loggerProvider := otel.GetLoggerProvider()
  	logger := loggerProvider.Logger("my-app")

  	// Log a message
  	logger.Emit(context.Background(), log.Record{
  		Severity: log.SeverityInfo,
  		Body:     log.StringValue("Log message line"),
  	})
  }
  ```
</CodeGroup>

### Usage with `slog`

<Compatibility versions={[{ name: "Go", version: "1.21" }]} />

You can configure the standard `slog` package to send structured logs to AppSignal using the OpenTelemetry handler.

<CodeGroup>
  ```go Go theme={null}
  package main

  import (
  	"context"
  	"log/slog"
  	"go.opentelemetry.io/contrib/bridges/otelslog"
  )

  func main() {
  	// Create an OpenTelemetry `slog` handler
  	otelHandler := otelslog.NewHandler("my-app")

  	// Create a `slog` logger with the OpenTelemetry handler
  	logger := slog.New(otelHandler)

  	// Use the logger
  	logger.Info("Log message line")
  	logger.With("user_id", 123).Info("User logged in")
  	logger.Error("An error occurred", "error", "database connection failed")
  }
  ```
</CodeGroup>

## Usage

### Sending Logs

Using the OpenTelemetry logger directly, you can define the severity level of your logs:

<CodeGroup>
  ```go Go theme={null}
  package main

  import (
  	"context"
  	"go.opentelemetry.io/otel"
  	"go.opentelemetry.io/otel/log"
  )

  func main() {
  	loggerProvider := otel.GetLoggerProvider()
  	logger := loggerProvider.Logger("my-app")

  	// Different severity levels
  	logger.Emit(context.Background(), log.Record{
  		Severity: log.SeverityWarn,
  		Body:     log.StringValue("Something went wrong"),
  	})

  	logger.Emit(context.Background(), log.Record{
  		Severity: log.SeverityInfo,
  		Body:     log.StringValue("Action completed"),
  	})

  	logger.Emit(context.Background(), log.Record{
  		Severity: log.SeverityError,
  		Body:     log.StringValue("Database connection failed"),
  	})
  }
  ```
</CodeGroup>

You can define custom attributes to send log information that can be used when filtering and querying logs:

<CodeGroup>
  ```go Go theme={null}
  package main

  import (
  	"context"
  	"go.opentelemetry.io/otel"
  	"go.opentelemetry.io/otel/log"
  )

  func processInvoice(customerID string) {
  	loggerProvider := otel.GetLoggerProvider()
  	logger := loggerProvider.Logger("invoice_helper")

  	logger.Emit(context.Background(), log.Record{
  		Severity: log.SeverityInfo,
  		Body:     log.StringValue("Generating invoice for customer"),
  		Attributes: []log.KeyValue{
  			log.String("customer_id", customerID),
  		},
  	})

  	invoice := generateInvoice(customerID)

  	logger.Emit(context.Background(), log.Record{
  		Severity: log.SeverityInfo,
  		Body:     log.StringValue("Generated invoice for customer"),
  		Attributes: []log.KeyValue{
  			log.String("customer_id", customerID),
  			log.String("invoice_id", invoice.ID),
  		},
  	})
  }
  ```
</CodeGroup>

You can query and filter on message contents and attribute values from within the [Log Management](/logging/log-management) tool.

Once configured, the desired attributes will be sent to AppSignal as log tags, and be queryable in the AppSignal logging interface.

## Filtering Logs

You can use [the `ignore_logs` configuration option](/go/configuration#option-ignore_logs) to ignore log lines. See [our Ignore Logs guide](/guides/filter-data/ignore-logs) to learn more.

## Need Help?

After configuring your Go 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!
