Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to search by --ray-id #30

Merged
merged 5 commits into from Feb 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 9 additions & 3 deletions cmd/logshare-cli/main.go
Expand Up @@ -98,7 +98,6 @@ func run(conf *config) func(c *cli.Context) error {
&logshare.Options{
Fields: conf.fields,
Dest: outputWriter,
ByReceived: true,
Sample: conf.sample,
TimestampFormat: conf.timestampFormat,
})
Expand All @@ -110,7 +109,13 @@ func run(conf *config) func(c *cli.Context) error {
// endpoint.
var meta *logshare.Meta

if conf.listFields {
if conf.rayID != "" {
meta, err = client.GetFromRayID(conf.zoneID, conf.rayID)
if err != nil {
return errors.Wrap(err, "failed to fetch via ray ID")
}

} else if conf.listFields {
meta, err = client.FetchFieldNames(conf.zoneID)
if err != nil {
return errors.Wrap(err, "failed to fetch field names")
Expand Down Expand Up @@ -146,6 +151,7 @@ func parseFlags(conf *config, c *cli.Context) error {
conf.googleStorageBucket = c.String("google-storage-bucket")
conf.googleProjectID = c.String("google-project-id")
conf.skipCreateBucket = c.Bool("skip-create-bucket")
conf.rayID = c.String("ray-id")

return conf.Validate()
}
Expand All @@ -165,10 +171,10 @@ type config struct {
googleStorageBucket string
googleProjectID string
skipCreateBucket bool
rayID string
}

func (conf *config) Validate() error {

if conf.apiKey == "" || conf.apiEmail == "" {
return errors.New("Must provide both api-key and api-email")
}
Expand Down
58 changes: 34 additions & 24 deletions logshare.go
Expand Up @@ -8,6 +8,7 @@ import (
"net/http"
"net/url"
"os"
"path"
"strconv"
"strings"
"time"
Expand All @@ -17,14 +18,11 @@ import (

const (
apiURL = "https://api.cloudflare.com/client/v4"
byRequest = "requests"
unix = "unix"
unixNano = "unixnano"
rfc3339 = "rfc3339"
byReceived = "received"
)

const (
unix = "unix"
unixNano = "unixnano"
rfc3339 = "rfc3339"
byRayID = "rayids"
)

// Client holds the current API credentials & HTTP client configuration. Client
Expand All @@ -33,7 +31,6 @@ type Client struct {
endpoint string
apiKey string
apiEmail string
byReceived bool
sample float64
timestampFormat string
fields []string
Expand All @@ -50,8 +47,6 @@ type Options struct {
Headers http.Header
// Destination to stream logs to.
Dest io.Writer
// Fetch logs by the processing/received timestamp
ByReceived bool
// Which timestamp format to use: one of "unix", "unixnano", "rfc3339"
TimestampFormat string
// Whether to only retrieve a sample of logs (0.001 to 1)
Expand Down Expand Up @@ -81,20 +76,13 @@ func New(apiKey string, apiEmail string, options *Options) (*Client, error) {
return nil, errors.New("apiEmail cannot be empty")
}

// Default to the received endpoint.
var byReceived = true
if options != nil {
byReceived = options.ByReceived
}

client := &Client{
apiKey: apiKey,
apiEmail: apiEmail,
endpoint: apiURL,
httpClient: http.DefaultClient,
dest: os.Stdout,
headers: make(http.Header),
byReceived: byReceived,
}

if options != nil {
Expand All @@ -114,27 +102,34 @@ func New(apiKey string, apiEmail string, options *Options) (*Client, error) {
}

func (c *Client) buildURL(zoneID string, params url.Values) (*url.URL, error) {
endpoint := byReceived
if !c.byReceived {
endpoint = byRequest
endpointType := byReceived

rayID := params.Get("rayid")
if rayID != "" {
endpointType = byRayID
params.Del("rayid")
}

u, err := url.Parse(
fmt.Sprintf("%s/zones/%s/logs/%s",
c.endpoint,
zoneID,
endpoint,
endpointType,
),
)
if err != nil {
return nil, err
}

if c.byReceived && len(c.fields) >= 1 {
if endpointType == byRayID {
u.Path = path.Join(u.Path, rayID)
}

if len(c.fields) >= 1 {
params.Set("fields", strings.Join(c.fields, ","))
}

if c.sample != 0.0 {
if endpointType != byRayID && c.sample != 0.0 {
params.Set("sample", strconv.FormatFloat(c.sample, 'f', 3, 64))
}

Expand All @@ -143,9 +138,23 @@ func (c *Client) buildURL(zoneID string, params url.Values) (*url.URL, error) {
}

u.RawQuery = params.Encode()

return u, nil
}

// GetFromRayID fetches a log entry based on a provided Ray ID value.
func (c *Client) GetFromRayID(zoneID string, rayID string) (*Meta, error) {
params := url.Values{}
params.Set("rayid", rayID)

url, err := c.buildURL(zoneID, params)
if err != nil {
return nil, err
}

return c.request(url)
}

// GetFromTimestamp fetches logs between the start and end timestamps provided,
// (up to 'count' logs).
func (c *Client) GetFromTimestamp(zoneID string, start int64, end int64, count int) (*Meta, error) {
Expand All @@ -172,9 +181,10 @@ func (c *Client) GetFromTimestamp(zoneID string, start int64, end int64, count i
func (c *Client) FetchFieldNames(zoneID string) (*Meta, error) {
u, err := url.Parse(
fmt.Sprintf(
"%s/zones/%s/logs/received/fields",
"%s/zones/%s/logs/%s/fields",
c.endpoint,
zoneID,
byReceived,
),
)
if err != nil {
Expand Down