| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687 |
- package sessions
- import (
- "bytes"
- "encoding/json"
- "fmt"
- "net/http"
- "github.com/bugsnag/bugsnag-go/headers"
- )
- // sessionPayloadVersion defines the current version of the payload that's
- // being sent to the session server.
- const sessionPayloadVersion = "1.0"
- type sessionPublisher interface {
- publish(sessions []*Session) error
- }
- type httpClient interface {
- Do(*http.Request) (*http.Response, error)
- }
- type publisher struct {
- config *SessionTrackingConfiguration
- client httpClient
- }
- // publish builds a payload from the given sessions and publishes them to the
- // session server. Returns any errors that happened as part of publishing.
- func (p *publisher) publish(sessions []*Session) error {
- if p.config.Endpoint == "" {
- // Session tracking is disabled, likely because the notify endpoint was
- // changed without changing the sessions endpoint
- // We've already logged a warning in this case, so no need to spam the
- // log every minute
- return nil
- }
- if apiKey := p.config.APIKey; len(apiKey) != 32 {
- return fmt.Errorf("bugsnag/sessions/publisher.publish invalid API key: '%s'", apiKey)
- }
- nrs, rs := p.config.NotifyReleaseStages, p.config.ReleaseStage
- if rs != "" && (nrs != nil && !contains(nrs, rs)) {
- // Always send sessions if the release stage is not set, but don't send any
- // sessions when notify release stages don't match the current release stage
- return nil
- }
- if len(sessions) == 0 {
- return fmt.Errorf("bugsnag/sessions/publisher.publish requested publication of 0")
- }
- p.config.mutex.Lock()
- defer p.config.mutex.Unlock()
- payload := makeSessionPayload(sessions, p.config)
- buf, err := json.Marshal(payload)
- if err != nil {
- return fmt.Errorf("bugsnag/sessions/publisher.publish unable to marshal json: %v", err)
- }
- req, err := http.NewRequest("POST", p.config.Endpoint, bytes.NewBuffer(buf))
- if err != nil {
- return fmt.Errorf("bugsnag/sessions/publisher.publish unable to create request: %v", err)
- }
- for k, v := range headers.PrefixedHeaders(p.config.APIKey, sessionPayloadVersion) {
- req.Header.Add(k, v)
- }
- res, err := p.client.Do(req)
- if err != nil {
- return fmt.Errorf("bugsnag/sessions/publisher.publish unable to deliver session: %v", err)
- }
- defer func(res *http.Response) {
- if err := res.Body.Close(); err != nil {
- p.config.logf("%v", err)
- }
- }(res)
- if res.StatusCode != 202 {
- return fmt.Errorf("bugsnag/session.publish expected 202 response status, got HTTP %s", res.Status)
- }
- return nil
- }
- func contains(coll []string, e string) bool {
- for _, s := range coll {
- if s == e {
- return true
- }
- }
- return false
- }
|