Skip to content

Commit 487703c

Browse files
authored
Merge pull request #853 from newrelic/develop
Release 3.30.0
2 parents 1ef7dea + ab5de7a commit 487703c

File tree

58 files changed

+628
-53
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+628
-53
lines changed

CHANGELOG.md

+12
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
## 3.30.0
2+
### Added
3+
* Updated the depencency on nrsecurityagent to 1.0.0.
4+
* Added new integration, logcontext-v2/nrslog, which instruments logging via the new slog library.
5+
6+
### Fixed
7+
* Redacts license keys from error reporting.
8+
9+
### Support statement
10+
We use the latest version of the Go language. At minimum, you should be using no version of Go older than what is supported by the Go team themselves.
11+
See the [Go agent EOL Policy](/docs/apm/agents/go-agent/get-started/go-agent-eol-policy) for details about supported versions of the Go agent and third-party components.
12+
113
## 3.29.1
214
### Added
315
* Added Dockerized Unit Tests for Github Actions (internal build support)

v3/integrations/logcontext-v2/logWriter/go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module github.com/newrelic/go-agent/v3/integrations/logcontext-v2/logWriter
33
go 1.19
44

55
require (
6-
github.com/newrelic/go-agent/v3 v3.29.1
6+
github.com/newrelic/go-agent/v3 v3.30.0
77
github.com/newrelic/go-agent/v3/integrations/logcontext-v2/nrwriter v1.0.0
88
)
99

v3/integrations/logcontext-v2/nrlogrus/go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module github.com/newrelic/go-agent/v3/integrations/logcontext-v2/nrlogrus
33
go 1.19
44

55
require (
6-
github.com/newrelic/go-agent/v3 v3.29.1
6+
github.com/newrelic/go-agent/v3 v3.30.0
77
github.com/sirupsen/logrus v1.8.1
88
)
99

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package main
2+
3+
import (
4+
"log/slog"
5+
"os"
6+
"time"
7+
8+
"github.com/newrelic/go-agent/v3/integrations/logcontext-v2/nrslog"
9+
"github.com/newrelic/go-agent/v3/newrelic"
10+
)
11+
12+
func main() {
13+
app, err := newrelic.NewApplication(
14+
newrelic.ConfigFromEnvironment(),
15+
newrelic.ConfigAppLogEnabled(true),
16+
)
17+
if err != nil {
18+
panic(err)
19+
}
20+
21+
app.WaitForConnection(time.Second * 5)
22+
log := slog.New(nrslog.TextHandler(app, os.Stdout, &slog.HandlerOptions{}))
23+
24+
log.Info("I am a log message")
25+
26+
txn := app.StartTransaction("example transaction")
27+
txnLogger := nrslog.WithTransaction(txn, log)
28+
txnLogger.Info("I am a log inside a transaction")
29+
30+
// pretend to do some work
31+
time.Sleep(500 * time.Millisecond)
32+
txnLogger.Warn("Uh oh, something important happened!")
33+
txn.End()
34+
35+
log.Info("All Done!")
36+
37+
app.Shutdown(time.Second * 10)
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module github.com/newrelic/go-agent/v3/integrations/logcontext-v2/nrslog
2+
3+
go 1.19
4+
5+
require github.com/newrelic/go-agent/v3 v3.30.0
6+
7+
replace github.com/newrelic/go-agent/v3 => ../../..
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
package nrslog
2+
3+
import (
4+
"context"
5+
"io"
6+
"log/slog"
7+
8+
"github.com/newrelic/go-agent/v3/newrelic"
9+
)
10+
11+
// NRHandler is an Slog handler that includes logic to implement New Relic Logs in Context
12+
type NRHandler struct {
13+
handler slog.Handler
14+
w *LogWriter
15+
app *newrelic.Application
16+
txn *newrelic.Transaction
17+
}
18+
19+
// TextHandler creates a wrapped Slog TextHandler, enabling it to both automatically capture logs
20+
// and to enrich logs locally depending on your logs in context configuration in your New Relic
21+
// application.
22+
func TextHandler(app *newrelic.Application, w io.Writer, opts *slog.HandlerOptions) NRHandler {
23+
nrWriter := NewWriter(w, app)
24+
textHandler := slog.NewTextHandler(nrWriter, opts)
25+
wrappedHandler := WrapHandler(app, textHandler)
26+
wrappedHandler.addWriter(&nrWriter)
27+
return wrappedHandler
28+
}
29+
30+
// JSONHandler creates a wrapped Slog JSONHandler, enabling it to both automatically capture logs
31+
// and to enrich logs locally depending on your logs in context configuration in your New Relic
32+
// application.
33+
func JSONHandler(app *newrelic.Application, w io.Writer, opts *slog.HandlerOptions) NRHandler {
34+
nrWriter := NewWriter(w, app)
35+
jsonHandler := slog.NewJSONHandler(nrWriter, opts)
36+
wrappedHandler := WrapHandler(app, jsonHandler)
37+
wrappedHandler.addWriter(&nrWriter)
38+
return wrappedHandler
39+
}
40+
41+
// WithTransaction creates a new Slog Logger object to be used for logging within a given transaction.
42+
func WithTransaction(txn *newrelic.Transaction, logger *slog.Logger) *slog.Logger {
43+
if txn == nil || logger == nil {
44+
return logger
45+
}
46+
47+
h := logger.Handler()
48+
switch nrHandler := h.(type) {
49+
case NRHandler:
50+
txnHandler := nrHandler.WithTransaction(txn)
51+
return slog.New(txnHandler)
52+
default:
53+
return logger
54+
}
55+
}
56+
57+
// WithTransaction creates a new Slog Logger object to be used for logging within a given transaction it its found
58+
// in a context.
59+
func WithContext(ctx context.Context, logger *slog.Logger) *slog.Logger {
60+
if ctx == nil {
61+
return logger
62+
}
63+
64+
txn := newrelic.FromContext(ctx)
65+
return WithTransaction(txn, logger)
66+
}
67+
68+
// WrapHandler returns a new handler that is wrapped with New Relic tools to capture
69+
// log data based on your application's logs in context settings.
70+
func WrapHandler(app *newrelic.Application, handler slog.Handler) NRHandler {
71+
return NRHandler{
72+
handler: handler,
73+
app: app,
74+
}
75+
}
76+
77+
// addWriter is an internal helper function to append an io.Writer to the NRHandler object
78+
func (h *NRHandler) addWriter(w *LogWriter) {
79+
h.w = w
80+
}
81+
82+
// WithTransaction returns a new handler that is configured to capture log data
83+
// and attribute it to a specific transaction.
84+
func (h *NRHandler) WithTransaction(txn *newrelic.Transaction) NRHandler {
85+
handler := NRHandler{
86+
handler: h.handler,
87+
app: h.app,
88+
txn: txn,
89+
}
90+
91+
if h.w != nil {
92+
writer := h.w.WithTransaction(txn)
93+
handler.addWriter(&writer)
94+
}
95+
96+
return handler
97+
}
98+
99+
// Enabled reports whether the handler handles records at the given level.
100+
// The handler ignores records whose level is lower.
101+
// It is called early, before any arguments are processed,
102+
// to save effort if the log event should be discarded.
103+
// If called from a Logger method, the first argument is the context
104+
// passed to that method, or context.Background() if nil was passed
105+
// or the method does not take a context.
106+
// The context is passed so Enabled can use its values
107+
// to make a decision.
108+
func (h NRHandler) Enabled(ctx context.Context, lvl slog.Level) bool {
109+
return h.handler.Enabled(ctx, lvl)
110+
}
111+
112+
// Handle handles the Record.
113+
// It will only be called when Enabled returns true.
114+
// The Context argument is as for Enabled.
115+
// It is present solely to provide Handlers access to the context's values.
116+
// Canceling the context should not affect record processing.
117+
// (Among other things, log messages may be necessary to debug a
118+
// cancellation-related problem.)
119+
//
120+
// Handle methods that produce output should observe the following rules:
121+
// - If r.Time is the zero time, ignore the time.
122+
// - If r.PC is zero, ignore it.
123+
// - Attr's values should be resolved.
124+
// - If an Attr's key and value are both the zero value, ignore the Attr.
125+
// This can be tested with attr.Equal(Attr{}).
126+
// - If a group's key is empty, inline the group's Attrs.
127+
// - If a group has no Attrs (even if it has a non-empty key),
128+
// ignore it.
129+
func (h NRHandler) Handle(ctx context.Context, record slog.Record) error {
130+
data := newrelic.LogData{
131+
Severity: record.Level.String(),
132+
Timestamp: record.Time.UnixMilli(),
133+
Message: record.Message,
134+
}
135+
if h.txn != nil {
136+
h.txn.RecordLog(data)
137+
} else {
138+
h.app.RecordLog(data)
139+
}
140+
141+
return h.handler.Handle(ctx, record)
142+
}
143+
144+
// WithAttrs returns a new Handler whose attributes consist of
145+
// both the receiver's attributes and the arguments.
146+
// The Handler owns the slice: it may retain, modify or discard it.
147+
func (h NRHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
148+
handler := h.handler.WithAttrs(attrs)
149+
return NRHandler{
150+
handler: handler,
151+
app: h.app,
152+
txn: h.txn,
153+
}
154+
155+
}
156+
157+
// WithGroup returns a new Handler with the given group appended to
158+
// the receiver's existing groups.
159+
// The keys of all subsequent attributes, whether added by With or in a
160+
// Record, should be qualified by the sequence of group names.
161+
//
162+
// How this qualification happens is up to the Handler, so long as
163+
// this Handler's attribute keys differ from those of another Handler
164+
// with a different sequence of group names.
165+
//
166+
// A Handler should treat WithGroup as starting a Group of Attrs that ends
167+
// at the end of the log event. That is,
168+
//
169+
// logger.WithGroup("s").LogAttrs(level, msg, slog.Int("a", 1), slog.Int("b", 2))
170+
//
171+
// should behave like
172+
//
173+
// logger.LogAttrs(level, msg, slog.Group("s", slog.Int("a", 1), slog.Int("b", 2)))
174+
//
175+
// If the name is empty, WithGroup returns the receiver.
176+
func (h NRHandler) WithGroup(name string) slog.Handler {
177+
handler := h.handler.WithGroup(name)
178+
return NRHandler{
179+
handler: handler,
180+
app: h.app,
181+
txn: h.txn,
182+
}
183+
}

0 commit comments

Comments
 (0)