@@ -4,21 +4,14 @@ import (
44 "bufio"
55 "bytes"
66 "context"
7- "crypto/sha256"
8- "encoding/hex"
97 "errors"
108 "fmt"
119 "io"
12- "io/ioutil"
1310 "log"
1411 "log/syslog"
1512 "os"
16- "strconv"
17- "strings"
18- "syscall"
1913 "time"
2014
21- "github.com/getsentry/sentry-go"
2215 "golang.org/x/sync/errgroup"
2316)
2417
@@ -70,7 +63,7 @@ func insertUUID(g GuardFunc) GuardFunc {
7063 if cr .ErrFileHideUUID {
7164 return g (ctx , cr )
7265 }
73- combined := newUUIDPrefixer (cr .Status .Combined )
66+ combined := newUUIDPrefixer (cr .Status .Combined )
7467 cr .Status .Combined = combined
7568 return g (ctx , cr )
7669 }
@@ -117,31 +110,16 @@ func headerize(g GuardFunc) GuardFunc {
117110func lockfile (g GuardFunc ) GuardFunc {
118111 return func (ctx context.Context , cr * CmdRequest ) (err error ) {
119112 if cr .Lockfile != "" {
120- _ , statErr := os .Stat (cr .Lockfile )
121- if statErr == nil {
122- pidBytes , err := ioutil .ReadFile (cr .Lockfile )
123- if err != nil {
124- return fmt .Errorf ("unable to read lockfile: %s" , err )
125- }
126- pid , err := strconv .Atoi (string (pidBytes ))
127- if err != nil {
128- return fmt .Errorf ("unable to read pidfile: %s" , err )
129- }
130- proc , err := os .FindProcess (pid )
131- if err != nil {
132- return fmt .Errorf ("process(%d) from pidfile missing: %s" , pid , err )
133- }
134- err = proc .Signal (syscall .Signal (0 ))
135- if err != nil {
136- return fmt .Errorf ("process(%d) from pidfile missing: %s" , pid , err )
137- }
138- _ , _ = fmt .Fprintf (cr .Status .Combined , "cron is still running, pid: %d" , pid )
113+ run , err := handleExistingLockfile (cr )
114+ if err != nil {
115+ return err
116+ }
117+ if ! run {
139118 return nil
140- } else if ! os .IsNotExist (statErr ) {
141- return fmt .Errorf ("unable to handle lockfile: %s" , statErr )
142119 }
120+
143121 pid := os .Getpid ()
144- lockfile , err := os .OpenFile (cr .Lockfile , os .O_CREATE | os .O_RDWR , 0600 )
122+ lockfile , err := os .OpenFile (cr .Lockfile , os .O_CREATE | os .O_TRUNC | os . O_RDWR , 0600 )
145123 if err != nil {
146124 return fmt .Errorf ("unable to open lockfile: %s" , err )
147125 }
@@ -157,80 +135,18 @@ func lockfile(g GuardFunc) GuardFunc {
157135 }
158136}
159137
138+ // sentryHandler redirects all errors to a sentry if configured
160139func sentryHandler (g GuardFunc ) GuardFunc {
161140 return func (ctx context.Context , cr * CmdRequest ) (err error ) {
162- // check if envar is set
163- sentryDSN , ok := os .LookupEnv ("CRONGUARD_SENTRY_DSN" )
164- if ! ok && cr .Config != nil {
165- sentryDSN = cr .Config .SentryDSN
166- }
167- if sentryDSN == "" {
141+ reporter , reporterErr := newReporter (cr )
142+ if reporterErr != nil {
168143 return g (ctx , cr )
169144 }
170145
171- // wrap buffers
172- start := time .Now ()
173- combined := bytes .NewBuffer ([]byte {})
174- stderr := bytes .NewBuffer ([]byte {})
175- cr .Status .Stderr = io .MultiWriter (stderr , combined , cr .Status .Stderr )
176- cr .Status .Stdout = io .MultiWriter (combined , cr .Status .Stdout )
177-
178- // prepare sentry
179- sentryErr := sentry .Init (sentry.ClientOptions {
180- Dsn : sentryDSN ,
181- Transport : sentry .NewHTTPSyncTransport (),
182- })
183- if sentryErr != nil {
184- fmt .Fprintf (cr .Status .Stderr , "cronguard: unable to connect to sentry: %s\n " , sentryErr )
185- fmt .Fprintf (cr .Status .Stderr , "cronguard: running cron anyways\n " )
186- }
187-
146+ cr .Reporter = reporter
188147 err = g (ctx , cr )
189-
190- // try to log to sentry
191- if err != nil && sentryErr == nil {
192- // gather data
193- hostname , _ := os .Hostname ()
194- if hostname == "" {
195- hostname = "no-hostname"
196- }
197- hostname = strings .SplitN (hostname , "." , 2 )[0 ]
198- cmd := cr .Command
199- if len (cmd ) > 32 {
200- cmd = fmt .Sprintf ("%s%s" , cmd [0 :30 ], "..." )
201- }
202- cmdHash := sha256 .New ()
203- cmdHash .Write ([]byte (cr .Command ))
204- cmdHash .Write ([]byte (hostname ))
205- hash := hex .EncodeToString (cmdHash .Sum (nil ))
206-
207- // add data to message
208- sentry .ConfigureScope (func (scope * sentry.Scope ) {
209- scope .SetExtra ("time_start" , start )
210- scope .SetExtra ("time_end" , time .Now ())
211- scope .SetExtra ("time_duration" , time .Since (start ).String ())
212- scope .SetExtra ("out_combined" , combined .String ())
213- scope .SetExtra ("out_stderr" , stderr .String ())
214- scope .SetExtra ("command" , cr .Command )
215- scope .SetFingerprint ([]string {hash })
216- })
217- name := fmt .Sprintf (
218- "%s: %s (%s)" ,
219- hostname ,
220- cmd ,
221- err .Error (),
222- )
223- _ = sentry .CaptureMessage (name )
224-
225- // hide error if messages are successfully flushed to sentry
226- flushed := sentry .Flush (30 * time .Second )
227- if flushed {
228- return nil
229- }
230- }
231- return err
148+ return reporter .Finish (err )
232149 }
233-
234150}
235151
236152// quietIgnore allows to ignore errors on lower settings if flag is set
0 commit comments