github.com/lulzWill/go-agent@v2.1.2+incompatible/internal/harvest.go (about) 1 package internal 2 3 import ( 4 "strings" 5 "sync" 6 "time" 7 ) 8 9 // Harvestable is something that can be merged into a Harvest. 10 type Harvestable interface { 11 MergeIntoHarvest(h *Harvest) 12 } 13 14 // Harvest contains collected data. 15 type Harvest struct { 16 Metrics *metricTable 17 CustomEvents *customEvents 18 TxnEvents *txnEvents 19 ErrorEvents *errorEvents 20 ErrorTraces harvestErrors 21 TxnTraces *harvestTraces 22 SlowSQLs *slowQueries 23 } 24 25 // Payloads returns a map from expected collector method name to data type. 26 func (h *Harvest) Payloads() map[string]PayloadCreator { 27 return map[string]PayloadCreator{ 28 cmdMetrics: h.Metrics, 29 cmdCustomEvents: h.CustomEvents, 30 cmdTxnEvents: h.TxnEvents, 31 cmdErrorEvents: h.ErrorEvents, 32 cmdErrorData: h.ErrorTraces, 33 cmdTxnTraces: h.TxnTraces, 34 cmdSlowSQLs: h.SlowSQLs, 35 } 36 } 37 38 // NewHarvest returns a new Harvest. 39 func NewHarvest(now time.Time) *Harvest { 40 return &Harvest{ 41 Metrics: newMetricTable(maxMetrics, now), 42 CustomEvents: newCustomEvents(maxCustomEvents), 43 TxnEvents: newTxnEvents(maxTxnEvents), 44 ErrorEvents: newErrorEvents(maxErrorEvents), 45 ErrorTraces: newHarvestErrors(maxHarvestErrors), 46 TxnTraces: newHarvestTraces(), 47 SlowSQLs: newSlowQueries(maxHarvestSlowSQLs), 48 } 49 } 50 51 var ( 52 trackMutex sync.Mutex 53 trackMetrics []string 54 ) 55 56 // TrackUsage helps track which integration packages are used. 57 func TrackUsage(s ...string) { 58 trackMutex.Lock() 59 defer trackMutex.Unlock() 60 61 m := "Supportability/" + strings.Join(s, "/") 62 trackMetrics = append(trackMetrics, m) 63 } 64 65 func createTrackUsageMetrics(metrics *metricTable) { 66 trackMutex.Lock() 67 defer trackMutex.Unlock() 68 69 for _, m := range trackMetrics { 70 metrics.addSingleCount(m, forced) 71 } 72 } 73 74 // CreateFinalMetrics creates extra metrics at harvest time. 75 func (h *Harvest) CreateFinalMetrics() { 76 h.Metrics.addSingleCount(instanceReporting, forced) 77 78 h.Metrics.addCount(customEventsSeen, h.CustomEvents.numSeen(), forced) 79 h.Metrics.addCount(customEventsSent, h.CustomEvents.numSaved(), forced) 80 81 h.Metrics.addCount(txnEventsSeen, h.TxnEvents.numSeen(), forced) 82 h.Metrics.addCount(txnEventsSent, h.TxnEvents.numSaved(), forced) 83 84 h.Metrics.addCount(errorEventsSeen, h.ErrorEvents.numSeen(), forced) 85 h.Metrics.addCount(errorEventsSent, h.ErrorEvents.numSaved(), forced) 86 87 if h.Metrics.numDropped > 0 { 88 h.Metrics.addCount(supportabilityDropped, float64(h.Metrics.numDropped), forced) 89 } 90 91 createTrackUsageMetrics(h.Metrics) 92 } 93 94 // PayloadCreator is a data type in the harvest. 95 type PayloadCreator interface { 96 // In the event of a rpm request failure (hopefully simply an 97 // intermittent collector issue) the payload may be merged into the next 98 // time period's harvest. 99 Harvestable 100 // Data prepares JSON in the format expected by the collector endpoint. 101 // This method should return (nil, nil) if the payload is empty and no 102 // rpm request is necessary. 103 Data(agentRunID string, harvestStart time.Time) ([]byte, error) 104 } 105 106 // CreateTxnMetrics creates metrics for a transaction. 107 func CreateTxnMetrics(args *TxnData, metrics *metricTable) { 108 // Duration Metrics 109 rollup := backgroundRollup 110 if args.IsWeb { 111 rollup = webRollup 112 metrics.addDuration(dispatcherMetric, "", args.Duration, 0, forced) 113 } 114 115 metrics.addDuration(args.FinalName, "", args.Duration, args.Exclusive, forced) 116 metrics.addDuration(rollup, "", args.Duration, args.Exclusive, forced) 117 118 // Apdex Metrics 119 if args.Zone != ApdexNone { 120 metrics.addApdex(apdexRollup, "", args.ApdexThreshold, args.Zone, forced) 121 122 mname := apdexPrefix + removeFirstSegment(args.FinalName) 123 metrics.addApdex(mname, "", args.ApdexThreshold, args.Zone, unforced) 124 } 125 126 // Error Metrics 127 if args.HasErrors() { 128 metrics.addSingleCount(errorsRollupMetric.all, forced) 129 metrics.addSingleCount(errorsRollupMetric.webOrOther(args.IsWeb), forced) 130 metrics.addSingleCount(errorsPrefix+args.FinalName, forced) 131 } 132 133 // Queueing Metrics 134 if args.Queuing > 0 { 135 metrics.addDuration(queueMetric, "", args.Queuing, args.Queuing, forced) 136 } 137 }