Skip to content

Commit 280bc61

Browse files
committed
Support non-colorized output, logging refactor
Three things are happening here: 1) An environment variable is added to allow for non-colorized text to be output. This is so /usr/sbin/daemon can direct stdout to syslog without escaped control sequences: Apr 15 14:48:52 orla syncv3[41839]: ^[[90m14:48:52^[[0m ^[[32mINF^[[0m Poller: accumulated data ^[[36mdevice [events,changed,left,account]=^[[0m[0,0,0,0] ^[[36mdevice_id=^[[0mQRZLYYCRTO ^[[36mrooms [timeline,state,typing,receipts,invites]=^[[0m[0,0,0,0,0] ^[[36muser_id=^[[0m@doug:yutz.horph.com I would have preferred a command-line switch instead of the env var but am following the existing pattern. 2) zerolog use is refactored. Since there really are no different types of log output and only minimal use of additional context, it makes sense to use zerolog's existing global logger. This simplifies things a bit both textually and cyclomatically and allows for central changes to the logger output based on the new env var. 3) A `go fmt ./...` changed a few very minor things.
1 parent c18961b commit 280bc61

36 files changed

+237
-263
lines changed

Diff for: cmd/syncv3/main.go

+33-12
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,13 @@ package main
33
import (
44
"flag"
55
"fmt"
6-
"log"
6+
"github.com/getsentry/sentry-go"
7+
sentryhttp "github.com/getsentry/sentry-go/http"
8+
"github.com/pressly/goose/v3"
9+
"github.com/prometheus/client_golang/prometheus/promhttp"
10+
"github.com/rs/zerolog"
11+
"github.com/rs/zerolog/log"
12+
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
713
"net/http"
814
_ "net/http/pprof"
915
"os"
@@ -14,13 +20,6 @@ import (
1420
"syscall"
1521
"time"
1622

17-
"github.com/getsentry/sentry-go"
18-
sentryhttp "github.com/getsentry/sentry-go/http"
19-
"github.com/pressly/goose/v3"
20-
"github.com/prometheus/client_golang/prometheus/promhttp"
21-
"github.com/rs/zerolog"
22-
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
23-
2423
syncv3 "github.com/matrix-org/sliding-sync"
2524
"github.com/matrix-org/sliding-sync/internal"
2625
"github.com/matrix-org/sliding-sync/sync2"
@@ -52,6 +51,7 @@ const (
5251
EnvOTLPPassword = "SYNCV3_OTLP_PASSWORD"
5352
EnvSentryDsn = "SYNCV3_SENTRY_DSN"
5453
EnvLogLevel = "SYNCV3_LOG_LEVEL"
54+
EnvPlainOutput = "SYNCV3_PLAIN_OUTPUT"
5555
EnvMaxConns = "SYNCV3_MAX_DB_CONN"
5656
EnvIdleTimeoutSecs = "SYNCV3_DB_IDLE_TIMEOUT_SECS"
5757
EnvHTTPTimeoutSecs = "SYNCV3_HTTP_TIMEOUT_SECS"
@@ -74,11 +74,12 @@ Environment var
7474
%s Default: unset. The Sentry DSN to report events to e.g https://[email protected]/123 - if unset does not send sentry events.
7575
%s Default: info. The level of verbosity for messages logged. Available values are trace, debug, info, warn, error and fatal
7676
%s Default: unset. Max database connections to use when communicating with postgres. Unset or 0 means no limit.
77+
%s Default: unset. Disable colorized output (for cleaner text logging). If set to 1, will output plain text.
7778
%s Default: 3600. The maximum amount of time a database connection may be idle, in seconds. 0 means no limit.
7879
%s Default: 300. The timeout in seconds for normal HTTP requests.
7980
%s Default: 1800. The timeout in seconds for initial sync requests.
8081
`, EnvServer, EnvDB, EnvSecret, EnvBindAddr, EnvTLSCert, EnvTLSKey, EnvPPROF, EnvPrometheus, EnvOTLP, EnvOTLPUsername, EnvOTLPPassword,
81-
EnvSentryDsn, EnvLogLevel, EnvMaxConns, EnvIdleTimeoutSecs, EnvHTTPTimeoutSecs, EnvHTTPInitialTimeoutSecs)
82+
EnvSentryDsn, EnvLogLevel, EnvMaxConns, EnvPlainOutput, EnvIdleTimeoutSecs, EnvHTTPTimeoutSecs, EnvHTTPInitialTimeoutSecs)
8283

8384
func defaulting(in, dft string) string {
8485
if in == "" {
@@ -113,6 +114,7 @@ func main() {
113114
EnvSentryDsn: os.Getenv(EnvSentryDsn),
114115
EnvLogLevel: os.Getenv(EnvLogLevel),
115116
EnvMaxConns: defaulting(os.Getenv(EnvMaxConns), "0"),
117+
EnvPlainOutput: defaulting(os.Getenv(EnvPlainOutput), "0"),
116118
EnvIdleTimeoutSecs: defaulting(os.Getenv(EnvIdleTimeoutSecs), "3600"),
117119
EnvHTTPTimeoutSecs: defaulting(os.Getenv(EnvHTTPTimeoutSecs), "300"),
118120
EnvHTTPInitialTimeoutSecs: defaulting(os.Getenv(EnvHTTPInitialTimeoutSecs), "1800"),
@@ -194,6 +196,25 @@ func main() {
194196
}
195197
}
196198

199+
if args[EnvPlainOutput] != "1" {
200+
log.Logger = log.Output(zerolog.ConsoleWriter{
201+
Out: os.Stderr,
202+
TimeFormat: "15:04:05",
203+
})
204+
} else {
205+
output := zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: time.RFC3339}
206+
output.FormatTimestamp = func(i interface{}) string {
207+
return fmt.Sprintf("%v", i)
208+
}
209+
output.FormatLevel = func(i interface{}) string {
210+
return strings.ToUpper(fmt.Sprintf("%s", i))
211+
}
212+
output.FormatFieldName = func(i interface{}) string {
213+
return fmt.Sprintf("%s=", i)
214+
}
215+
log.Logger = zerolog.New(output).With().Timestamp().Logger()
216+
}
217+
197218
maxConnsInt, err := strconv.Atoi(args[EnvMaxConns])
198219
if err != nil {
199220
panic("invalid value for " + EnvMaxConns + ": " + args[EnvMaxConns])
@@ -284,12 +305,12 @@ func executeMigrations() {
284305

285306
db, err := goose.OpenDBWithDriver("postgres", envArgs[EnvDB])
286307
if err != nil {
287-
log.Fatalf("goose: failed to open DB: %v\n", err)
308+
log.Fatal().Err(err).Msgf("goose: failed to open DB: %v\n", err)
288309
}
289310

290311
defer func() {
291312
if err := db.Close(); err != nil {
292-
log.Fatalf("goose: failed to close DB: %v\n", err)
313+
log.Fatal().Err(err).Msgf("goose: failed to close DB: %v\n", err)
293314
}
294315
}()
295316

@@ -300,7 +321,7 @@ func executeMigrations() {
300321

301322
goose.SetBaseFS(syncv3.EmbedMigrations)
302323
if err := goose.Run(command, db, "state/migrations", arguments...); err != nil {
303-
log.Fatalf("goose %v: %v", command, err)
324+
log.Fatal().Err(err).Msgf("goose %v: %v", command, err)
304325
}
305326
}
306327

Diff for: internal/errors.go

+2-8
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,9 @@ import (
88
"runtime"
99

1010
"github.com/getsentry/sentry-go"
11-
12-
"github.com/rs/zerolog"
11+
"github.com/rs/zerolog/log"
1312
)
1413

15-
var logger = zerolog.New(os.Stdout).With().Timestamp().Logger().Output(zerolog.ConsoleWriter{
16-
Out: os.Stderr,
17-
TimeFormat: "15:04:05",
18-
})
19-
2014
type HandlerError struct {
2115
StatusCode int
2216
Err error
@@ -103,7 +97,7 @@ func assert(msg string, expr bool) {
10397
if os.Getenv("SYNCV3_DEBUG") == "1" {
10498
panic(fmt.Sprintf("assert: %s", msg))
10599
}
106-
l := logger.Error()
100+
l := log.Error()
107101
_, file, line, ok := runtime.Caller(1)
108102
if ok {
109103
l = l.Str("assertion", fmt.Sprintf("%s:%d", file, line))

Diff for: pubsub/pubsub.go

-7
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,12 @@ package pubsub
22

33
import (
44
"fmt"
5-
"os"
65
"sync"
76
"time"
87

98
"github.com/prometheus/client_golang/prometheus"
10-
"github.com/rs/zerolog"
119
)
1210

13-
var logger = zerolog.New(os.Stdout).With().Timestamp().Logger().Output(zerolog.ConsoleWriter{
14-
Out: os.Stderr,
15-
TimeFormat: "15:04:05",
16-
})
17-
1811
type Payload interface {
1912
// The type of payload; used mostly for logging and prometheus metrics
2013
Type() string

Diff for: pubsub/v2.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"encoding/json"
55

66
"github.com/matrix-org/sliding-sync/internal"
7+
"github.com/rs/zerolog/log"
78
)
89

910
// The channel which has V2* payloads
@@ -197,7 +198,7 @@ func (v *V2Sub) onMessage(p Payload) {
197198
case *V2StateRedaction:
198199
v.receiver.OnStateRedaction(pl)
199200
default:
200-
logger.Warn().Str("type", p.Type()).Msg("V2Sub: unhandled payload type")
201+
log.Warn().Str("type", p.Type()).Msg("V2Sub: unhandled payload type")
201202
}
202203
}
203204

Diff for: pubsub/v3.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package pubsub
22

3+
import (
4+
"github.com/rs/zerolog/log"
5+
)
6+
37
// The channel which has V3* payloads
48
const ChanV3 = "v3ch"
59

@@ -39,7 +43,7 @@ func (v *V3Sub) onMessage(p Payload) {
3943
case *V3EnsurePolling:
4044
v.receiver.EnsurePolling(pl)
4145
default:
42-
logger.Warn().Str("type", p.Type()).Msg("V3Sub: unhandled payload type")
46+
log.Warn().Str("type", p.Type()).Msg("V3Sub: unhandled payload type")
4347
}
4448
}
4549

Diff for: sqlutil/sql.go

+4-9
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,12 @@ import (
44
"context"
55
"fmt"
66
"github.com/matrix-org/sliding-sync/internal"
7-
"github.com/rs/zerolog"
8-
"os"
97
"runtime/debug"
108

119
"github.com/jmoiron/sqlx"
10+
"github.com/rs/zerolog/log"
1211
)
1312

14-
var logger = zerolog.New(os.Stdout).With().Timestamp().Logger().Output(zerolog.ConsoleWriter{
15-
Out: os.Stderr,
16-
TimeFormat: "15:04:05",
17-
})
18-
1913
// WithTransaction runs a block of code passing in an SQL transaction
2014
// If the code returns an error or panics then the transactions is rolled back
2115
// Otherwise the transaction is committed.
@@ -30,7 +24,7 @@ func WithTransaction(db *sqlx.DB, fn func(txn *sqlx.Tx) error) (err error) {
3024
if err == nil && panicErr != nil {
3125
// TODO: thread a context through to here?
3226
ctx := context.Background()
33-
logger.Error().Msg(string(debug.Stack()))
27+
log.Error().Msg(string(debug.Stack()))
3428
internal.GetSentryHubFromContextOrDefault(ctx).RecoverWithContext(ctx, panicErr)
3529
err = fmt.Errorf("panic: %v", panicErr)
3630
}
@@ -59,7 +53,8 @@ type Chunker interface {
5953
// Inserting events using NamedExec involves 3n params (n=number of events), meaning it's easy to hit
6054
// the limit in rooms like Matrix HQ. This function breaks up the events into chunks which can be
6155
// batch inserted in multiple statements. Without this, you'll see errors like:
62-
// "pq: got 95331 parameters but PostgreSQL only supports 65535 parameters"
56+
//
57+
// "pq: got 95331 parameters but PostgreSQL only supports 65535 parameters"
6358
func Chunkify(numParamsPerStmt, maxParamsPerCall int, entries Chunker) []Chunker {
6459
// common case, most things are small
6560
if (entries.Len() * numParamsPerStmt) <= maxParamsPerCall {

Diff for: state/accumulator.go

+8-7
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/jmoiron/sqlx"
1414
"github.com/lib/pq"
1515
"github.com/matrix-org/sliding-sync/sqlutil"
16+
"github.com/rs/zerolog/log"
1617
"github.com/tidwall/gjson"
1718
)
1819

@@ -77,7 +78,7 @@ func (a *Accumulator) calculateNewSnapshot(old StrippedEvents, new Event) (Strip
7778
// ruh roh. This should be impossible, but it can happen if the v2 response sends the same
7879
// event in both state and timeline. We need to alert the operator and whine badly as it means
7980
// we have lost an event by now.
80-
logger.Warn().Str("new_event_id", new.ID).Str("old_event_id", e.ID).Str("room_id", new.RoomID).Str("type", new.Type).Str("state_key", new.StateKey).Msg(
81+
log.Warn().Str("new_event_id", new.ID).Str("old_event_id", e.ID).Str("room_id", new.RoomID).Str("type", new.Type).Str("state_key", new.StateKey).Msg(
8182
"Detected different event IDs with the same NID when rolling forward state. This has resulted in data loss in this room (1 event). " +
8283
"This can happen when the v2 /sync response sends the same event in both state and timeline sections. " +
8384
"The event in this log line has been dropped!",
@@ -227,7 +228,7 @@ func (a *Accumulator) Initialise(roomID string, state []json.RawMessage) (Initia
227228
// we don't have a current snapshot for this room but yet no events are new,
228229
// no idea how this should be handled.
229230
const errMsg = "Accumulator.Initialise: room has no current snapshot but also no new inserted events, doing nothing. This is probably a bug."
230-
logger.Error().Str("room_id", roomID).Msg(errMsg)
231+
log.Error().Str("room_id", roomID).Msg(errMsg)
231232
sentry.CaptureException(fmt.Errorf(errMsg))
232233
}
233234
// Note: we otherwise ignore cases where the state has only changed to a
@@ -398,7 +399,7 @@ func (a *Accumulator) Accumulate(txn *sqlx.Tx, userID, roomID string, timeline s
398399
} else {
399400
// Bail out and complain loudly.
400401
const msg = "Accumulator: skipping processing of timeline, as no snapshot exists"
401-
logger.Warn().
402+
log.Warn().
402403
Str("event_id", newEvents[0].ID).
403404
Str("event_type", newEvents[0].Type).
404405
Str("event_state_key", newEvents[0].StateKey).
@@ -484,7 +485,7 @@ func (a *Accumulator) Accumulate(txn *sqlx.Tx, userID, roomID string, timeline s
484485
if roomVersion == "" {
485486
// Defaults to "1" if the key does not exist.
486487
roomVersion = "1"
487-
logger.Warn().Str("room", roomID).Err(err).Msg(
488+
log.Warn().Str("room", roomID).Err(err).Msg(
488489
"Redact: no content.room_version in create event, defaulting to v1",
489490
)
490491
}
@@ -576,13 +577,13 @@ func parseAndDeduplicateTimelineEvents(roomID string, timeline sync2.TimelineRes
576577
RoomID: roomID,
577578
}
578579
if err := e.ensureFieldsSetOnEvent(); err != nil {
579-
logger.Warn().Str("event_id", e.ID).Str("room_id", roomID).Err(err).Msg(
580+
log.Warn().Str("event_id", e.ID).Str("room_id", roomID).Err(err).Msg(
580581
"Accumulator.filterToNewTimelineEvents: failed to parse event, ignoring",
581582
)
582583
continue
583584
}
584585
if _, ok := seenEvents[e.ID]; ok {
585-
logger.Warn().Str("event_id", e.ID).Str("room_id", roomID).Msg(
586+
log.Warn().Str("event_id", e.ID).Str("room_id", roomID).Msg(
586587
"Accumulator.filterToNewTimelineEvents: seen the same event ID twice, ignoring",
587588
)
588589
continue
@@ -671,7 +672,7 @@ func ensureStateHasCreateEvent(events []Event) error {
671672
})
672673
sentry.CaptureMessage(errMsg)
673674
})
674-
logger.Warn().
675+
log.Warn().
675676
Str("room_id", events[0].RoomID).
676677
Int("len_state", len(events)).
677678
Msg(errMsg)

Diff for: state/event_table.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/matrix-org/gomatrixserverlib"
1515
"github.com/matrix-org/sliding-sync/internal"
1616
"github.com/matrix-org/sliding-sync/sqlutil"
17+
"github.com/rs/zerolog/log"
1718
)
1819

1920
const (
@@ -360,7 +361,7 @@ func (t *EventTable) Redact(txn *sqlx.Tx, roomVer string, redacteeEventIDToRedac
360361
if err != nil {
361362
// unknown room version... let's just default to "1"
362363
rv = gomatrixserverlib.MustGetRoomVersion(gomatrixserverlib.RoomVersionV1)
363-
logger.Warn().Str("version", roomVer).Err(err).Msg(
364+
log.Warn().Str("version", roomVer).Err(err).Msg(
364365
"Redact: GetRoomVersion: unknown room version, defaulting to v1",
365366
)
366367
}
@@ -523,7 +524,7 @@ func filterAndEnsureFieldsSet(events []Event) []Event {
523524
for i := range events {
524525
ev := &events[i]
525526
if err := ev.ensureFieldsSetOnEvent(); err != nil {
526-
logger.Warn().Str("event_id", ev.ID).Err(err).Msg(
527+
log.Warn().Str("event_id", ev.ID).Err(err).Msg(
527528
"filterAndEnsureFieldsSet: failed to parse event, ignoring",
528529
)
529530
continue

Diff for: state/migrations/20230822180807_bogus_snapshot_cleanup.go

+5-10
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,12 @@ import (
44
"context"
55
"database/sql"
66
"fmt"
7+
78
"github.com/lib/pq"
89
"github.com/pressly/goose/v3"
9-
"github.com/rs/zerolog"
10-
"os"
10+
"github.com/rs/zerolog/log"
1111
)
1212

13-
var logger = zerolog.New(os.Stdout).With().Timestamp().Logger().Output(zerolog.ConsoleWriter{
14-
Out: os.Stderr,
15-
TimeFormat: "15:04:05",
16-
})
17-
1813
func init() {
1914
goose.AddMigrationContext(upBogusSnapshotCleanup, downBogusSnapshotCleanup)
2015
}
@@ -29,7 +24,7 @@ func upBogusSnapshotCleanup(ctx context.Context, tx *sql.Tx) error {
2924
if len(bogusRooms) == 0 {
3025
return nil
3126
}
32-
logger.Info().Strs("room_ids", bogusRooms).
27+
log.Info().Strs("room_ids", bogusRooms).
3328
Msgf("Found %d bogus rooms to cleanup", len(bogusRooms))
3429

3530
tables := []string{"syncv3_snapshots", "syncv3_events", "syncv3_rooms"}
@@ -52,9 +47,9 @@ func deleteFromTable(ctx context.Context, tx *sql.Tx, table string, roomIDs []st
5247
}
5348
ra, err := result.RowsAffected()
5449
if err != nil {
55-
logger.Warn().Err(err).Msgf("Couldn't get number of rows deleted from %s", table)
50+
log.Warn().Err(err).Msgf("Couldn't get number of rows deleted from %s", table)
5651
} else {
57-
logger.Info().Msgf("Deleted %d rows from %s", ra, table)
52+
log.Info().Msgf("Deleted %d rows from %s", ra, table)
5853
}
5954
return nil
6055
}

0 commit comments

Comments
 (0)