Initial changes to provide configurable logging options
This commit is contained in:
parent
f55e04bb7a
commit
7326b390a0
70
chromedp.go
70
chromedp.go
|
@ -34,6 +34,9 @@ type CDP struct {
|
||||||
// handlerMap is the map of target IDs to its active handler.
|
// handlerMap is the map of target IDs to its active handler.
|
||||||
handlerMap map[string]int
|
handlerMap map[string]int
|
||||||
|
|
||||||
|
// logging funcs
|
||||||
|
logf, debugf, errorf LogFunc
|
||||||
|
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,6 +47,9 @@ func New(ctxt context.Context, opts ...Option) (*CDP, error) {
|
||||||
c := &CDP{
|
c := &CDP{
|
||||||
handlers: make([]*TargetHandler, 0),
|
handlers: make([]*TargetHandler, 0),
|
||||||
handlerMap: make(map[string]int),
|
handlerMap: make(map[string]int),
|
||||||
|
logf: log.Printf,
|
||||||
|
debugf: func(string, ...interface{}) {},
|
||||||
|
errorf: func(s string, v ...interface{}) { log.Printf("error: "+s, v...) },
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply options
|
// apply options
|
||||||
|
@ -108,16 +114,16 @@ func (c *CDP) AddTarget(ctxt context.Context, t client.Target) {
|
||||||
defer c.Unlock()
|
defer c.Unlock()
|
||||||
|
|
||||||
// create target manager
|
// create target manager
|
||||||
h, err := NewTargetHandler(t)
|
h, err := NewTargetHandler(t, c.logf, c.debugf, c.errorf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("error: could not create handler for %s, got: %v", t, err)
|
c.errorf("could not create handler for %s, got: %v", t, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// run
|
// run
|
||||||
err = h.Run(ctxt)
|
err = h.Run(ctxt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("error: could not start handler for %s, got: %v", t, err)
|
c.errorf("could not start handler for %s, got: %v", t, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,8 +350,8 @@ func (c *CDP) Run(ctxt context.Context, a Action) error {
|
||||||
// Option is a Chrome Debugging Protocol option.
|
// Option is a Chrome Debugging Protocol option.
|
||||||
type Option func(*CDP) error
|
type Option func(*CDP) error
|
||||||
|
|
||||||
// WithRunner is a option to specify the underlying Chrome runner to monitor
|
// WithRunner is a CDP option to specify the underlying Chrome runner to
|
||||||
// for page handlers.
|
// monitor for page handlers.
|
||||||
func WithRunner(r *runner.Runner) Option {
|
func WithRunner(r *runner.Runner) Option {
|
||||||
return func(c *CDP) error {
|
return func(c *CDP) error {
|
||||||
c.r = r
|
c.r = r
|
||||||
|
@ -353,8 +359,8 @@ func WithRunner(r *runner.Runner) Option {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithTargets is an option to specify the incoming targets to monitor for page
|
// WithTargets is a CDP option to specify the incoming targets to monitor for
|
||||||
// handlers.
|
// page handlers.
|
||||||
func WithTargets(watch <-chan client.Target) Option {
|
func WithTargets(watch <-chan client.Target) Option {
|
||||||
return func(c *CDP) error {
|
return func(c *CDP) error {
|
||||||
c.watch = watch
|
c.watch = watch
|
||||||
|
@ -362,7 +368,7 @@ func WithTargets(watch <-chan client.Target) Option {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithRunnerOptions is a option to specify the options to pass to a newly
|
// WithRunnerOptions is a CDP option to specify the options to pass to a newly
|
||||||
// created Chrome process runner.
|
// created Chrome process runner.
|
||||||
func WithRunnerOptions(opts ...runner.CommandLineOption) Option {
|
func WithRunnerOptions(opts ...runner.CommandLineOption) Option {
|
||||||
return func(c *CDP) error {
|
return func(c *CDP) error {
|
||||||
|
@ -370,3 +376,51 @@ func WithRunnerOptions(opts ...runner.CommandLineOption) Option {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LogFunc is the common logging func type.
|
||||||
|
type LogFunc func(string, ...interface{})
|
||||||
|
|
||||||
|
// WithLogf is a CDP option to specify a func to receive general logging.
|
||||||
|
func WithLogf(f LogFunc) Option {
|
||||||
|
return func(c *CDP) error {
|
||||||
|
c.logf = f
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithDebugf is a CDP option to specify a func to receive debug logging (ie,
|
||||||
|
// protocol information).
|
||||||
|
func WithDebugf(f LogFunc) Option {
|
||||||
|
return func(c *CDP) error {
|
||||||
|
c.debugf = f
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithErrorf is a CDP option to specify a func to receive error logging.
|
||||||
|
func WithErrorf(f LogFunc) Option {
|
||||||
|
return func(c *CDP) error {
|
||||||
|
c.errorf = f
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithLog is a CDP option that sets the logging, debugging, and error funcs to
|
||||||
|
// f.
|
||||||
|
func WithLog(f LogFunc) Option {
|
||||||
|
return func(c *CDP) error {
|
||||||
|
c.logf = f
|
||||||
|
c.debugf = f
|
||||||
|
c.errorf = f
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithConsolef is a CDP option to specify a func to receive chrome log events.
|
||||||
|
//
|
||||||
|
// Note: NOT YET IMPLEMENTED.
|
||||||
|
func WithConsolef(f LogFunc) Option {
|
||||||
|
return func(c *CDP) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
45
handler.go
45
handler.go
|
@ -3,7 +3,6 @@ package chromedp
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -54,17 +53,25 @@ type TargetHandler struct {
|
||||||
res map[int64]chan interface{}
|
res map[int64]chan interface{}
|
||||||
resrw sync.RWMutex
|
resrw sync.RWMutex
|
||||||
|
|
||||||
|
// logging funcs
|
||||||
|
logf, debugf, errorf LogFunc
|
||||||
|
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTargetHandler creates a new handler for the specified client target.
|
// NewTargetHandler creates a new handler for the specified client target.
|
||||||
func NewTargetHandler(t client.Target) (*TargetHandler, error) {
|
func NewTargetHandler(t client.Target, logf, debugf, errorf LogFunc) (*TargetHandler, error) {
|
||||||
conn, err := client.Dial(t)
|
conn, err := client.Dial(t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &TargetHandler{conn: conn}, nil
|
return &TargetHandler{
|
||||||
|
conn: conn,
|
||||||
|
logf: logf,
|
||||||
|
debugf: debugf,
|
||||||
|
errorf: errorf,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run starts the processing of commands and events of the client target
|
// Run starts the processing of commands and events of the client target
|
||||||
|
@ -154,7 +161,7 @@ func (h *TargetHandler) run(ctxt context.Context) {
|
||||||
h.qres <- msg
|
h.qres <- msg
|
||||||
|
|
||||||
default:
|
default:
|
||||||
log.Printf("ignoring malformed incoming message (missing id or method): %#v", msg)
|
h.errorf("ignoring malformed incoming message (missing id or method): %#v", msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
case <-h.detached:
|
case <-h.detached:
|
||||||
|
@ -175,19 +182,19 @@ func (h *TargetHandler) run(ctxt context.Context) {
|
||||||
case ev := <-h.qevents:
|
case ev := <-h.qevents:
|
||||||
err = h.processEvent(ctxt, ev)
|
err = h.processEvent(ctxt, ev)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("could not process event, got: %v", err)
|
h.errorf("could not process event, got: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
case res := <-h.qres:
|
case res := <-h.qres:
|
||||||
err = h.processResult(res)
|
err = h.processResult(res)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("could not process command result, got: %v", err)
|
h.errorf("could not process command result, got: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
case cmd := <-h.qcmd:
|
case cmd := <-h.qcmd:
|
||||||
err = h.processCommand(cmd)
|
err = h.processCommand(cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("could not process command, got: %v", err)
|
h.errorf("could not process command, got: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
case <-ctxt.Done():
|
case <-ctxt.Done():
|
||||||
|
@ -204,7 +211,7 @@ func (h *TargetHandler) read() (*cdp.Message, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("-> %s", string(buf))
|
h.debugf("-> %s", string(buf))
|
||||||
|
|
||||||
// unmarshal
|
// unmarshal
|
||||||
msg := new(cdp.Message)
|
msg := new(cdp.Message)
|
||||||
|
@ -264,7 +271,7 @@ func (h *TargetHandler) processEvent(ctxt context.Context, msg *cdp.Message) err
|
||||||
func (h *TargetHandler) documentUpdated(ctxt context.Context) {
|
func (h *TargetHandler) documentUpdated(ctxt context.Context) {
|
||||||
f, err := h.WaitFrame(ctxt, EmptyFrameID)
|
f, err := h.WaitFrame(ctxt, EmptyFrameID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("could not get current frame, got: %v", err)
|
h.errorf("could not get current frame, got: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,7 +286,7 @@ func (h *TargetHandler) documentUpdated(ctxt context.Context) {
|
||||||
f.Nodes = make(map[cdp.NodeID]*cdp.Node)
|
f.Nodes = make(map[cdp.NodeID]*cdp.Node)
|
||||||
f.Root, err = dom.GetDocument().WithPierce(true).Do(ctxt, h)
|
f.Root, err = dom.GetDocument().WithPierce(true).Do(ctxt, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("error could not retrieve document root for %s, got: %v", f.ID, err)
|
h.errorf("could not retrieve document root for %s, got: %v", f.ID, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
f.Root.Invalidated = make(chan struct{})
|
f.Root.Invalidated = make(chan struct{})
|
||||||
|
@ -293,7 +300,9 @@ func (h *TargetHandler) processResult(msg *cdp.Message) error {
|
||||||
|
|
||||||
res, ok := h.res[msg.ID]
|
res, ok := h.res[msg.ID]
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("expected result to be present for message id %d", msg.ID))
|
err := fmt.Errorf("expected result to be present for message id %d", msg.ID)
|
||||||
|
h.errorf(err.Error())
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if msg.Error != nil {
|
if msg.Error != nil {
|
||||||
|
@ -316,7 +325,7 @@ func (h *TargetHandler) processCommand(cmd *cdp.Message) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("<- %s", string(buf))
|
h.debugf("<- %s", string(buf))
|
||||||
|
|
||||||
// write
|
// write
|
||||||
return h.conn.Write(buf)
|
return h.conn.Write(buf)
|
||||||
|
@ -539,12 +548,13 @@ func (h *TargetHandler) pageEvent(ctxt context.Context, ev interface{}) {
|
||||||
return
|
return
|
||||||
|
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("unhandled page event %s", reflect.TypeOf(ev)))
|
h.errorf("unhandled page event %s", reflect.TypeOf(ev))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := h.WaitFrame(ctxt, id)
|
f, err := h.WaitFrame(ctxt, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("error could not get frame %s, got: %v", id, err)
|
h.errorf("could not get frame %s, got: %v", id, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -564,7 +574,7 @@ func (h *TargetHandler) domEvent(ctxt context.Context, ev interface{}) {
|
||||||
// wait current frame
|
// wait current frame
|
||||||
f, err := h.WaitFrame(ctxt, EmptyFrameID)
|
f, err := h.WaitFrame(ctxt, EmptyFrameID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("error processing DOM event %s: error waiting for frame, got: %v", reflect.TypeOf(ev), err)
|
h.errorf("error processing DOM event %s: error waiting for frame, got: %v", reflect.TypeOf(ev), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -624,7 +634,8 @@ func (h *TargetHandler) domEvent(ctxt context.Context, ev interface{}) {
|
||||||
return
|
return
|
||||||
|
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("unhandled node event %s", reflect.TypeOf(ev)))
|
h.errorf("unhandled node event %s", reflect.TypeOf(ev))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
s := strings.TrimPrefix(strings.TrimSuffix(runtime.FuncForPC(reflect.ValueOf(op).Pointer()).Name(), ".func1"), "github.com/knq/chromedp.")
|
s := strings.TrimPrefix(strings.TrimSuffix(runtime.FuncForPC(reflect.ValueOf(op).Pointer()).Name(), ".func1"), "github.com/knq/chromedp.")
|
||||||
|
@ -632,7 +643,7 @@ func (h *TargetHandler) domEvent(ctxt context.Context, ev interface{}) {
|
||||||
// retrieve node
|
// retrieve node
|
||||||
n, err := h.WaitNode(ctxt, f, id)
|
n, err := h.WaitNode(ctxt, f, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("error could not perform (%s) operation on node %d (wait node error), got: %v", s, id, err)
|
h.errorf("error could not perform (%s) operation on node %d (wait node error), got: %v", s, id, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
28
pool.go
28
pool.go
|
@ -3,6 +3,7 @@ package chromedp
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/knq/chromedp/runner"
|
"github.com/knq/chromedp/runner"
|
||||||
|
@ -19,6 +20,9 @@ type Pool struct {
|
||||||
// res are the running chrome resources.
|
// res are the running chrome resources.
|
||||||
res map[int]*Res
|
res map[int]*Res
|
||||||
|
|
||||||
|
// logging funcs
|
||||||
|
logf, debugf, errorf LogFunc
|
||||||
|
|
||||||
rw sync.RWMutex
|
rw sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,9 +31,12 @@ func NewPool(opts ...PoolOption) (*Pool, error) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
p := &Pool{
|
p := &Pool{
|
||||||
start: DefaultPoolStartPort,
|
start: DefaultPoolStartPort,
|
||||||
end: DefaultPoolEndPort,
|
end: DefaultPoolEndPort,
|
||||||
res: make(map[int]*Res),
|
res: make(map[int]*Res),
|
||||||
|
logf: log.Printf,
|
||||||
|
debugf: func(string, ...interface{}) {},
|
||||||
|
errorf: func(s string, v ...interface{}) { log.Printf("error: "+s, v...) },
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply opts
|
// apply opts
|
||||||
|
@ -85,7 +92,10 @@ func (p *Pool) Allocate(ctxt context.Context, opts ...runner.CommandLineOption)
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup cdp
|
// setup cdp
|
||||||
r.c, err = New(ctxt, WithRunner(r.r))
|
r.c, err = New(
|
||||||
|
ctxt, WithRunner(r.r),
|
||||||
|
WithLogf(p.logf), WithDebugf(p.debugf), WithErrorf(p.errorf),
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cancel()
|
cancel()
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -173,3 +183,13 @@ func PortRange(start, end int) PoolOption {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PoolLog is a pool option to set the logging to use for the pool.
|
||||||
|
func PoolLog(logf, debugf, errorf LogFunc) PoolOption {
|
||||||
|
return func(p *Pool) error {
|
||||||
|
p.logf = logf
|
||||||
|
p.debugf = debugf
|
||||||
|
p.errorf = errorf
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user