// Log sends data to the agent's global log. It works like log.Log func (j *Job) Log(v ...interface{}) { for _, val := range v { if j.errorChannel != nil { if v, ok := val.(string); ok { j.errorChannel <- gotelemetry.NewLogError("%s -> %s", j.ID, v) } else { j.errorChannel <- gotelemetry.NewLogError("%s -> %#v", j.ID, val) } } } }
func setupUDPListener(listen string, errorChannel chan error) { addr, err := net.ResolveUDPAddr("udp", listen) if err != nil { errorChannel <- err return } conn, err := net.ListenUDP("udp", addr) if err != nil { errorChannel <- err return } errorChannel <- gotelemetry.NewLogError("Graphite => Listening for UDP plaintext messages on %s", conn.LocalAddr()) buf := make([]byte, 2048) for { if n, addr, err := conn.ReadFromUDP(buf); err == nil { remoteAddress := addr.String() + ", UDP" if err := parseRequest(remoteAddress, string(buf[0:n]), errorChannel); err != nil { errorChannel <- gotelemetry.NewErrorWithFormat(400, "Graphite => [%s, UDP] Error %s while receving data", nil, addr, err) } } else { errorChannel <- gotelemetry.NewErrorWithFormat(400, "Graphite => [%s, UDP] Error %s while receving data", nil, addr, err) } } }
func ProcessNotificationRequest(configFile *config.ConfigFile, errorChannel chan error, completionChannel chan bool, notificationChannel string, notificationFlow string, notification gotelemetry.Notification) { errorChannel <- gotelemetry.NewLogError("Notification mode is on.") apiToken, err := configFile.APIToken() if err != nil { errorChannel <- err completionChannel <- true return } credentials, err := gotelemetry.NewCredentials(apiToken) if err != nil { errorChannel <- err completionChannel <- true return } credentials.SetDebugChannel(errorChannel) if len(notificationChannel) > 0 { channel := gotelemetry.NewChannel(notificationChannel) err = channel.SendNotification(credentials, notification) } else if len(notificationFlow) > 0 { err = gotelemetry.SendFlowChannelNotification(credentials, notificationFlow, notification) } else { err = gotelemetry.NewError(http.StatusBadRequest, "Either channel or flow is required") } if err != nil { errorChannel <- err } else { errorChannel <- gotelemetry.NewLogError("Notification sent successfully.") } completionChannel <- true }
func RunCommand(cfg config.CLIConfigType, errorChannel chan error, completionChannel chan bool) { client, err := clientForEntryWithName(cfg.OAuthName) if err != nil { errorChannel <- err return } switch cfg.OAuthCommand { case config.OAuthCommands.None: // Do nothing break case config.OAuthCommands.Request: url, err := client.GetAuthorizationURL() if err != nil { errorChannel <- err break } errorChannel <- gotelemetry.NewLogError("Please visit this URL and authorize the Agent:\n\n---\n%s\n---\n\n", url) errorChannel <- gotelemetry.NewLogError("When you are done, please run the agent with the oauth-exchange command to set the new token.\n\n") case config.OAuthCommands.Exchange: err := client.ExchangeToken(cfg.OAuthCode, cfg.OAuthVerifier, cfg.OAuthRealmID) if err != nil { errorChannel <- err break } errorChannel <- gotelemetry.NewLogError("Token exchanged successfully. The entry %s can now be used to make authenticated calls.", cfg.OAuthName) default: errorChannel <- fmt.Errorf("Unknown oauth command %s", cfg.OAuthCommand) } completionChannel <- true }
func parseCounterRequest(remoteAddress string, line []string, errorChannel chan error) error { counterName := line[0] valueString := line[1] isSetOperation := valueString[0] == '=' if isSetOperation { valueString = strings.TrimPrefix(valueString, "=") } value, err := strconv.ParseInt(valueString, 10, 64) if err != nil { return gotelemetry.NewErrorWithFormat( 400, "Graphite => [%s] Invalid value %s: %s", nil, remoteAddress, line[1], err.Error(), ) } counter, isCreated, err := aggregations.GetCounter(counterName) if isCreated { errorChannel <- gotelemetry.NewLogError("Graphite => Started receiving graphite data for '%s'", counterName) } if err != nil { return gotelemetry.NewErrorWithFormat( 500, "Graphite => [%s] Unable to get counter %s: %s", nil, remoteAddress, counterName, err.Error(), ) } if isSetOperation { counter.SetValue(value) } else { counter.Increment(value) } return nil }
func setupTCPListener(listen string, errorChannel chan error) { l, err := net.Listen("tcp", listen) if err != nil { errorChannel <- err return } defer l.Close() errorChannel <- gotelemetry.NewLogError("Graphite => Listening for TCP plaintext connections on %s", l.Addr()) for { conn, err := l.Accept() if err != nil { errorChannel <- err return } go handleTCPRequest(conn, errorChannel, true) } }
// Logf sends a formatted string to the agent's global log. It works like log.Logf func (m *Manager) Logf(format string, v ...interface{}) { if m.errorChannel != nil { m.errorChannel <- gotelemetry.NewLogError("Data Manager -> %#s", fmt.Sprintf(format, v...)) } }
func (c *Counter) debug(format string, data ...interface{}) { manager.errorChannel <- gotelemetry.NewLogError("Counter %s -> %s", c.Name, fmt.Sprintf(format, data...)) }
func ProcessPipeRequest(configFile *config.ConfigFile, errorChannel chan error, completionChannel chan bool, data []byte) { errorChannel <- gotelemetry.NewLogError("Piped mode is on.") errorChannel <- gotelemetry.NewDebugError("Input data is %s", strings.Replace(string(data), "\n", "\\n", -1)) submissionType := gotelemetry.BatchTypePATCH if config.CLIConfig.UseJSONPatch { errorChannel <- gotelemetry.NewDebugError("Will perform a JSON-Patch operation") submissionType = gotelemetry.BatchTypeJSONPATCH } else if config.CLIConfig.UsePOST { errorChannel <- gotelemetry.NewDebugError("Will perform a POST operation") submissionType = gotelemetry.BatchTypePOST } else { errorChannel <- gotelemetry.NewDebugError("Will perform a Rails-style HTTP PATCH operation") } apiToken, err := configFile.APIToken() if err != nil { errorChannel <- err completionChannel <- true return } credentials, err := gotelemetry.NewCredentials(apiToken, configFile.APIURL()) if err != nil { errorChannel <- err completionChannel <- true return } credentials.SetDebugChannel(errorChannel) updates := map[string]interface{}{} err = json.Unmarshal(data, &updates) if err != nil { errorChannel <- err completionChannel <- true return } b := gotelemetry.Batch{} for tag, update := range updates { b.SetData(tag, update) } err = b.Publish(credentials, configFile.ChannelTag(), submissionType) if err != nil { errorChannel <- err } errorChannel <- gotelemetry.NewLogError("Processing complete. Exiting.") completionChannel <- true }
func parseTraditionalRequest(remoteAddress string, line []string, errorChannel chan error) error { seriesName := line[0] value, err := strconv.ParseFloat(line[1], 64) if err != nil { return gotelemetry.NewErrorWithFormat( 400, "Graphite => [%s] Invalid value %s: %s", nil, remoteAddress, line[1], err.Error(), ) } timestamp, err := strconv.ParseInt(line[2], 10, 64) if err != nil { return gotelemetry.NewErrorWithFormat( 400, "Graphite => [%s] Invalid timestamp %s: %s", nil, remoteAddress, line[2], err.Error(), ) } series, isCreated, err := aggregations.GetSeries(seriesName) if err != nil { return gotelemetry.NewErrorWithFormat( 500, "Graphite => [%s] Unable to get series %s: %s", nil, remoteAddress, seriesName, err.Error(), ) } if isCreated { errorChannel <- gotelemetry.NewLogError("Graphite => Started receiving graphite data for '%s'", seriesName) } ts := time.Unix(timestamp, 0) if err := series.Push(&ts, value); err != nil { return gotelemetry.NewErrorWithFormat( 500, "Graphite => [%s] Unable to push value %f with timestamp %s to series %s: %s", nil, remoteAddress, value, ts, seriesName, err.Error(), ) } errorChannel <- gotelemetry.NewDebugError( "Graphite => [%s] Pushed value %f to series %s at time %s", remoteAddress, value, seriesName, ts, ) return nil }
// Logf sends a formatted string to the agent's global log. It works like log.Logf func (j *Job) Logf(format string, v ...interface{}) { if j.errorChannel != nil { j.errorChannel <- gotelemetry.NewLogError("%s -> %#s", j.ID, fmt.Sprintf(format, v...)) } }
func NewJobManager(jobConfig config.ConfigInterface, errorChannel chan error, completionChannel chan bool) (*JobManager, error) { result := &JobManager{ jobs: map[string]*Job{}, completionChannel: completionChannel, jobCompletionChannel: make(chan string), } apiToken, err := jobConfig.APIToken() if err != nil { return nil, err } credentials, err := gotelemetry.NewCredentials(apiToken, jobConfig.APIURL()) if err != nil { return nil, err } credentials.SetDebugChannel(errorChannel) result.credentials = credentials submissionInterval := jobConfig.SubmissionInterval() if submissionInterval < time.Second { errorChannel <- gotelemetry.NewLogError("Submission interval automatically set to 1s. You can change this value by adding a `submission_interval` property to your configuration file.") submissionInterval = time.Second } else { errorChannel <- gotelemetry.NewLogError("Submission interval set to %ds", submissionInterval/time.Second) } result.accountStreams = map[string]*gotelemetry.BatchStream{} for _, jobDescription := range jobConfig.Jobs() { jobId := jobDescription.ID() if jobId == "" { return nil, gotelemetry.NewError(500, "Job ID missing and no `flow_tag` provided.") } if !config.CLIConfig.Filter.MatchString(jobId) { continue } if config.CLIConfig.ForceRunOnce { delete(jobDescription, "refresh") } channelTag := jobDescription.ChannelTag() accountStream, ok := result.accountStreams[channelTag] if !ok { var err error accountStream, err = gotelemetry.NewBatchStream(credentials, channelTag, submissionInterval, errorChannel) if err != nil { return nil, err } result.accountStreams[channelTag] = accountStream } job, err := createJob(result, credentials, accountStream, errorChannel, jobDescription, result.jobCompletionChannel, false) if err != nil { return nil, err } if err := result.addJob(job); err != nil { return nil, err } } if len(result.jobs) == 0 { errorChannel <- gotelemetry.NewLogError("No jobs are being scheduled.") return nil, nil } go result.monitorDoneChannel() return result, nil }