Documentation ¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func NewUnregisteredFake ¶
func NewUnregisteredFake(namespace types.StreamName) (Fake, *Client)
NewUnregisteredFake returns a new Fake as well as a *Client for this Fake.
Fake.StreamServerPath() will return an empty string and Unregister is a no-op.
Aside from the returned *Client there's no way to obtain another *Client for this Fake.
func RenderOptions ¶
func RenderOptions(opts ...Option) (flags streamproto.Flags, forProcess bool)
RenderOptions is a helper function for tests and low-level code.
Returns the cumulative effect of a list of Options.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is a client to a local LogDog Butler.
The methods here allow you to open a stream (text, binary or datagram) which you can then use to send data to LogDog.
func New ¶
func New(path string, namespace types.StreamName) (*Client, error)
New instantiates a new Client instance. This type of instance will be parsed from the supplied path string, which takes the form:
<protocol>:<protocol-specific-spec>
Supported protocols ¶
Below is the list of all supported protocols:
unix:/path/to/socket (POSIX only)
Connects to a UNIX domain socket at "/path/to/socket". This is the preferred protocol for Linux/Mac.
net.pipe:name (Windows only)
Connects to a local Windows named pipe "\\.\pipe\name". This is the preferred protocol for Windows.
null (All platforms)
Sinks all connections and writes into a null data sink. Useful for tests, or for running programs which use logdog but you don't care about their logdog outputs.
fake:$id
Connects to an in-memory Fake created in this package by calling NewFake. The string `fake:$id` can be obtained by calling the Fake's StreamServerPath method.
func NewLoopback ¶
func NewLoopback(b butler, namespace types.StreamName) *Client
NewLoopback makes a loopback Client attached to a Butler instance.
The `butler` interface should be, exactly:
*"go.chromium.org/luci/logdog/client/butler".Butler
The interface is merely used for import cycle management.
NOTE: `ForProcess` will be a no-op for the created Client. If you intend to generate streams from this Client to attach to subprocesses, you would be better served by using New to create a real client.
func (*Client) GetNamespace ¶
func (c *Client) GetNamespace() types.StreamName
GetNamespace returns the LOGDOG_NAMESPACE value associated with this Client.
Safe to call on a nil client; will return an empty StreamName.
func (*Client) NewDatagramStream ¶
func (c *Client) NewDatagramStream(ctx context.Context, name types.StreamName, opts ...Option) (DatagramStream, error)
NewDatagramStream returns a new datagram stream to the butler.
Datagram streams allow you to send messages without having to demark the separation between messages.
NOTE: It is an error to pass ForProcess as an Option (see documentation on ForProcess for more detail).
func (*Client) NewStream ¶
func (c *Client) NewStream(ctx context.Context, name types.StreamName, opts ...Option) (io.WriteCloser, error)
NewStream returns a new open stream to the butler.
By default this is text-based (line-oriented); pass Binary for a binary stream.
Text streams look for newlines to delimit log chunks. Binary streams use fixed size chunks to delimit log chunks.
type DatagramStream ¶
type DatagramStream interface { io.Closer DatagramWriter }
DatagramStream is the interface for datagram oriented streams.
type DatagramWriter ¶
type DatagramWriter interface { // WriteDatagram writes `dg` as a single datagram. WriteDatagram(dg []byte) error }
DatagramWriter is the interface for writing datagrams.
You'll typically use DatagramStream instaed, but it's occasionally useful to separate this from io.Closer.
type Fake ¶
type Fake struct {
// contains filtered or unexported fields
}
Fake implements an in-memory sink for Client connections and data.
You can retrieve the collected data via the Data method.
func NewFake ¶
func NewFake() Fake
NewFake makes an in-memory Fake which absorbs all data written via Clients connected to it, and allows retrieval of this data via extra methods.
You must call Fake.Unregister to free the collected data.
You can obtain a Client for this Fake by doing:
fake := streamclient.NewFake() defer fake.Unregister() client, _ := streamclient.New(fake.StreamServerPath(), "whatever")
This is particularly useful for testing programs which use bootstrap.GetFromEnv() to obtain the Client:
env := environ.New(nil) env.Set(bootstrap.EnvStreamServerPath, client.StreamServerPath()) bs := bootstrap.GetFromEnv(env) # returns Bootstrap containing `client`.
If you JUST want a single client and don't need streamclient.New to work, consider NewUnregisteredFake.
func (Fake) Data ¶
func (f Fake) Data() map[types.StreamName]FakeStreamData
Data returns all absorbed data collected by this Fake so far.
Note that the FakeStreamData objects are `live`, and so calling their methods will always get you the current value of those streams. You'll need to call this method again if you expect a new stream to show up, however.
func (Fake) StreamServerPath ¶
StreamServerPath returns a value suitable for streamclient.New that will allow construction of a *Client which points to this Fake.
If this Fake was generated via NewUnregisteredFake, or you called Unregister on it, returns an empty string.
func (Fake) Unregister ¶
func (f Fake) Unregister()
Unregister idempotently removes this Fake from the global registry.
This has no effect for a Fake created with NewUnregisteredFake.
After calling Unregister, StreamServerPath will return an empty string.
type FakeStreamData ¶
type FakeStreamData interface { // GetFlags returns the stream's streamproto.Flags from when the stream was // opened. GetFlags() streamproto.Flags // GetStreamData returns the written text/binary data as a string. // // If this is a datagram stream, returns "". GetStreamData() string // GetDatagrams returns the written datagrams as a list of strings. // // If this is a text/binary stream, returns nil. GetDatagrams() []string // Returns true iff the user of the client has closed this stream. IsClosed() bool }
FakeStreamData is data about a single stream for a client created with the "fake" protocol. You can retrieve this with Fake.Data().
type Option ¶
type Option func(*options)
Option functions are returned by the With* functions in this package and can be passed to the Client.New*Stream methods to alter their contents during initial stream setup.
func Binary ¶
func Binary() Option
Binary can be used with NewStream to select a binary mode stream.
Using this with NewDatagramStream has no effect.
func ForProcess ¶
func ForProcess() Option
ForProcess is an Option which opens this stream optimized for subprocess IO (i.e. to attach to "os/exec".Cmd.Std{out,err}).
Accidentally passing a non-`ForProcess` stream to a subprocess will result in an extra pipe, and an extra goroutine with a copy loop in the parent process.
ForProcess is only allowed on Text and Binary streams, not datagram streams. This is because the datagram stream is "packet" oriented, but stdout/stderr are not. If an application knows enough about the butler protocol to properly frame its output, it should just open a butler connection directly, rather than emitting framed data on its standard outputs.
Note that when using a stream as a replacement for a process stdout/stderr handle, it must be used in the following manner (error checks omitted for brevity). The important thing to notice is that stdout must be Close'd after Wait (which could be accomplised by a defer). Failure to do this will keep the Stream open from the butler's point of view, which will prevent the butler from closing down.
stdout, _ = logdogServ.Client.NewStream( ..., streamclient.ForProcess()) cmd.Stdout = stdout cmd.Start() cmd.Wait() stdout.Close()
Using this has some caveats, depending on the underlying stream implementation:
Local ¶
Clients created with NewLocal ignore this option.
Fake ¶
Clients created with NewFake ignore this option.
Null ¶
The "null" protocol will return an open File pointing to os.DevNull.
Windows - NamedPipe ¶
This stream will be opened as a synchronous *os.File, and so will be suitable for os/exec's specific optimizations for this type (namely: it will be passed as a replacement HANDLE for stdout/stderr, and no extra pipe/goroutine will be allocated).
Accidentally using a `ForProcess` stream in the current process will result in go falling back to its internal IO threadpool to emulate asynchrony. Without `ForProcess`, the stream will use Windows-native OVERLAPPED IO completion ports, which allows the go process to be much more efficient with its thread count.
Mac and Linux - Unix Domain Sockets ¶
This stream will be dialed as a regular unix socket, but will be converted to an *os.File via `"net".UnixConn.File()`, and the original file handle ("Conn") closed.
Accidentally using a `ForProcess` stream in the current process isn't extremely harmful (because Go has a decent event-based IO system for *NIX systems).
func WithContentType ¶
WithContentType returns an Option to set the content type for a new stream.
The content type can be read by LogDog clients and may be used to indicate the type of data in this stream.
By default:
- Text streams have the type "text/plain"
- Binary streams have the type "application/octet-stream"
- Datagram streams have the type "application/x-logdog-datagram"
func WithTagMap ¶
WithTagMap allows you to add arbitrary tags to this stream (subject to the limits in `logdog/common/types.ValidateTag`).
By default, streams have no additional tags.
func WithTags ¶
WithTags allows you to add arbitrary tags to this stream (subject to the limits in `logdog/common/types.ValidateTag`). This is a convenience version of WithTagMap.
You must supply tags in pairs of {key, value}. Otherwise this function panics.
By default, streams have no additional tags.
func WithTimestamp ¶
WithTimestamp allows you to set the 'starting' timestamp for this stream.
Panics if given a timestamp that ptypes.TimestampProto cannot handle (no real timestamps will ever fall into this range).
By default the stream will be marked as starting at `clock.Now(ctx)`.