streamclient

package
v0.0.0-...-ef45db5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 19, 2024 License: Apache-2.0 Imports: 17 Imported by: 15

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) SetError

func (f Fake) SetError(err error)

SetError causes New* methods for Clients of this Fake to return this error.

func (Fake) StreamServerPath

func (f Fake) StreamServerPath() string

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

func WithContentType(contentType string) Option

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

func WithTagMap(tags map[string]string) Option

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

func WithTags(keyValues ...string) Option

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

func WithTimestamp(stamp time.Time) Option

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)`.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL