Skip to content

feat(go): Modify docs to follow logger API changes #14260

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
177 changes: 76 additions & 101 deletions docs/platforms/go/common/logs/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,149 +11,124 @@ With Sentry Structured Logs, you can send text based log information from your a

## Requirements

Logs in Go are supported in Sentry Go SDK version `0.33.0` and above.
Logs in Go are supported in Sentry Go SDK version `0.33.0` and above. To use integrations with other logging libraries, check their specific documentation pages for detailed requirements.

## Setup
## Configure

### Initialize the Sentry SDK

To enable logging, you need to initialize the SDK with the `EnableLogs` option set to true.

```go
package main
<PlatformContent includePath="getting-started-include-logs-config" />

import (
"context"
"github.com/getsentry/sentry-go"
"time"
)
### Options

func main() {
if err := sentry.Init(sentry.ClientOptions{
#### BeforeSendLog

To filter logs, or update them before they are sent to Sentry, you can use the `BeforeSendLog` client option.

```go
sentry.Init(sentry.ClientOptions{
Dsn: "___PUBLIC_DSN___",
EnableLogs: true,
}); err != nil {
fmt.Printf("Sentry initialization failed: %v\n", err)
}
// Flush buffered events before the program terminates.
// Set the timeout to the maximum duration the program can afford to wait.
defer sentry.Flush(2 * time.Second)
}
BeforeSendLog: func(log *sentry.Log) *sentry.Log {
// filter out all trace logs
if log.Level == sentry.LogLevelTrace {
return nil
}

// filter all logs below warning
if log.Severity <= sentry.LogSeverityInfo {
return nil
}
return log
},
})
```

## Usage

Once the feature is enabled on the SDK and the SDK is initialized, you can send logs by using
the `sentry.Logger` API.
Once the feature is enabled on the SDK and the SDK is initialized, you can send logs by using the `sentry.Logger` API or our different integrations.

The `Sentry.Logger` API exposes methods that support six different log levels: `trace`,
`debug`, `info`, `warn`, `error` and `fatal`. The methods support both `fmt.Print` and `fmt.Printf` like syntax.
If you pass in format specifiers like `%v`, these will be sent to Sentry, and can be searched from within the Logs UI,
and even added to the Logs views as a dedicated column.
The `sentry.Logger` API exposes methods that support six different log levels:
- `trace`
- `debug`
- `info`
- `warn`
- `error`
- `fatal`

```go
ctx := context.Background()
logger := sentry.NewLogger(ctx)

// You can use the logger like [fmt.Print]
logger.Info(ctx, "Hello ", "world!")
// Or like [fmt.Printf]
logger.Infof(ctx, "Hello %v!", "world")
```

You can also pass additional attributes to the logger via the `SetAttributes` function. These attributes will also be searchable in the Logs UI.
The methods support both `fmt.Print` and `fmt.Printf` like syntax. If you pass in format specifiers like `%v`, these will be
sent to Sentry, and can be searched from within the Logs UI, and even added to the Logs views as a dedicated column.

```go
package main

import (
"context"
"github.com/getsentry/sentry-go"
"github.com/getsentry/sentry-go/attribute"
"time"
)

func main() {
err := sentry.Init(sentry.ClientOptions{
if err := sentry.Init(sentry.ClientOptions{
Dsn: "___PUBLIC_DSN___",
EnableLogs: true,
})
if err != nil {
panic(err)
}); err != nil {
log.Fatalf("Sentry initialization failed: %v", err)
}
// Flush buffered events before the program terminates.
// Set the timeout to the maximum duration the program can afford to wait.
defer sentry.Flush(2 * time.Second)

// The SentryLogger requires context, to link logs with the appropriate traces. You can either create a new logger
// by providing the context, or use WithCtx() to pass the context inline.
ctx := context.Background()
logger := sentry.NewLogger(ctx)

logger.SetAttributes(
attribute.Int("key.int", 42),
attribute.Bool("key.boolean", true),
attribute.Float64("key.float", 42.4),
attribute.String("key.string", "string"),
)
logger.Warnf(ctx, "I have params: %v and attributes", "example param")
// Or inline using WithCtx()
newCtx := context.Background()
// WithCtx() does not modify the original context attached on the logger.
logger.Info().WithCtx(newCtx).Emit("context passed")

// You can use the logger like [fmt.Print]
logger.Info().Emit("Hello ", "world!")
// Or like [fmt.Printf]
logger.Info().Emitf("Hello %v!", "world")
}
```

Currently the `attribute` API supports only these value types: `int`, `string`, `bool`, and `float`.

## Integrations

### `io.Writer` interface

The `sentry.Logger` implements the `io.Writer` interface, so you can easily inject the logger into your existing setup.
You can also pass additional permanent attributes to the logger via `SetAttributes`, or attach certain attributes to the `LogEntry` itself.
These attributes do not persist after Emitting the `LogEntry`. All attributes will be searchable in the Logs UI.

```go
sentryLogger := sentry.NewLogger(ctx)
logger := log.New(sentryLogger, "", log.LstdFlags)
logger.Println("Implementing log.Logger")
logger.SetAttributes(
attribute.Int("key.int", 42),
attribute.Bool("key.boolean", true),
attribute.Float64("key.float", 42.4),
attribute.String("key.string", "string"),
)
logger.Warn().Emitf("I have params: %v and attributes", "example param")

slogger := slog.New(slog.NewJSONHandler(sentryLogger, nil))
slogger.Info("Implementing slog.Logger")
// This entry would contain all attributes attached to the logger.
// However, it's also possible to overwrite them.
logger.Info().String("key.string", "newstring").Emit("overwriting key.string")
```

<Alert>
In order to properly attach the correct trace with each Log entry, a
`context.Context` is required. The `Write` function of the `io.Writer`
interface doesn't provide `context`, so wrapping the custom logger will not
get the trace and current span attached. We recommend using the
`sentry.Logger` to ensure your logs are connected to spans and errors in the
Sentry UI.
</Alert>
Currently, the `attribute` API supports only these value types: `int`, `string`, `bool`, and `float`.

## Integrations

### Integrations
### Supported libraries
- [Slog](/platforms/go/guides/slog)
- [Logrus](/platforms/go/guides/logrus)

### Upcoming Integrations

We're actively working on adding more integration support for Logs. Currently, we are looking at adding support for [`zerolog`](https://pkg.go.dev/github.com/rs/zerolog). You can follow this [GitHub issue](https://github.com/getsentry/sentry-go/issues/1015) to track progress.

## Options

### BeforeSendLog
### `io.Writer` interface

To filter logs, or update them before they are sent to Sentry, you can use the `BeforeSendLog` client option.
The `sentry.Logger` implements the `io.Writer` interface, so you can easily inject the logger into your existing setup. However, to correctly
link your traces you would need to create a new logger everytime you want to pass a new context. Due to this limitation we recommend using the
`sentry.Logger` or any of the other supported integrations.

```go
if err := sentry.Init(sentry.ClientOptions{
Dsn: "___PUBLIC_DSN___",
EnableLogs: true,
BeforeSendLog: func(log *Log) *Log {
// filter out all trace logs
if log.Level == sentry.LogLevelTrace {
return nil
}

// filter all logs below warning
if log.Severity <= LogSeverityInfo {
return nil
}
},
}); err != nil {
fmt.Printf("Sentry initialization failed: %v\n", err)
}
sentryLogger := sentry.NewLogger(ctx)
logger := log.New(sentryLogger, "", log.LstdFlags)
logger.Println("Implementing log.Logger")
```

### Debug

If the `Debug` init option is set to true, calls to the `sentry.Logger` will also print to the console with the appropriate log level.

<Include name="logs/go-ctx-usage-alert.mdx"/>
4 changes: 4 additions & 0 deletions includes/logs/go-ctx-usage-alert.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
## Correlating Logs With Traces

In order to properly attach the correct trace with each log entry, a `context.Context` is required.
If you're using logs combined with tracing, you should pass the correct context to properly attach each trace with the appropriate logs.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
If you're using logs combined with tracing, you should pass the correct context to properly attach each trace with the appropriate logs.
When using logs with tracing, make sure to pass the correct context so each log is properly associated with its trace.

31 changes: 31 additions & 0 deletions platform-includes/getting-started-include-logs-config/go.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<OnboardingOptionButtons
options={[
'error-monitoring',
'performance',
]}
/>

```go
err := sentry.Init(sentry.ClientOptions{
Dsn: "___PUBLIC_DSN___",
// Enable printing of SDK debug messages.
// Useful when getting started or trying to figure something out.
Debug: true,
// Adds request headers and IP for users,
// visit: https://docs.sentry.io/platforms/go/data-management/data-collected/ for more info
SendDefaultPII: true,
EnableLogs: true,
// ___PRODUCT_OPTION_START___ performance
EnableTracing: true,
// Set TracesSampleRate to 1.0 to capture 100%
// of transactions for tracing.
TracesSampleRate: 1.0,
// ___PRODUCT_OPTION_END___ performance
})
if err != nil {
log.Fatalf("sentry.Init: %s", err)
}
// Flush buffered events before the program terminates.
// Set the timeout to the maximum duration the program can afford to wait.
defer sentry.Flush(2 * time.Second)
```