blob: 754da92fc0ef8137ae2b145503e422f1b95882f0 [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//go:build tracing
// +build tracing
// This file implements a Go equivalent of C++ trace library found at:
// https://fuchsia.googlesource.com/fuchsia/+/HEAD/zircon/system/ulib/trace/include/lib/trace/internal/event_common.h
// https://fuchsia.googlesource.com/fuchsia/+/HEAD/zircon/system/ulib/trace/event.cc
// Package trace provides the functions for instrumenting Go programs to capture
// trace data. It also implements low-level trace engine functions.
package trace
import (
"syscall/zx"
)
// Instant writes an instant event representing a single moment in time (a probe).
func Instant(category, name string, scope EventScope) {
internalEventRecord(category, name, func(c *context, ticks ticksT, threadRef *threadRef, categoryRef, nameRef *stringRef) {
c.writeInstantEventRecord(ticks, threadRef, categoryRef, nameRef, scope, nil)
})
}
// Counter writes a counter event with the specified id.
func Counter(category, name string, counterID CounterID) {
internalEventRecord(category, name, func(c *context, ticks ticksT, threadRef *threadRef, categoryRef, nameRef *stringRef) {
c.writeCounterEventRecord(ticks, threadRef, categoryRef, nameRef, counterID, nil)
})
}
// DurationBegin writes a duration begin event.
func DurationBegin(category, name string) {
internalEventRecord(category, name, func(c *context, ticks ticksT, threadRef *threadRef, categoryRef, nameRef *stringRef) {
c.writeDurationBeginEventRecord(ticks, threadRef, categoryRef, nameRef, nil)
})
}
// DurationEnd writes a duration end event.
func DurationEnd(category, name string) {
internalEventRecord(category, name, func(c *context, ticks ticksT, threadRef *threadRef, categoryRef, nameRef *stringRef) {
c.writeDurationEndEventRecord(ticks, threadRef, categoryRef, nameRef, nil)
})
}
// AsyncBegin writes an asynchronous begin event with the specified id.
func AsyncBegin(category, name string, asyncID AsyncID) {
internalEventRecord(category, name, func(c *context, ticks ticksT, threadRef *threadRef, categoryRef, nameRef *stringRef) {
c.writeAsyncBeginEventRecord(ticks, threadRef, categoryRef, nameRef, asyncID, nil)
})
}
// AsyncInstant writes an asynchronous instant event with the specified id.
func AsyncInstant(category, name string, asyncID AsyncID) {
internalEventRecord(category, name, func(c *context, ticks ticksT, threadRef *threadRef, categoryRef, nameRef *stringRef) {
c.writeAsyncInstantEventRecord(ticks, threadRef, categoryRef, nameRef, asyncID, nil)
})
}
// AsyncEnd writes an asynchronous end event with the specified id.
func AsyncEnd(category, name string, asyncID AsyncID) {
internalEventRecord(category, name, func(c *context, ticks ticksT, threadRef *threadRef, categoryRef, nameRef *stringRef) {
c.writeAsyncEndEventRecord(ticks, threadRef, categoryRef, nameRef, asyncID, nil)
})
}
// FlowBegin writes a flow begin event with the specified id.
func FlowBegin(category, name string, flowID FlowID) {
internalEventRecord(category, name, func(c *context, ticks ticksT, threadRef *threadRef, categoryRef, nameRef *stringRef) {
c.writeFlowBeginEventRecord(ticks, threadRef, categoryRef, nameRef, flowID, nil)
})
}
// FlowStep writes a flow step event with the specified id.
func FlowStep(category, name string, flowID FlowID) {
internalEventRecord(category, name, func(c *context, ticks ticksT, threadRef *threadRef, categoryRef, nameRef *stringRef) {
c.writeFlowStepEventRecord(ticks, threadRef, categoryRef, nameRef, flowID, nil)
})
}
// FlowEnd writes a flow end event with the specified id.
func FlowEnd(category, name string, flowID FlowID) {
internalEventRecord(category, name, func(c *context, ticks ticksT, threadRef *threadRef, categoryRef, nameRef *stringRef) {
c.writeFlowEndEventRecord(ticks, threadRef, categoryRef, nameRef, flowID, nil)
})
}
// Blob writes a blob of binary data to the trace buffer.
func Blob(typ BlobType, name string, blob []byte) {
internalSimpleRecord(name, func(c *context, nameRef *stringRef) {
c.writeBlobRecord(typ, nameRef, blob)
})
}
func internalEventRecord(category, name string, f func(c *context, ticks ticksT, threadRef *threadRef, categoryRef, nameRef *stringRef)) {
c, ok := acquireContext()
if !ok {
return
}
defer releaseContext()
c.mu.Lock()
defer c.mu.Unlock()
categoryRef, enabled := c.registerStringLocked(category, true)
if !enabled {
return
}
nameRef, _ := c.registerStringLocked(name, false)
threadRef := c.registerCurrentThreadLocked()
ticks := ticksT(zx.Sys_ticks_get())
f(c, ticks, &threadRef, &categoryRef, &nameRef)
}
func internalSimpleRecord(name string, f func(c *context, nameRef *stringRef)) {
c, ok := acquireContext()
if !ok {
return
}
defer releaseContext()
c.mu.Lock()
defer c.mu.Unlock()
nameRef, _ := c.registerStringLocked(name, false)
f(c, &nameRef)
}