Closed jnatalzia closed 5 years ago
Wow, the idea sounds cool! I want to help you on this feature as you start to implementation. It will be lot of fun to see colorful log streams!
Sounds great! Would love your thoughts on how to be integrate with the existing code base. I'm not too familiar with it but from my light experience with it, it seems like separating a logger class from the builder would be a nice separator and still allow folks to use just the builder if they're not trying to color all the logs.
Yeah Logger's itself can be implemented with builder pattern to accumulate matcherFuncs in struct, we can simply wrap golangs logger functions to inject colorized strings to logger. I will experiment some abstractions asap.
👍
Joe, I want to hear about your suggestions for managing the repository. Should we create a new branch for new features/bug fixes? Or should we go on master simply?
Heya!
Yeah I think new branches make the most sense. It'll help to have the code sectioned out for reviews as well as open the opportunity to parallelize any feature development!
If you want to make a branch with even some pseudo-code of how you see this logger wrapper working, I'd be more than happy to weigh in on it and collaborate.
Hey @cyucelen have you had a chance to look into this? I'm happy to take a crack at it this weekend if you've been busy!
I was planning to dive in this weekend. Go ahead and start if you have time earlier than me.
Just created a new branch log-marker
and started to implement logger functionality.
My idea is wrapping the Golang's logger with our logger. So, implemented the Print function for inspiration. We can wrap others Println
, Printf
etc...
You can find a better name for LogMarkerRule
and can change the current abstraction I made.
Had a thought after browsing some other implementations. Rather than wrapping fmt
which it seems you're thinking, what do you think about wrapping the log
library?
This link looked promising: https://snippets.aktagon.com/snippets/795-a-simple-log-wrapper-for-go
The additional metadata is great for features like mark surrounded or regex vs fmt which is going to print the raw line
Yes, indeed i wrapped log
library! Take a look at my commits.
Oh nice! Will give a look. What do you think about opening a work in progress (draft) pr to make comments against?
Draft PR opened! Waiting for your comment to add you as assignee.
@jnatalzia also what do you think about being collaborator to the marker!
Looking now! Also I'd be happy to be a collaborator 🙂
There are many various libraries that helps logging things, but most of them have one thing in common - they write information using io.Writer interface. And builtin log actually does the same thing - you can control where it writes using log.SetOutput. So, we can make more general solution to this problem. We can make wrapper to io.Writer interface that colourize its input and writes it to old Writer. Rough, incorrect code that just illustrate my idea:
type ColorWriter struct {
Out io.Writer
// some fields
}
func (cw *ColorWriter) Write(p []byte) (n int, err error) {
// convert p to string, maybe we should wait until \n and collect parts
s := ...
// colorize
marked = Mark(marked, rule.Matcher, rule.Color)
return cw.Out.Write([]byte(marked))
}
// for logger
log.SetOutput(ColorWriter{stdout})
Of course there are some drawbacks. For example we can not control colors for different log methods. Question is: what actually do we want?
Oooo very interesting.
For example we can not control colors for different log method
Do you mean different places to write to? As in colorizing only matters in a stdout case?
Do you mean different places to write to? As in colorizing only matters in a stdout case?
Actually it does. If logging is happening to file - colors will be in the way later. But it wasn't a point, I completely forgot about case you mentioned, but it is also a very good remark.
I can't imagine why we should have different behaviour for different log methods, so we will end in just wrapping all methods of log.
But anyways, we can implement io.Writer
interface to pass marker.StdoutWriter
to log.SetOutput
instead of wrapping all methods of log
right?
type StdoutWriter struct {
rules []MarkRule
Out io.Writer
}
...
// AddRule methods...
...
func (s StdoutWriter) Write(p []byte) (n int, err error) {
marked := string(p)
for _, rule := range s.rules {
marked = Mark(marked, rule.Matcher, rule.Color)
}
return l.Out.Write([]byte(marked))
}
red := color.New(color.FgRed)
stdoutMarker := marker.NewStdoutMarker() // sets Out to os.stdout
stdoutMarker.AddRule(marker.MarkRule{marker.MatchBracketSurrounded(), red})
logger := log.New(stdoutMarker, "", 0)
logger.Println("[you] or not [me]")
This is just for logging to stdout
, we can implement another writer for another use case - most probably we will end up with implementing(when the day comes) another Mark
function for another usecases too.
Like MarkHTML
, MarkPDF
, put your imagination here...
I implemented the io.Writer interface that we discussed. I think it is super easy and awesome now!
We simply reversed the flow from
marker.Logger -> log.Logger -> os.Stdout
to
log.Logger -> marker.StdoutMarker -> os.Stdout
By this way instead of manipulating and passing the text to downstream log.Logger, we are just getting the final output of logger; manipulating it and writing to stdout.
This also makes us pluggable to existing codebases! :tada:
[WIP]
Thinking about this project, it stands to reason that one of the strongest use cases would be for users to colorize their logs for easy reading. With that in mind, the current setup where you create a builder, give it a string, then mark means that there is a decent amount of overhead to integrating it with a logging system.
I was messing around with the
testing
framework and the fact that the testing instances have a.Log
function got me thinking about wrapping marker in a similar way. There could be someCreateLogger
which you could pass a builder to (or maybe it is the builder) which then logs in the colorized manner you specify.