Skip to content
Merged
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
24 changes: 16 additions & 8 deletions core/types/transaction_signing.go
Original file line number Diff line number Diff line change
Expand Up @@ -534,20 +534,28 @@ type CachedSigner struct {
cache SenderCache
}

func WrapWithCachedSigner(signer Signer, cache SenderCache) *CachedSigner {
return &CachedSigner{
func WrapWithCachedSigner(signer Signer, cache SenderCache) CachedSigner {
return CachedSigner{
Signer: signer,
cache: cache,
}
}


func (cs CachedSigner) Equal(s2 Signer) bool {
cs2, ok := s2.(CachedSigner)
if ok {
// unwrap the signer
return cs.Signer.Equal(cs2.Signer)
}
return cs.Signer.Equal(s2)
}

func (cs CachedSigner) Sender(tx *Transaction) (common.Address, error) {
if tx.from.Load() == nil {
// try to load the sender from the global cache
cached := cs.cache.Get(tx.Hash())
if cached != nil && cached.Signer.Equal(cs.Signer) {
return cached.From, nil
}
// try to load the sender from the global cache
cached := cs.cache.Get(tx.Hash())
if cached != nil && cached.Signer.Equal(cs.Signer) {
return cached.From, nil
}
from, err := cs.Signer.Sender(tx)
if err != nil {
Expand Down
8 changes: 8 additions & 0 deletions log/format.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,16 @@ func PrintOrigins(print bool) {
} else {
atomic.StoreUint32(&locationEnabled, 0)
}
if print {
stackEnabled.Store(true)
}
}

// stackEnabled is an atomic flag controlling whether the log handler needs
// to store the callsite stack. This is needed in case any handler wants to
// print locations (locationEnabled), use vmodule, or print full stacks (BacktraceAt).
var stackEnabled atomic.Bool

// locationEnabled is an atomic flag controlling whether the terminal formatter
// should append the log locations too when printing entries.
var locationEnabled uint32
Expand Down
6 changes: 6 additions & 0 deletions log/handler_glog.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ func (h *GlogHandler) Vmodule(ruleset string) error {
h.siteCache = make(map[uintptr]Lvl)
atomic.StoreUint32(&h.override, uint32(len(filter)))

// Enable location storage (globally)
if len(h.patterns) > 0 {
stackEnabled.Store(true)
}
return nil
}

Expand Down Expand Up @@ -173,6 +177,8 @@ func (h *GlogHandler) BacktraceAt(location string) error {
h.location = location
atomic.StoreUint32(&h.backtrace, uint32(len(location)))

// Enable location storage (globally)
stackEnabled.Store(true)
return nil
}

Expand Down
9 changes: 6 additions & 3 deletions log/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,19 +131,22 @@ type logger struct {
}

func (l *logger) write(msg string, lvl Lvl, ctx []interface{}, skip int) {
l.h.Log(&Record{
record := &Record{
Time: time.Now(),
Lvl: lvl,
Msg: msg,
Ctx: newContext(l.ctx, ctx),
Call: stack.Caller(skip),
KeyNames: RecordKeyNames{
Time: timeKey,
Msg: msgKey,
Lvl: lvlKey,
Ctx: ctxKey,
},
})
}
if stackEnabled.Load() {
record.Call = stack.Caller(skip)
}
l.h.Log(record)
}

func (l *logger) New(ctx ...interface{}) Logger {
Expand Down
67 changes: 67 additions & 0 deletions log/logger_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package log

import (
"bytes"
"os"
"strings"
"testing"
)

// TestLoggingWithTrace checks that if BackTraceAt is set, then the
// gloghandler is capable of spitting out a stacktrace
func TestLoggingWithTrace(t *testing.T) {
defer stackEnabled.Store(stackEnabled.Load())
out := new(bytes.Buffer)
logger := New()
{
glog := NewGlogHandler(StreamHandler(out, TerminalFormat(false)))
glog.Verbosity(LvlTrace)
if err := glog.BacktraceAt("logger_test.go:24"); err != nil {
t.Fatal(err)
}
logger.SetHandler(glog)
}
logger.Trace("a message", "foo", "bar") // Will be bumped to INFO
have := out.String()
if !strings.HasPrefix(have, "INFO") {
t.Fatalf("backtraceat should bump level to info: %s", have)
}
// The timestamp is locale-dependent, so we want to trim that off
// "INFO [01-01|00:00:00.000] a messag ..." -> "a messag..."
have = strings.Split(have, "]")[1]
wantPrefix := " a message\n\ngoroutine"
if !strings.HasPrefix(have, wantPrefix) {
t.Errorf("\nhave: %q\nwant: %q\n", have, wantPrefix)
}
}

// TestLoggingWithVmodule checks that vmodule works.
func TestLoggingWithVmodule(t *testing.T) {
defer stackEnabled.Store(stackEnabled.Load())
out := new(bytes.Buffer)
logger := New()
{
glog := NewGlogHandler(StreamHandler(out, TerminalFormat(false)))
glog.Verbosity(LvlCrit)
logger.SetHandler(glog)
logger.Warn("This should not be seen", "ignored", "true")
glog.Vmodule("logger_test.go=5")
}
logger.Trace("a message", "foo", "bar")
have := out.String()
// The timestamp is locale-dependent, so we want to trim that off
// "INFO [01-01|00:00:00.000] a messag ..." -> "a messag..."
have = strings.Split(have, "]")[1]
want := " a message foo=bar\n"
if have != want {
t.Errorf("\nhave: %q\nwant: %q\n", have, want)
}
}

func BenchmarkTraceLogging(b *testing.B) {
Root().SetHandler(LvlFilterHandler(LvlInfo, StreamHandler(os.Stderr, TerminalFormat(true))))
b.ResetTimer()
for i := 0; i < b.N; i++ {
Trace("a message", "v", i)
}
}
14 changes: 7 additions & 7 deletions metrics/counter.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@ func NewCounter() Counter {
if !Enabled {
return NilCounter{}
}
return &StandardCounter{0}
return &StandardCounter{}
}

// NewCounterForced constructs a new StandardCounter and returns it no matter if
// the global switch is enabled or not.
func NewCounterForced() Counter {
return &StandardCounter{0}
return &StandardCounter{}
}

// NewRegisteredCounter constructs and registers a new StandardCounter.
Expand Down Expand Up @@ -115,27 +115,27 @@ func (NilCounter) Snapshot() Counter { return NilCounter{} }
// StandardCounter is the standard implementation of a Counter and uses the
// sync/atomic package to manage a single int64 value.
type StandardCounter struct {
count int64
count atomic.Int64
}

// Clear sets the counter to zero.
func (c *StandardCounter) Clear() {
atomic.StoreInt64(&c.count, 0)
c.count.Store(0)
}

// Count returns the current count.
func (c *StandardCounter) Count() int64 {
return atomic.LoadInt64(&c.count)
return c.count.Load()
}

// Dec decrements the counter by the given amount.
func (c *StandardCounter) Dec(i int64) {
atomic.AddInt64(&c.count, -i)
c.count.Add(-i)
}

// Inc increments the counter by the given amount.
func (c *StandardCounter) Inc(i int64) {
atomic.AddInt64(&c.count, i)
c.count.Add(i)
}

// Snapshot returns a read-only copy of the counter.
Expand Down
8 changes: 4 additions & 4 deletions metrics/ewma.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func (NilEWMA) Update(n int64) {}
// of uncounted events and processes them on each tick. It uses the
// sync/atomic package to manage uncounted events.
type StandardEWMA struct {
uncounted int64 // /!\ this should be the first member to ensure 64-bit alignment
uncounted atomic.Int64
alpha float64
rate float64
init bool
Expand All @@ -97,8 +97,8 @@ func (a *StandardEWMA) Snapshot() EWMA {
// Tick ticks the clock to update the moving average. It assumes it is called
// every five seconds.
func (a *StandardEWMA) Tick() {
count := atomic.LoadInt64(&a.uncounted)
atomic.AddInt64(&a.uncounted, -count)
count := a.uncounted.Load()
a.uncounted.Add(-count)
instantRate := float64(count) / float64(5*time.Second)
a.mutex.Lock()
defer a.mutex.Unlock()
Expand All @@ -112,5 +112,5 @@ func (a *StandardEWMA) Tick() {

// Update adds n uncounted events.
func (a *StandardEWMA) Update(n int64) {
atomic.AddInt64(&a.uncounted, n)
a.uncounted.Add(n)
}
12 changes: 6 additions & 6 deletions metrics/gauge.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func NewGauge() Gauge {
if !Enabled {
return NilGauge{}
}
return &StandardGauge{0}
return &StandardGauge{}
}

// NewRegisteredGauge constructs and registers a new StandardGauge.
Expand Down Expand Up @@ -101,7 +101,7 @@ func (NilGauge) Value() int64 { return 0 }
// StandardGauge is the standard implementation of a Gauge and uses the
// sync/atomic package to manage a single int64 value.
type StandardGauge struct {
value int64
value atomic.Int64
}

// Snapshot returns a read-only copy of the gauge.
Expand All @@ -111,22 +111,22 @@ func (g *StandardGauge) Snapshot() Gauge {

// Update updates the gauge's value.
func (g *StandardGauge) Update(v int64) {
atomic.StoreInt64(&g.value, v)
g.value.Store(v)
}

// Value returns the gauge's current value.
func (g *StandardGauge) Value() int64 {
return atomic.LoadInt64(&g.value)
return g.value.Load()
}

// Dec decrements the gauge's current value by the given amount.
func (g *StandardGauge) Dec(i int64) {
atomic.AddInt64(&g.value, -i)
g.value.Add(-i)
}

// Inc increments the gauge's current value by the given amount.
func (g *StandardGauge) Inc(i int64) {
atomic.AddInt64(&g.value, i)
g.value.Add(i)
}

// FunctionalGauge returns value from given function
Expand Down
25 changes: 14 additions & 11 deletions metrics/meter.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,7 @@ func NewRegisteredMeterForced(name string, r Registry) Meter {

// MeterSnapshot is a read-only copy of another Meter.
type MeterSnapshot struct {
// WARNING: The `temp` field is accessed atomically.
// On 32 bit platforms, only 64-bit aligned fields can be atomic. The struct is
// guaranteed to be so aligned, so take advantage of that. For more information,
// see https://golang.org/pkg/sync/atomic/#pkg-note-BUG.
temp int64
temp atomic.Int64
count int64
rate1, rate5, rate15, rateMean float64
}
Expand Down Expand Up @@ -173,7 +169,7 @@ type StandardMeter struct {
snapshot *MeterSnapshot
a1, a5, a15 EWMA
startTime time.Time
stopped uint32
stopped atomic.Bool
}

func newStandardMeter() *StandardMeter {
Expand All @@ -188,8 +184,8 @@ func newStandardMeter() *StandardMeter {

// Stop stops the meter, Mark() will be a no-op if you use it after being stopped.
func (m *StandardMeter) Stop() {
stopped := atomic.SwapUint32(&m.stopped, 1)
if stopped != 1 {
stopped := m.stopped.Swap(true)
if !stopped {
arbiter.Lock()
delete(arbiter.meters, m)
arbiter.Unlock()
Expand All @@ -207,7 +203,7 @@ func (m *StandardMeter) Count() int64 {

// Mark records the occurrence of n events.
func (m *StandardMeter) Mark(n int64) {
atomic.AddInt64(&m.snapshot.temp, n)
m.snapshot.temp.Add(n)
}

// Rate1 returns the one-minute moving average rate of events per second.
Expand Down Expand Up @@ -241,7 +237,14 @@ func (m *StandardMeter) RateMean() float64 {
// Snapshot returns a read-only copy of the meter.
func (m *StandardMeter) Snapshot() Meter {
m.lock.RLock()
snapshot := *m.snapshot
snapshot := MeterSnapshot{
count: m.snapshot.count,
rate1: m.snapshot.rate1,
rate5: m.snapshot.rate5,
rate15: m.snapshot.rate15,
rateMean: m.snapshot.rateMean,
}
snapshot.temp.Store(m.snapshot.temp.Load())
m.lock.RUnlock()
return &snapshot
}
Expand All @@ -257,7 +260,7 @@ func (m *StandardMeter) updateSnapshot() {

func (m *StandardMeter) updateMeter() {
// should only run with write lock held on m.lock
n := atomic.SwapInt64(&m.snapshot.temp, 0)
n := m.snapshot.temp.Swap(0)
m.snapshot.count += n
m.a1.Update(n)
m.a5.Update(n)
Expand Down