lmittmann / tint

🌈 slog.Handler that writes tinted (colorized) logs
https://pkg.go.dev/github.com/lmittmann/tint
MIT License
731 stars 38 forks source link

Colorized attribute #59

Open tommsawyer opened 6 months ago

tommsawyer commented 6 months ago

Hi! I'm trying to add syntax highlighting for my SQL queries in logs.

There is a library that does it pretty well:

package main

import (
    "bytes"
    "os"

    "github.com/alecthomas/chroma/quick"
)

func main() {
    var q bytes.Buffer
    quick.Highlight(&q, "SELECT 1 + 1", "sql", "terminal16m", "monokai")
    os.Stderr.Write(q.Bytes()) // output will be colorized, as expected
}

But when I try to add colorized SQL as slog.Attr, it will print escaped sequence instead:

package main

import (
    "bytes"
    "log/slog"
    "os"
    "time"

    "github.com/alecthomas/chroma/quick"
    "github.com/lmittmann/tint"
)

func main() {
    slog.SetDefault(slog.New(
        tint.NewHandler(os.Stderr, &tint.Options{
            Level:      slog.LevelDebug,
            TimeFormat: time.TimeOnly,
        }),
    ))

    var q bytes.Buffer
    quick.Highlight(&q, "SELECT 1 + 1", "sql", "terminal16m", "monokai")

    // prints something like
    // 18:50:29 INF SQL query query="\x1b[38;2;102;217;239mSELECT\x1b[0m\x1b[38;2;248;248;242m \x1b[0m\x1b[38;2;174;129;255m1\x1b[0m\x1b[38;2;24
    slog.Info("SQL query", "query", q.String())
}

I believe this is happening because of strconv.AppendQuote, which you are using to quote strings here. AppendQuote escapes all the colors sequences.

Seems like you're passing "quote=true" everywhere and I cannot disable this behavior using ReplaceAttrs or something like that.

Am I missing something? Is there a way to preserve colors for some attributes? Thanks!

jose-tim commented 6 months ago

In case my idea is fine for the lib, I solved this issue for me with:

imagen

imagen

imagen

imagen

mologie commented 4 months ago

Careful though, if this is solved with just a prefix then an attacker could exploit this to make your terminal do funky things by if they merely control some to-be-logged value (which they usually do).

If this becomes a library feature then imo it should be 1) behind an off-by-default flag (for e.g. libraries) and 2) a special type to wrap unsafe "raw" strings with, that should not be escaped when being printed.