Skip to content

Commit

Permalink
Merge pull request #4 from pyroscope-io/windows-support
Browse files Browse the repository at this point in the history
Windows support
  • Loading branch information
kolesnikovae authored May 25, 2021
2 parents 27769c5 + 1a0bc21 commit c22867d
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 22 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# .Net diagnostics
# .NET diagnostics

The package provides means for .Net runtime diagnostics implemented in Golang:
- [Diagnostics IPC Protocol](https://github.com/dotnet/diagnostics/blob/main/documentation/design-docs/ipc-protocol.md#transport) client.
Expand All @@ -10,12 +10,12 @@ The package provides means for .Net runtime diagnostics implemented in Golang:
# go get github.com/pyroscope-io/dotnetdiag
```

Supported .Net versions:
- .Net 5.0
- .Net Core 3.1
Supported .NET versions:
- .NET 5.0
- .NET Core 3.1

Supported platforms:
- [ ] Windows
- [x] Windows
- [x] Linux
- [x] MacOS

Expand Down
36 changes: 31 additions & 5 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,28 @@ import (
)

// Client implement Diagnostic IPC Protocol client.
// https://github.com/dotnet/diagnostics/blob/main/documentation/design-docs/ipc-protocol.md#CollectStreaming
// https://github.com/dotnet/diagnostics/blob/main/documentation/design-docs/ipc-protocol.md
type Client struct {
addr string
dial Dialer
}

// Dialer establishes connection to the given address. Due to the potential for
// an optional continuation in the Diagnostics IPC Protocol, each successful
// connection between the runtime and a Diagnostic Port is only usable once.
//
// Note that the dialer is OS-specific, refer to documentation for details:
// https://github.com/dotnet/diagnostics/blob/main/documentation/design-docs/ipc-protocol.md#transport
type Dialer func(addr string) (net.Conn, error)

// Option overrides default Client parameters.
type Option func(*Client)

// WithDialer overrides default dialer function with d.
func WithDialer(d Dialer) Option {
return func(c *Client) {
c.dial = d
}
}

// Session represents EventPipe stream of NetTrace data created with
Expand Down Expand Up @@ -44,16 +63,23 @@ type CollectTracingConfig struct {
//
// Refer to documentation for details:
// https://github.com/dotnet/diagnostics/blob/main/documentation/design-docs/ipc-protocol.md#transport
func NewClient(addr string) *Client {
return &Client{addr: addr}
func NewClient(addr string, options ...Option) *Client {
c := &Client{addr: addr}
for _, option := range options {
option(c)
}
if c.dial == nil {
c.dial = DefaultDialer()
}
return c
}

// CollectTracing creates a new EventPipe session stream of NetTrace data.
func (c *Client) CollectTracing(config CollectTracingConfig) (s *Session, err error) {
// Every session has its own IPC connection which cannot be reused for any
// other purposes; in order to close the connection another connection
// to be opened - see `StopTracing`.
conn, err := dial(c.addr)
conn, err := c.dial(c.addr)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -89,7 +115,7 @@ func (c *Client) CollectTracing(config CollectTracingConfig) (s *Session, err er

// StopTracing stops the given streaming session started with CollectTracing.
func (c *Client) StopTracing(sessionID uint64) error {
conn, err := dial(c.addr)
conn, err := c.dial(c.addr)
if err != nil {
return err
}
Expand Down
22 changes: 13 additions & 9 deletions client_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,22 @@ import (
"sort"
)

func dial(addr string) (net.Conn, error) {
ua := &net.UnixAddr{
Name: addr,
Net: "unix",
func DefaultDialer() Dialer {
return func(addr string) (net.Conn, error) {
ua := &net.UnixAddr{
Name: addr,
Net: "unix",
}
conn, err := net.DialUnix("unix", nil, ua)
if err != nil {
return nil, err
}
return conn, nil
}
conn, err := net.DialUnix("unix", nil, ua)
if err != nil {
return nil, err
}
return conn, nil
}

// DefaultServerAddress returns Diagnostic Server unix domain socket path for the process given.
// https://github.com/dotnet/diagnostics/blob/main/documentation/design-docs/ipc-protocol.md#transport
func DefaultServerAddress(pid int) string {
paths, err := filepath.Glob(fmt.Sprintf("%s/dotnet-diagnostic-%d-*-socket", os.TempDir(), pid))
if err != nil || len(paths) == 0 {
Expand Down
20 changes: 20 additions & 0 deletions client_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package dotnetdiag

import (
"fmt"
"net"

"github.com/Microsoft/go-winio"
)

func DefaultDialer() Dialer {
return func(addr string) (net.Conn, error) {
return winio.DialPipe(addr, nil)
}
}

// DefaultServerAddress returns Diagnostic Server named pipe name for the process given.
// https://github.com/dotnet/diagnostics/blob/main/documentation/design-docs/ipc-protocol.md#transport
func DefaultServerAddress(pid int) string {
return fmt.Sprintf(`\\.\pipe\dotnet-diagnostic-%d`, pid)
}
5 changes: 4 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@ module github.com/pyroscope-io/dotnetdiag

go 1.16

require golang.org/x/text v0.3.6
require (
github.com/Microsoft/go-winio v0.5.0
golang.org/x/text v0.3.6
)
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
github.com/Microsoft/go-winio v0.5.0 h1:Elr9Wn+sGKPlkaBvwu4mTrxtmOp3F3yV9qhaHbXGjwU=
github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
4 changes: 2 additions & 2 deletions nettrace/profiler/profiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func (s *SampleProfiler) Samples() map[string]time.Duration {
for i := range x.stack {
name[i] = s.sym.resolve(x.stack[i])
}
samples[strings.Join(name, ";")] += time.Duration(x.value * -1)
samples[strings.Join(name, ";")] += -time.Millisecond * time.Duration(x.value)
}
return samples
}
Expand Down Expand Up @@ -172,7 +172,7 @@ func (s *SampleProfiler) addSample(e *nettrace.Blob) error {
threadID: e.Header.ThreadID,
stackID: e.Header.StackID,
timestamp: e.Header.TimeStamp,
relativeTime: e.Header.TimeStamp - s.trace.SyncTimeQPC,
relativeTime: (e.Header.TimeStamp - s.trace.SyncTimeQPC) * 1000 / s.trace.QPCFrequency,
})
return nil
}
Expand Down

0 comments on commit c22867d

Please sign in to comment.