Create init method on provider interface
This commit is contained in:
parent
b2a57ca1f3
commit
027093a5a5
52 changed files with 2760 additions and 131 deletions
22
vendor/github.com/Microsoft/ApplicationInsights-Go/LICENSE
generated
vendored
Normal file
22
vendor/github.com/Microsoft/ApplicationInsights-Go/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015-2017 Microsoft
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
122
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/bond.go
generated
vendored
Normal file
122
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/bond.go
generated
vendored
Normal file
|
@ -0,0 +1,122 @@
|
|||
package appinsights
|
||||
|
||||
type Domain interface {
|
||||
}
|
||||
|
||||
type domain struct {
|
||||
Ver int `json:"ver"`
|
||||
Properties map[string]string `json:"properties"`
|
||||
}
|
||||
|
||||
type data struct {
|
||||
BaseType string `json:"baseType"`
|
||||
BaseData Domain `json:"baseData"`
|
||||
}
|
||||
|
||||
type envelope struct {
|
||||
Name string `json:"name"`
|
||||
Time string `json:"time"`
|
||||
IKey string `json:"iKey"`
|
||||
Tags map[string]string `json:"tags"`
|
||||
Data *data `json:"data"`
|
||||
}
|
||||
|
||||
type DataPointType int
|
||||
|
||||
const (
|
||||
Measurement DataPointType = iota
|
||||
Aggregation
|
||||
)
|
||||
|
||||
type DataPoint struct {
|
||||
Name string `json:"name"`
|
||||
Kind DataPointType `json:"kind"`
|
||||
Value float32 `json:"value"`
|
||||
Count int `json:"count"`
|
||||
min float32 `json:"min"`
|
||||
max float32 `json:"max"`
|
||||
stdDev float32 `json:"stdDev"`
|
||||
}
|
||||
|
||||
type metricData struct {
|
||||
domain
|
||||
Metrics []*DataPoint `json:"metrics"`
|
||||
}
|
||||
|
||||
type eventData struct {
|
||||
domain
|
||||
Name string `json:"name"`
|
||||
Measurements map[string]float32 `json:"measurements"`
|
||||
}
|
||||
|
||||
type SeverityLevel int
|
||||
|
||||
const (
|
||||
Verbose SeverityLevel = iota
|
||||
Information
|
||||
Warning
|
||||
Error
|
||||
Critical
|
||||
)
|
||||
|
||||
type messageData struct {
|
||||
domain
|
||||
Message string `json:"message"`
|
||||
SeverityLevel SeverityLevel `json:"severityLevel"`
|
||||
}
|
||||
|
||||
type requestData struct {
|
||||
domain
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
StartTime string `json:"startTime"` // yyyy-mm-ddThh:mm:ss.fffffff-hh:mm
|
||||
Duration string `json:"duration"` // d:hh:mm:ss.fffffff
|
||||
ResponseCode string `json:"responseCode"`
|
||||
Success bool `json:"success"`
|
||||
HttpMethod string `json:"httpMethod"`
|
||||
Url string `json:"url"`
|
||||
Measurements map[string]float32 `json:"measurements"`
|
||||
}
|
||||
|
||||
type ContextTagKeys string
|
||||
|
||||
const (
|
||||
ApplicationVersion ContextTagKeys = "ai.application.ver"
|
||||
ApplicationBuild = "ai.application.build"
|
||||
CloudRole = "ai.cloud.role"
|
||||
CloudRoleInstance = "ai.cloud.roleInstance"
|
||||
DeviceId = "ai.device.id"
|
||||
DeviceIp = "ai.device.ip"
|
||||
DeviceLanguage = "ai.device.language"
|
||||
DeviceLocale = "ai.device.locale"
|
||||
DeviceModel = "ai.device.model"
|
||||
DeviceNetwork = "ai.device.network"
|
||||
DeviceOEMName = "ai.device.oemName"
|
||||
DeviceOS = "ai.device.os"
|
||||
DeviceOSVersion = "ai.device.osVersion"
|
||||
DeviceRoleInstance = "ai.device.roleInstance"
|
||||
DeviceRoleName = "ai.device.roleName"
|
||||
DeviceScreenResolution = "ai.device.screenResolution"
|
||||
DeviceType = "ai.device.type"
|
||||
DeviceMachineName = "ai.device.machineName"
|
||||
LocationIp = "ai.location.ip"
|
||||
OperationCorrelationVector = "ai.operation.correlationVector"
|
||||
OperationId = "ai.operation.id"
|
||||
OperationName = "ai.operation.name"
|
||||
OperationParentId = "ai.operation.parentId"
|
||||
OperationRootId = "ai.operation.rootId"
|
||||
OperationSyntheticSource = "ai.operation.syntheticSource"
|
||||
OperationIsSynthetic = "ai.operation.isSynthetic"
|
||||
SessionId = "ai.session.id"
|
||||
SessionIsFirst = "ai.session.isFirst"
|
||||
SessionIsNew = "ai.session.isNew"
|
||||
UserAccountAcquisitionDate = "ai.user.accountAcquisitionDate"
|
||||
UserAccountId = "ai.user.accountId"
|
||||
UserAgent = "ai.user.userAgent"
|
||||
UserAuthUserId = "ai.user.authUserId"
|
||||
UserId = "ai.user.id"
|
||||
UserStoreRegion = "ai.user.storeRegion"
|
||||
SampleRate = "ai.sample.sampleRate"
|
||||
InternalSdkVersion = "ai.internal.sdkVersion"
|
||||
InternalAgentVersion = "ai.internal.agentVersion"
|
||||
)
|
132
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/client.go
generated
vendored
Normal file
132
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/client.go
generated
vendored
Normal file
|
@ -0,0 +1,132 @@
|
|||
package appinsights
|
||||
|
||||
import "time"
|
||||
|
||||
type TelemetryClient interface {
|
||||
Context() TelemetryContext
|
||||
InstrumentationKey() string
|
||||
Channel() TelemetryChannel
|
||||
IsEnabled() bool
|
||||
SetIsEnabled(bool)
|
||||
Track(Telemetry)
|
||||
TrackEvent(string)
|
||||
TrackEventTelemetry(*EventTelemetry)
|
||||
TrackMetric(string, float32)
|
||||
TrackMetricTelemetry(*MetricTelemetry)
|
||||
TrackTrace(string)
|
||||
TrackTraceTelemetry(*TraceTelemetry)
|
||||
TrackRequest(string, string, string, time.Time, time.Duration, string, bool)
|
||||
TrackRequestTelemetry(*RequestTelemetry)
|
||||
}
|
||||
|
||||
type telemetryClient struct {
|
||||
TelemetryConfiguration *TelemetryConfiguration
|
||||
channel TelemetryChannel
|
||||
context TelemetryContext
|
||||
isEnabled bool
|
||||
}
|
||||
|
||||
func NewTelemetryClient(iKey string) TelemetryClient {
|
||||
return NewTelemetryClientFromConfig(NewTelemetryConfiguration(iKey))
|
||||
}
|
||||
|
||||
func NewTelemetryClientFromConfig(config *TelemetryConfiguration) TelemetryClient {
|
||||
channel := NewInMemoryChannel(config)
|
||||
context := NewClientTelemetryContext()
|
||||
return &telemetryClient{
|
||||
TelemetryConfiguration: config,
|
||||
channel: channel,
|
||||
context: context,
|
||||
isEnabled: true,
|
||||
}
|
||||
}
|
||||
|
||||
func (tc *telemetryClient) Context() TelemetryContext {
|
||||
return tc.context
|
||||
}
|
||||
|
||||
func (tc *telemetryClient) Channel() TelemetryChannel {
|
||||
return tc.channel
|
||||
}
|
||||
|
||||
func (tc *telemetryClient) InstrumentationKey() string {
|
||||
return tc.TelemetryConfiguration.InstrumentationKey
|
||||
}
|
||||
|
||||
func (tc *telemetryClient) IsEnabled() bool {
|
||||
return tc.isEnabled
|
||||
}
|
||||
|
||||
func (tc *telemetryClient) SetIsEnabled(isEnabled bool) {
|
||||
tc.isEnabled = isEnabled
|
||||
}
|
||||
|
||||
func (tc *telemetryClient) Track(item Telemetry) {
|
||||
if tc.isEnabled {
|
||||
iKey := tc.context.InstrumentationKey()
|
||||
if len(iKey) == 0 {
|
||||
iKey = tc.TelemetryConfiguration.InstrumentationKey
|
||||
}
|
||||
|
||||
itemContext := item.Context().(*telemetryContext)
|
||||
itemContext.iKey = iKey
|
||||
|
||||
clientContext := tc.context.(*telemetryContext)
|
||||
|
||||
for tagkey, tagval := range clientContext.tags {
|
||||
if itemContext.tags[tagkey] == "" {
|
||||
itemContext.tags[tagkey] = tagval
|
||||
}
|
||||
}
|
||||
|
||||
tc.channel.Send(item)
|
||||
}
|
||||
}
|
||||
|
||||
func (tc *telemetryClient) TrackEvent(name string) {
|
||||
item := NewEventTelemetry(name)
|
||||
tc.TrackEventTelemetry(item)
|
||||
}
|
||||
|
||||
func (tc *telemetryClient) TrackEventTelemetry(event *EventTelemetry) {
|
||||
var item Telemetry
|
||||
item = event
|
||||
|
||||
tc.Track(item)
|
||||
}
|
||||
|
||||
func (tc *telemetryClient) TrackMetric(name string, value float32) {
|
||||
item := NewMetricTelemetry(name, value)
|
||||
tc.TrackMetricTelemetry(item)
|
||||
}
|
||||
|
||||
func (tc *telemetryClient) TrackMetricTelemetry(metric *MetricTelemetry) {
|
||||
var item Telemetry
|
||||
item = metric
|
||||
|
||||
tc.Track(item)
|
||||
}
|
||||
|
||||
func (tc *telemetryClient) TrackTrace(message string) {
|
||||
item := NewTraceTelemetry(message, Information)
|
||||
tc.TrackTraceTelemetry(item)
|
||||
}
|
||||
|
||||
func (tc *telemetryClient) TrackTraceTelemetry(trace *TraceTelemetry) {
|
||||
var item Telemetry
|
||||
item = trace
|
||||
|
||||
tc.Track(item)
|
||||
}
|
||||
|
||||
func (tc *telemetryClient) TrackRequest(name, method, url string, timestamp time.Time, duration time.Duration, responseCode string, success bool) {
|
||||
item := NewRequestTelemetry(name, method, url, timestamp, duration, responseCode, success)
|
||||
tc.TrackRequestTelemetry(item)
|
||||
}
|
||||
|
||||
func (tc *telemetryClient) TrackRequestTelemetry(request *RequestTelemetry) {
|
||||
var item Telemetry
|
||||
item = request
|
||||
|
||||
tc.Track(item)
|
||||
}
|
11
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/clock.go
generated
vendored
Normal file
11
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/clock.go
generated
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
package appinsights
|
||||
|
||||
// We need to mock out the clock for tests; we'll use this to do it.
|
||||
|
||||
import "code.cloudfoundry.org/clock"
|
||||
|
||||
var currentClock clock.Clock
|
||||
|
||||
func init() {
|
||||
currentClock = clock.NewClock()
|
||||
}
|
45
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/concurrentrandom.go
generated
vendored
Normal file
45
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/concurrentrandom.go
generated
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
package appinsights
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"math/rand"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type concurrentRandom struct {
|
||||
channel chan string
|
||||
random *rand.Rand
|
||||
}
|
||||
|
||||
var randomGenerator *concurrentRandom
|
||||
|
||||
func newConcurrentRandom() *concurrentRandom {
|
||||
source := rand.NewSource(time.Now().UnixNano())
|
||||
return &concurrentRandom{
|
||||
channel: make(chan string, 4),
|
||||
random: rand.New(source),
|
||||
}
|
||||
}
|
||||
|
||||
func (generator *concurrentRandom) run() {
|
||||
buf := make([]byte, 8)
|
||||
for {
|
||||
generator.random.Read(buf)
|
||||
generator.channel <- base64.StdEncoding.EncodeToString(buf)
|
||||
}
|
||||
}
|
||||
|
||||
func randomId() string {
|
||||
if randomGenerator == nil {
|
||||
r := newConcurrentRandom()
|
||||
if atomic.CompareAndSwapPointer((*unsafe.Pointer)(unsafe.Pointer(&randomGenerator)), unsafe.Pointer(nil), unsafe.Pointer(r)) {
|
||||
go r.run()
|
||||
} else {
|
||||
close(r.channel)
|
||||
}
|
||||
}
|
||||
|
||||
return <-randomGenerator.channel
|
||||
}
|
19
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/configuration.go
generated
vendored
Normal file
19
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/configuration.go
generated
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
package appinsights
|
||||
|
||||
import "time"
|
||||
|
||||
type TelemetryConfiguration struct {
|
||||
InstrumentationKey string
|
||||
EndpointUrl string
|
||||
MaxBatchSize int
|
||||
MaxBatchInterval time.Duration
|
||||
}
|
||||
|
||||
func NewTelemetryConfiguration(instrumentationKey string) *TelemetryConfiguration {
|
||||
return &TelemetryConfiguration{
|
||||
InstrumentationKey: instrumentationKey,
|
||||
EndpointUrl: "https://dc.services.visualstudio.com/v2/track",
|
||||
MaxBatchSize: 1024,
|
||||
MaxBatchInterval: time.Duration(10) * time.Second,
|
||||
}
|
||||
}
|
228
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/datacontracts.go
generated
vendored
Normal file
228
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/datacontracts.go
generated
vendored
Normal file
|
@ -0,0 +1,228 @@
|
|||
package appinsights
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Telemetry interface {
|
||||
Timestamp() time.Time
|
||||
Context() TelemetryContext
|
||||
baseTypeName() string
|
||||
baseData() Domain
|
||||
SetProperty(string, string)
|
||||
}
|
||||
|
||||
type BaseTelemetry struct {
|
||||
timestamp time.Time
|
||||
context TelemetryContext
|
||||
}
|
||||
|
||||
type TraceTelemetry struct {
|
||||
BaseTelemetry
|
||||
data *messageData
|
||||
}
|
||||
|
||||
func NewTraceTelemetry(message string, severityLevel SeverityLevel) *TraceTelemetry {
|
||||
now := time.Now()
|
||||
data := &messageData{
|
||||
Message: message,
|
||||
SeverityLevel: severityLevel,
|
||||
}
|
||||
|
||||
data.Ver = 2
|
||||
|
||||
item := &TraceTelemetry{
|
||||
data: data,
|
||||
}
|
||||
|
||||
item.timestamp = now
|
||||
item.context = NewItemTelemetryContext()
|
||||
|
||||
return item
|
||||
}
|
||||
|
||||
func (item *TraceTelemetry) Timestamp() time.Time {
|
||||
return item.timestamp
|
||||
}
|
||||
|
||||
func (item *TraceTelemetry) Context() TelemetryContext {
|
||||
return item.context
|
||||
}
|
||||
|
||||
func (item *TraceTelemetry) baseTypeName() string {
|
||||
return "Message"
|
||||
}
|
||||
|
||||
func (item *TraceTelemetry) baseData() Domain {
|
||||
return item.data
|
||||
}
|
||||
|
||||
func (item *TraceTelemetry) SetProperty(key, value string) {
|
||||
if item.data.Properties == nil {
|
||||
item.data.Properties = make(map[string]string)
|
||||
}
|
||||
item.data.Properties[key] = value
|
||||
}
|
||||
|
||||
type EventTelemetry struct {
|
||||
BaseTelemetry
|
||||
data *eventData
|
||||
}
|
||||
|
||||
func NewEventTelemetry(name string) *EventTelemetry {
|
||||
now := time.Now()
|
||||
data := &eventData{
|
||||
Name: name,
|
||||
}
|
||||
|
||||
data.Ver = 2
|
||||
|
||||
item := &EventTelemetry{
|
||||
data: data,
|
||||
}
|
||||
|
||||
item.timestamp = now
|
||||
item.context = NewItemTelemetryContext()
|
||||
|
||||
return item
|
||||
}
|
||||
|
||||
func (item *EventTelemetry) Timestamp() time.Time {
|
||||
return item.timestamp
|
||||
}
|
||||
|
||||
func (item *EventTelemetry) Context() TelemetryContext {
|
||||
return item.context
|
||||
}
|
||||
|
||||
func (item *EventTelemetry) baseTypeName() string {
|
||||
return "Event"
|
||||
}
|
||||
|
||||
func (item *EventTelemetry) baseData() Domain {
|
||||
return item.data
|
||||
}
|
||||
|
||||
func (item *EventTelemetry) SetProperty(key, value string) {
|
||||
if item.data.Properties == nil {
|
||||
item.data.Properties = make(map[string]string)
|
||||
}
|
||||
item.data.Properties[key] = value
|
||||
}
|
||||
|
||||
type MetricTelemetry struct {
|
||||
BaseTelemetry
|
||||
data *metricData
|
||||
}
|
||||
|
||||
func NewMetricTelemetry(name string, value float32) *MetricTelemetry {
|
||||
now := time.Now()
|
||||
metric := &DataPoint{
|
||||
Name: name,
|
||||
Value: value,
|
||||
Count: 1,
|
||||
}
|
||||
|
||||
data := &metricData{
|
||||
Metrics: make([]*DataPoint, 1),
|
||||
}
|
||||
|
||||
data.Ver = 2
|
||||
data.Metrics[0] = metric
|
||||
|
||||
item := &MetricTelemetry{
|
||||
data: data,
|
||||
}
|
||||
|
||||
item.timestamp = now
|
||||
item.context = NewItemTelemetryContext()
|
||||
|
||||
return item
|
||||
}
|
||||
|
||||
func (item *MetricTelemetry) Timestamp() time.Time {
|
||||
return item.timestamp
|
||||
}
|
||||
|
||||
func (item *MetricTelemetry) Context() TelemetryContext {
|
||||
return item.context
|
||||
}
|
||||
|
||||
func (item *MetricTelemetry) baseTypeName() string {
|
||||
return "Metric"
|
||||
}
|
||||
|
||||
func (item *MetricTelemetry) baseData() Domain {
|
||||
return item.data
|
||||
}
|
||||
|
||||
func (item *MetricTelemetry) SetProperty(key, value string) {
|
||||
if item.data.Properties == nil {
|
||||
item.data.Properties = make(map[string]string)
|
||||
}
|
||||
item.data.Properties[key] = value
|
||||
}
|
||||
|
||||
type RequestTelemetry struct {
|
||||
BaseTelemetry
|
||||
data *requestData
|
||||
}
|
||||
|
||||
func NewRequestTelemetry(name, httpMethod, url string, timestamp time.Time, duration time.Duration, responseCode string, success bool) *RequestTelemetry {
|
||||
now := time.Now()
|
||||
data := &requestData{
|
||||
Name: name,
|
||||
StartTime: timestamp.Format(time.RFC3339Nano),
|
||||
Duration: formatDuration(duration),
|
||||
ResponseCode: responseCode,
|
||||
Success: success,
|
||||
HttpMethod: httpMethod,
|
||||
Url: url,
|
||||
Id: randomId(),
|
||||
}
|
||||
|
||||
data.Ver = 2
|
||||
|
||||
item := &RequestTelemetry{
|
||||
data: data,
|
||||
}
|
||||
|
||||
item.timestamp = now
|
||||
item.context = NewItemTelemetryContext()
|
||||
|
||||
return item
|
||||
}
|
||||
|
||||
func (item *RequestTelemetry) Timestamp() time.Time {
|
||||
return item.timestamp
|
||||
}
|
||||
|
||||
func (item *RequestTelemetry) Context() TelemetryContext {
|
||||
return item.context
|
||||
}
|
||||
|
||||
func (item *RequestTelemetry) baseTypeName() string {
|
||||
return "Request"
|
||||
}
|
||||
|
||||
func (item *RequestTelemetry) baseData() Domain {
|
||||
return item.data
|
||||
}
|
||||
|
||||
func (item *RequestTelemetry) SetProperty(key, value string) {
|
||||
if item.data.Properties == nil {
|
||||
item.data.Properties = make(map[string]string)
|
||||
}
|
||||
item.data.Properties[key] = value
|
||||
}
|
||||
|
||||
func formatDuration(d time.Duration) string {
|
||||
ticks := int64(d/(time.Nanosecond*100)) % 10000000
|
||||
seconds := int64(d/time.Second) % 60
|
||||
minutes := int64(d/time.Minute) % 60
|
||||
hours := int64(d/time.Hour) % 24
|
||||
days := int64(d / (time.Hour * 24))
|
||||
|
||||
return fmt.Sprintf("%d.%02d:%02d:%02d.%07d", days, hours, minutes, seconds, ticks)
|
||||
}
|
64
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/diagnostics.go
generated
vendored
Normal file
64
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/diagnostics.go
generated
vendored
Normal file
|
@ -0,0 +1,64 @@
|
|||
package appinsights
|
||||
|
||||
import "fmt"
|
||||
|
||||
type DiagnosticsMessageWriter interface {
|
||||
Write(string)
|
||||
appendListener(*diagnosticsMessageListener)
|
||||
}
|
||||
|
||||
type diagnosticsMessageWriter struct {
|
||||
listeners []chan string
|
||||
}
|
||||
|
||||
type DiagnosticsMessageProcessor func(string)
|
||||
|
||||
type DiagnosticsMessageListener interface {
|
||||
ProcessMessages(DiagnosticsMessageProcessor)
|
||||
}
|
||||
|
||||
type diagnosticsMessageListener struct {
|
||||
channel chan string
|
||||
}
|
||||
|
||||
var diagnosticsWriter *diagnosticsMessageWriter = &diagnosticsMessageWriter{
|
||||
listeners: make([]chan string, 0),
|
||||
}
|
||||
|
||||
func NewDiagnosticsMessageListener() DiagnosticsMessageListener {
|
||||
listener := &diagnosticsMessageListener{
|
||||
channel: make(chan string),
|
||||
}
|
||||
|
||||
diagnosticsWriter.appendListener(listener)
|
||||
|
||||
return listener
|
||||
}
|
||||
|
||||
func (writer *diagnosticsMessageWriter) appendListener(listener *diagnosticsMessageListener) {
|
||||
writer.listeners = append(writer.listeners, listener.channel)
|
||||
}
|
||||
|
||||
func (writer *diagnosticsMessageWriter) Write(message string) {
|
||||
for _, c := range writer.listeners {
|
||||
c <- message
|
||||
}
|
||||
}
|
||||
|
||||
func (writer *diagnosticsMessageWriter) Printf(message string, args ...interface{}) {
|
||||
// Don't bother with Sprintf if nobody is listening
|
||||
if writer.hasListeners() {
|
||||
writer.Write(fmt.Sprintf(message, args...))
|
||||
}
|
||||
}
|
||||
|
||||
func (writer *diagnosticsMessageWriter) hasListeners() bool {
|
||||
return len(writer.listeners) > 0
|
||||
}
|
||||
|
||||
func (listener *diagnosticsMessageListener) ProcessMessages(process DiagnosticsMessageProcessor) {
|
||||
for {
|
||||
message := <-listener.channel
|
||||
process(message)
|
||||
}
|
||||
}
|
408
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/inmemorychannel.go
generated
vendored
Normal file
408
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/inmemorychannel.go
generated
vendored
Normal file
|
@ -0,0 +1,408 @@
|
|||
package appinsights
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"code.cloudfoundry.org/clock"
|
||||
)
|
||||
|
||||
var (
|
||||
submit_retries = []time.Duration{time.Duration(10 * time.Second), time.Duration(30 * time.Second), time.Duration(60 * time.Second)}
|
||||
)
|
||||
|
||||
type TelemetryBufferItems []Telemetry
|
||||
|
||||
type InMemoryChannel struct {
|
||||
endpointAddress string
|
||||
isDeveloperMode bool
|
||||
collectChan chan Telemetry
|
||||
controlChan chan *inMemoryChannelControl
|
||||
batchSize int
|
||||
batchInterval time.Duration
|
||||
waitgroup sync.WaitGroup
|
||||
throttle *throttleManager
|
||||
transmitter transmitter
|
||||
}
|
||||
|
||||
type inMemoryChannelControl struct {
|
||||
// If true, flush the buffer.
|
||||
flush bool
|
||||
|
||||
// If true, stop listening on the channel. (Flush is required if any events are to be sent)
|
||||
stop bool
|
||||
|
||||
// If stopping and flushing, this specifies whether to retry submissions on error.
|
||||
retry bool
|
||||
|
||||
// If retrying, what is the max time to wait before finishing up?
|
||||
timeout time.Duration
|
||||
|
||||
// If specified, a message will be sent on this channel when all pending telemetry items have been submitted
|
||||
callback chan struct{}
|
||||
}
|
||||
|
||||
func NewInMemoryChannel(config *TelemetryConfiguration) *InMemoryChannel {
|
||||
channel := &InMemoryChannel{
|
||||
endpointAddress: config.EndpointUrl,
|
||||
collectChan: make(chan Telemetry),
|
||||
controlChan: make(chan *inMemoryChannelControl),
|
||||
batchSize: config.MaxBatchSize,
|
||||
batchInterval: config.MaxBatchInterval,
|
||||
throttle: newThrottleManager(),
|
||||
transmitter: newTransmitter(config.EndpointUrl),
|
||||
}
|
||||
|
||||
go channel.acceptLoop()
|
||||
|
||||
return channel
|
||||
}
|
||||
|
||||
func (channel *InMemoryChannel) EndpointAddress() string {
|
||||
return channel.endpointAddress
|
||||
}
|
||||
|
||||
func (channel *InMemoryChannel) Send(item Telemetry) {
|
||||
if item != nil && channel.collectChan != nil {
|
||||
channel.collectChan <- item
|
||||
}
|
||||
}
|
||||
|
||||
func (channel *InMemoryChannel) Flush() {
|
||||
if channel.controlChan != nil {
|
||||
channel.controlChan <- &inMemoryChannelControl{
|
||||
flush: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (channel *InMemoryChannel) Stop() {
|
||||
if channel.controlChan != nil {
|
||||
channel.controlChan <- &inMemoryChannelControl{
|
||||
stop: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (channel *InMemoryChannel) IsThrottled() bool {
|
||||
return channel.throttle != nil && channel.throttle.IsThrottled()
|
||||
}
|
||||
|
||||
func (channel *InMemoryChannel) Close(timeout ...time.Duration) <-chan struct{} {
|
||||
if channel.controlChan != nil {
|
||||
callback := make(chan struct{})
|
||||
|
||||
ctl := &inMemoryChannelControl{
|
||||
stop: true,
|
||||
flush: true,
|
||||
retry: false,
|
||||
callback: callback,
|
||||
}
|
||||
|
||||
if len(timeout) > 0 {
|
||||
ctl.retry = true
|
||||
ctl.timeout = timeout[0]
|
||||
}
|
||||
|
||||
channel.controlChan <- ctl
|
||||
|
||||
return callback
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (channel *InMemoryChannel) acceptLoop() {
|
||||
channelState := newInMemoryChannelState(channel)
|
||||
|
||||
for !channelState.stopping {
|
||||
channelState.start()
|
||||
}
|
||||
|
||||
channelState.stop()
|
||||
}
|
||||
|
||||
// Data shared between parts of a channel
|
||||
type inMemoryChannelState struct {
|
||||
channel *InMemoryChannel
|
||||
stopping bool
|
||||
buffer TelemetryBufferItems
|
||||
retry bool
|
||||
retryTimeout time.Duration
|
||||
callback chan struct{}
|
||||
timer clock.Timer
|
||||
}
|
||||
|
||||
func newInMemoryChannelState(channel *InMemoryChannel) *inMemoryChannelState {
|
||||
return &inMemoryChannelState{
|
||||
channel: channel,
|
||||
buffer: make(TelemetryBufferItems, 0, 16),
|
||||
stopping: false,
|
||||
timer: currentClock.NewTimer(channel.batchInterval),
|
||||
}
|
||||
}
|
||||
|
||||
// Part of channel accept loop: Initialize buffer and accept first message, handle controls.
|
||||
func (state *inMemoryChannelState) start() bool {
|
||||
if len(state.buffer) > 16 {
|
||||
// Start out with the size of the previous buffer
|
||||
state.buffer = make(TelemetryBufferItems, 0, cap(state.buffer))
|
||||
} else if len(state.buffer) > 0 {
|
||||
// Start out with at least 16 slots
|
||||
state.buffer = make(TelemetryBufferItems, 0, 16)
|
||||
}
|
||||
|
||||
// Wait for an event
|
||||
select {
|
||||
case event := <-state.channel.collectChan:
|
||||
if event == nil {
|
||||
// Channel closed? Not intercepted by Send()?
|
||||
panic("Received nil event")
|
||||
}
|
||||
|
||||
state.buffer = append(state.buffer, event)
|
||||
|
||||
case ctl := <-state.channel.controlChan:
|
||||
// The buffer is empty, so there would be no point in flushing
|
||||
state.channel.signalWhenDone(ctl.callback)
|
||||
|
||||
if ctl.stop {
|
||||
state.stopping = true
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if len(state.buffer) == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
return state.waitToSend()
|
||||
}
|
||||
|
||||
// Part of channel accept loop: Wait for buffer to fill, timeout to expire, or flush
|
||||
func (state *inMemoryChannelState) waitToSend() bool {
|
||||
// Things that are used by the sender if we receive a control message
|
||||
state.retryTimeout = 0
|
||||
state.retry = true
|
||||
state.callback = nil
|
||||
|
||||
// Delay until timeout passes or buffer fills up
|
||||
state.timer.Reset(state.channel.batchInterval)
|
||||
for {
|
||||
select {
|
||||
case event := <-state.channel.collectChan:
|
||||
if event == nil {
|
||||
// Channel closed? Not intercepted by Send()?
|
||||
panic("Received nil event")
|
||||
}
|
||||
|
||||
state.buffer = append(state.buffer, event)
|
||||
if len(state.buffer) >= state.channel.batchSize {
|
||||
return state.send()
|
||||
}
|
||||
|
||||
case ctl := <-state.channel.controlChan:
|
||||
if ctl.stop {
|
||||
state.stopping = true
|
||||
state.retry = ctl.retry
|
||||
if !ctl.flush {
|
||||
// No flush? Just exit.
|
||||
state.channel.signalWhenDone(ctl.callback)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if ctl.flush {
|
||||
state.retryTimeout = ctl.timeout
|
||||
state.callback = ctl.callback
|
||||
return state.send()
|
||||
}
|
||||
|
||||
case _ = <-state.timer.C():
|
||||
// Timeout expired
|
||||
return state.send()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Part of channel accept loop: Check and wait on throttle, submit pending telemetry
|
||||
func (state *inMemoryChannelState) send() bool {
|
||||
// Hold up transmission if we're being throttled
|
||||
if !state.stopping && state.channel.throttle.IsThrottled() {
|
||||
if !state.waitThrottle() {
|
||||
// Stopped
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Send
|
||||
if len(state.buffer) > 0 {
|
||||
state.channel.waitgroup.Add(1)
|
||||
|
||||
// If we have a callback, wait on the waitgroup now that it's
|
||||
// incremented.
|
||||
state.channel.signalWhenDone(state.callback)
|
||||
|
||||
go func(buffer TelemetryBufferItems, retry bool, retryTimeout time.Duration) {
|
||||
defer state.channel.waitgroup.Done()
|
||||
state.channel.transmitRetry(buffer, retry, retryTimeout)
|
||||
}(state.buffer, state.retry, state.retryTimeout)
|
||||
} else if state.callback != nil {
|
||||
state.channel.signalWhenDone(state.callback)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Part of channel accept loop: Wait for throttle to expire while dropping messages
|
||||
func (state *inMemoryChannelState) waitThrottle() bool {
|
||||
// Channel is currently throttled. Once the buffer fills, messages will
|
||||
// be lost... If we're exiting, then we'll just try to submit anyway. That
|
||||
// request may be throttled and transmitRetry will perform the backoff correctly.
|
||||
|
||||
diagnosticsWriter.Write("Channel is throttled, events may be dropped.")
|
||||
throttleDone := state.channel.throttle.NotifyWhenReady()
|
||||
dropped := 0
|
||||
|
||||
defer diagnosticsWriter.Printf("Channel dropped %d events while throttled", dropped)
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-throttleDone:
|
||||
close(throttleDone)
|
||||
return true
|
||||
|
||||
case event := <-state.channel.collectChan:
|
||||
// If there's still room in the buffer, then go ahead and add it.
|
||||
if len(state.buffer) < state.channel.batchSize {
|
||||
state.buffer = append(state.buffer, event)
|
||||
} else {
|
||||
if dropped == 0 {
|
||||
diagnosticsWriter.Write("Buffer is full, dropping further events.")
|
||||
}
|
||||
|
||||
dropped++
|
||||
}
|
||||
|
||||
case ctl := <-state.channel.controlChan:
|
||||
if ctl.stop {
|
||||
state.stopping = true
|
||||
state.retry = ctl.retry
|
||||
if !ctl.flush {
|
||||
state.channel.signalWhenDone(ctl.callback)
|
||||
return false
|
||||
} else {
|
||||
// Make an exception when stopping
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// Cannot flush
|
||||
// TODO: Figure out what to do about callback?
|
||||
if ctl.flush {
|
||||
state.channel.signalWhenDone(ctl.callback)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Part of channel accept loop: Clean up and close telemetry channel
|
||||
func (state *inMemoryChannelState) stop() {
|
||||
close(state.channel.collectChan)
|
||||
close(state.channel.controlChan)
|
||||
|
||||
state.channel.collectChan = nil
|
||||
state.channel.controlChan = nil
|
||||
|
||||
// Throttle can't close until transmitters are done using it.
|
||||
state.channel.waitgroup.Wait()
|
||||
state.channel.throttle.Stop()
|
||||
|
||||
state.channel.throttle = nil
|
||||
}
|
||||
|
||||
func (channel *InMemoryChannel) transmitRetry(items TelemetryBufferItems, retry bool, retryTimeout time.Duration) {
|
||||
payload := items.serialize()
|
||||
retryTimeRemaining := retryTimeout
|
||||
|
||||
for _, wait := range submit_retries {
|
||||
result, err := channel.transmitter.Transmit(payload, items)
|
||||
if err == nil && result != nil && result.IsSuccess() {
|
||||
return
|
||||
}
|
||||
|
||||
if !retry {
|
||||
diagnosticsWriter.Write("Refusing to retry telemetry submission (retry==false)")
|
||||
return
|
||||
}
|
||||
|
||||
// Check for success, determine if we need to retry anything
|
||||
if result != nil {
|
||||
if result.CanRetry() {
|
||||
// Filter down to failed items
|
||||
payload, items = result.GetRetryItems(payload, items)
|
||||
if len(payload) == 0 || len(items) == 0 {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
diagnosticsWriter.Write("Cannot retry telemetry submission")
|
||||
return
|
||||
}
|
||||
|
||||
// Check for throttling
|
||||
if result.IsThrottled() {
|
||||
if result.retryAfter != nil {
|
||||
diagnosticsWriter.Printf("Channel is throttled until %s", *result.retryAfter)
|
||||
channel.throttle.RetryAfter(*result.retryAfter)
|
||||
} else {
|
||||
// TODO: Pick a time
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if retryTimeout > 0 {
|
||||
// We're on a time schedule here. Make sure we don't try longer
|
||||
// than we have been allowed.
|
||||
if retryTimeRemaining < wait {
|
||||
// One more chance left -- we'll wait the max time we can
|
||||
// and then retry on the way out.
|
||||
currentClock.Sleep(retryTimeRemaining)
|
||||
break
|
||||
} else {
|
||||
// Still have time left to go through the rest of the regular
|
||||
// retry schedule
|
||||
retryTimeRemaining -= wait
|
||||
}
|
||||
}
|
||||
|
||||
diagnosticsWriter.Printf("Waiting %s to retry submission", wait)
|
||||
currentClock.Sleep(wait)
|
||||
|
||||
// Wait if the channel is throttled and we're not on a schedule
|
||||
if channel.IsThrottled() && retryTimeout == 0 {
|
||||
diagnosticsWriter.Printf("Channel is throttled; extending wait time.")
|
||||
ch := channel.throttle.NotifyWhenReady()
|
||||
result := <-ch
|
||||
close(ch)
|
||||
|
||||
if !result {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// One final try
|
||||
_, err := channel.transmitter.Transmit(payload, items)
|
||||
if err != nil {
|
||||
diagnosticsWriter.Write("Gave up transmitting payload; exhausted retries")
|
||||
}
|
||||
}
|
||||
|
||||
func (channel *InMemoryChannel) signalWhenDone(callback chan struct{}) {
|
||||
if callback != nil {
|
||||
go func() {
|
||||
channel.waitgroup.Wait()
|
||||
close(callback)
|
||||
}()
|
||||
}
|
||||
}
|
45
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/jsonserializer.go
generated
vendored
Normal file
45
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/jsonserializer.go
generated
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
package appinsights
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (items TelemetryBufferItems) serialize() []byte {
|
||||
var result bytes.Buffer
|
||||
encoder := json.NewEncoder(&result)
|
||||
|
||||
for _, item := range items {
|
||||
end := result.Len()
|
||||
if err := encoder.Encode(prepare(item)); err != nil {
|
||||
diagnosticsWriter.Write(fmt.Sprintf("Telemetry item failed to serialize: %s", err.Error()))
|
||||
result.Truncate(end)
|
||||
}
|
||||
}
|
||||
|
||||
return result.Bytes()
|
||||
}
|
||||
|
||||
func prepare(item Telemetry) *envelope {
|
||||
data := &data{
|
||||
BaseType: item.baseTypeName() + "Data",
|
||||
BaseData: item.baseData(),
|
||||
}
|
||||
|
||||
context := item.Context()
|
||||
|
||||
envelope := &envelope{
|
||||
Name: "Microsoft.ApplicationInsights." + item.baseTypeName(),
|
||||
Time: item.Timestamp().Format(time.RFC3339),
|
||||
IKey: context.InstrumentationKey(),
|
||||
Data: data,
|
||||
}
|
||||
|
||||
if tcontext, ok := context.(*telemetryContext); ok {
|
||||
envelope.Tags = tcontext.tags
|
||||
}
|
||||
|
||||
return envelope
|
||||
}
|
8
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/package.go
generated
vendored
Normal file
8
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/package.go
generated
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
// Package appinsights provides an interface to submit telemetry to Application Insights.
|
||||
// See more at https://azure.microsoft.com/en-us/services/application-insights/
|
||||
package appinsights
|
||||
|
||||
const (
|
||||
sdkName = "go"
|
||||
Version = "0.3.1-pre"
|
||||
)
|
47
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/telemetrychannel.go
generated
vendored
Normal file
47
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/telemetrychannel.go
generated
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
package appinsights
|
||||
|
||||
import "time"
|
||||
|
||||
// Implementations of TelemetryChannel are responsible for queueing and
|
||||
// periodically submitting telemetry items.
|
||||
type TelemetryChannel interface {
|
||||
// The address of the endpoint to which telemetry is sent
|
||||
EndpointAddress() string
|
||||
|
||||
// Queues a single telemetry item
|
||||
Send(Telemetry)
|
||||
|
||||
// Forces the current queue to be sent
|
||||
Flush()
|
||||
|
||||
// Tears down the submission goroutines, closes internal channels.
|
||||
// Any telemetry waiting to be sent is discarded. Further calls to
|
||||
// Send() have undefined behavior. This is a more abrupt version of
|
||||
// Close().
|
||||
Stop()
|
||||
|
||||
// Returns true if this channel has been throttled by the data
|
||||
// collector.
|
||||
IsThrottled() bool
|
||||
|
||||
// Flushes and tears down the submission goroutine and closes
|
||||
// internal channels. Returns a channel that is closed when all
|
||||
// pending telemetry items have been submitted and it is safe to
|
||||
// shut down without losing telemetry.
|
||||
//
|
||||
// If retryTimeout is specified and non-zero, then failed
|
||||
// submissions will be retried until one succeeds or the timeout
|
||||
// expires, whichever occurs first. A retryTimeout of zero
|
||||
// indicates that failed submissions will be retried as usual. An
|
||||
// omitted retryTimeout indicates that submissions should not be
|
||||
// retried if they fail.
|
||||
//
|
||||
// Note that the returned channel may not be closed before
|
||||
// retryTimeout even if it is specified. This is because
|
||||
// retryTimeout only applies to the latest telemetry buffer. This
|
||||
// may be typical for applications that submit a large amount of
|
||||
// telemetry or are prone to being throttled. When exiting, you
|
||||
// should select on the result channel and your own timer to avoid
|
||||
// long delays.
|
||||
Close(retryTimeout ...time.Duration) <-chan struct{}
|
||||
}
|
400
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/telemetrycontext.go
generated
vendored
Normal file
400
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/telemetrycontext.go
generated
vendored
Normal file
|
@ -0,0 +1,400 @@
|
|||
package appinsights
|
||||
|
||||
import (
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type TelemetryContext interface {
|
||||
InstrumentationKey() string
|
||||
loadDeviceContext()
|
||||
|
||||
Component() ComponentContext
|
||||
Device() DeviceContext
|
||||
Cloud() CloudContext
|
||||
Session() SessionContext
|
||||
User() UserContext
|
||||
Operation() OperationContext
|
||||
Location() LocationContext
|
||||
}
|
||||
|
||||
type telemetryContext struct {
|
||||
iKey string
|
||||
tags map[string]string
|
||||
}
|
||||
|
||||
type ComponentContext interface {
|
||||
GetVersion() string
|
||||
SetVersion(string)
|
||||
}
|
||||
|
||||
type DeviceContext interface {
|
||||
GetType() string
|
||||
SetType(string)
|
||||
GetId() string
|
||||
SetId(string)
|
||||
GetOperatingSystem() string
|
||||
SetOperatingSystem(string)
|
||||
GetOemName() string
|
||||
SetOemName(string)
|
||||
GetModel() string
|
||||
SetModel(string)
|
||||
GetNetworkType() string
|
||||
SetNetworkType(string)
|
||||
GetScreenResolution() string
|
||||
SetScreenResolution(string)
|
||||
GetLanguage() string
|
||||
SetLanguage(string)
|
||||
}
|
||||
|
||||
type CloudContext interface {
|
||||
GetRoleName() string
|
||||
SetRoleName(string)
|
||||
GetRoleInstance() string
|
||||
SetRoleInstance(string)
|
||||
}
|
||||
|
||||
type SessionContext interface {
|
||||
GetId() string
|
||||
SetId(string)
|
||||
GetIsFirst() bool
|
||||
SetIsFirst(bool)
|
||||
}
|
||||
|
||||
type UserContext interface {
|
||||
GetId() string
|
||||
SetId(string)
|
||||
GetAccountId() string
|
||||
SetAccountId(string)
|
||||
GetUserAgent() string
|
||||
SetUserAgent(string)
|
||||
GetAuthenticatedUserId() string
|
||||
SetAuthenticatedUserId(string)
|
||||
}
|
||||
|
||||
type OperationContext interface {
|
||||
GetId() string
|
||||
SetId(string)
|
||||
GetParentId() string
|
||||
SetParentId(string)
|
||||
GetCorrelationVector() string
|
||||
SetCorrelationVector(string)
|
||||
GetName() string
|
||||
SetName(string)
|
||||
GetSyntheticSource() string
|
||||
SetSyntheticSource(string)
|
||||
}
|
||||
|
||||
type LocationContext interface {
|
||||
GetIp() string
|
||||
SetIp(string)
|
||||
}
|
||||
|
||||
func NewItemTelemetryContext() TelemetryContext {
|
||||
context := &telemetryContext{
|
||||
tags: make(map[string]string),
|
||||
}
|
||||
return context
|
||||
}
|
||||
|
||||
func NewClientTelemetryContext() TelemetryContext {
|
||||
context := &telemetryContext{
|
||||
tags: make(map[string]string),
|
||||
}
|
||||
context.loadDeviceContext()
|
||||
context.loadInternalContext()
|
||||
return context
|
||||
}
|
||||
|
||||
func (context *telemetryContext) InstrumentationKey() string {
|
||||
return context.iKey
|
||||
}
|
||||
|
||||
func (context *telemetryContext) loadDeviceContext() {
|
||||
hostname, err := os.Hostname()
|
||||
if err == nil {
|
||||
context.tags[DeviceId] = hostname
|
||||
context.tags[DeviceMachineName] = hostname
|
||||
context.tags[DeviceRoleInstance] = hostname
|
||||
}
|
||||
context.tags[DeviceOS] = runtime.GOOS
|
||||
}
|
||||
|
||||
func (context *telemetryContext) loadInternalContext() {
|
||||
context.tags[InternalSdkVersion] = sdkName + ":" + Version
|
||||
}
|
||||
|
||||
func (context *telemetryContext) Component() ComponentContext {
|
||||
return &componentContext{context: context}
|
||||
}
|
||||
|
||||
func (context *telemetryContext) Device() DeviceContext {
|
||||
return &deviceContext{context: context}
|
||||
}
|
||||
|
||||
func (context *telemetryContext) Cloud() CloudContext {
|
||||
return &cloudContext{context: context}
|
||||
}
|
||||
|
||||
func (context *telemetryContext) Session() SessionContext {
|
||||
return &sessionContext{context: context}
|
||||
}
|
||||
|
||||
func (context *telemetryContext) User() UserContext {
|
||||
return &userContext{context: context}
|
||||
}
|
||||
|
||||
func (context *telemetryContext) Operation() OperationContext {
|
||||
return &operationContext{context: context}
|
||||
}
|
||||
|
||||
func (context *telemetryContext) Location() LocationContext {
|
||||
return &locationContext{context: context}
|
||||
}
|
||||
|
||||
func (context *telemetryContext) getTagString(key ContextTagKeys) string {
|
||||
if val, ok := context.tags[string(key)]; ok {
|
||||
return val
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func (context *telemetryContext) setTagString(key ContextTagKeys, value string) {
|
||||
if value != "" {
|
||||
context.tags[string(key)] = value
|
||||
} else {
|
||||
delete(context.tags, string(key))
|
||||
}
|
||||
}
|
||||
|
||||
func (context *telemetryContext) getTagBool(key ContextTagKeys) bool {
|
||||
if val, ok := context.tags[string(key)]; ok {
|
||||
if b, err := strconv.ParseBool(val); err != nil {
|
||||
return b
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (context *telemetryContext) setTagBool(key ContextTagKeys, value bool) {
|
||||
if value {
|
||||
context.tags[string(key)] = "true"
|
||||
} else {
|
||||
delete(context.tags, string(key))
|
||||
}
|
||||
}
|
||||
|
||||
type componentContext struct {
|
||||
context *telemetryContext
|
||||
}
|
||||
|
||||
type deviceContext struct {
|
||||
context *telemetryContext
|
||||
}
|
||||
|
||||
type cloudContext struct {
|
||||
context *telemetryContext
|
||||
}
|
||||
|
||||
type sessionContext struct {
|
||||
context *telemetryContext
|
||||
}
|
||||
|
||||
type userContext struct {
|
||||
context *telemetryContext
|
||||
}
|
||||
|
||||
type operationContext struct {
|
||||
context *telemetryContext
|
||||
}
|
||||
|
||||
type locationContext struct {
|
||||
context *telemetryContext
|
||||
}
|
||||
|
||||
func (context *componentContext) GetVersion() string {
|
||||
return context.context.getTagString(ApplicationVersion)
|
||||
}
|
||||
|
||||
func (context *componentContext) SetVersion(value string) {
|
||||
context.context.setTagString(ApplicationVersion, value)
|
||||
}
|
||||
|
||||
func (context *deviceContext) GetType() string {
|
||||
return context.context.getTagString(DeviceType)
|
||||
}
|
||||
|
||||
func (context *deviceContext) SetType(value string) {
|
||||
context.context.setTagString(DeviceType, value)
|
||||
}
|
||||
|
||||
func (context *deviceContext) GetId() string {
|
||||
return context.context.getTagString(DeviceId)
|
||||
}
|
||||
|
||||
func (context *deviceContext) SetId(value string) {
|
||||
context.context.setTagString(DeviceId, value)
|
||||
}
|
||||
|
||||
func (context *deviceContext) GetOperatingSystem() string {
|
||||
return context.context.getTagString(DeviceOSVersion)
|
||||
}
|
||||
|
||||
func (context *deviceContext) SetOperatingSystem(value string) {
|
||||
context.context.setTagString(DeviceOSVersion, value)
|
||||
}
|
||||
|
||||
func (context *deviceContext) GetOemName() string {
|
||||
return context.context.getTagString(DeviceOEMName)
|
||||
}
|
||||
|
||||
func (context *deviceContext) SetOemName(value string) {
|
||||
context.context.setTagString(DeviceOEMName, value)
|
||||
}
|
||||
|
||||
func (context *deviceContext) GetModel() string {
|
||||
return context.context.getTagString(DeviceModel)
|
||||
}
|
||||
|
||||
func (context *deviceContext) SetModel(value string) {
|
||||
context.context.setTagString(DeviceModel, value)
|
||||
}
|
||||
|
||||
func (context *deviceContext) GetNetworkType() string {
|
||||
return context.context.getTagString(DeviceNetwork)
|
||||
}
|
||||
|
||||
func (context *deviceContext) SetNetworkType(value string) {
|
||||
context.context.setTagString(DeviceNetwork, value)
|
||||
}
|
||||
|
||||
func (context *deviceContext) GetScreenResolution() string {
|
||||
return context.context.getTagString(DeviceScreenResolution)
|
||||
}
|
||||
|
||||
func (context *deviceContext) SetScreenResolution(value string) {
|
||||
context.context.setTagString(DeviceScreenResolution, value)
|
||||
}
|
||||
|
||||
func (context *deviceContext) GetLanguage() string {
|
||||
return context.context.getTagString(DeviceLanguage)
|
||||
}
|
||||
|
||||
func (context *deviceContext) SetLanguage(value string) {
|
||||
context.context.setTagString(DeviceLanguage, value)
|
||||
}
|
||||
|
||||
func (context *cloudContext) GetRoleName() string {
|
||||
return context.context.getTagString(CloudRole)
|
||||
}
|
||||
|
||||
func (context *cloudContext) SetRoleName(value string) {
|
||||
context.context.setTagString(CloudRole, value)
|
||||
}
|
||||
|
||||
func (context *cloudContext) GetRoleInstance() string {
|
||||
return context.context.getTagString(CloudRoleInstance)
|
||||
}
|
||||
|
||||
func (context *cloudContext) SetRoleInstance(value string) {
|
||||
context.context.setTagString(CloudRoleInstance, value)
|
||||
}
|
||||
|
||||
func (context *sessionContext) GetId() string {
|
||||
return context.context.getTagString(SessionId)
|
||||
}
|
||||
|
||||
func (context *sessionContext) SetId(value string) {
|
||||
context.context.setTagString(SessionId, value)
|
||||
}
|
||||
|
||||
func (context *sessionContext) GetIsFirst() bool {
|
||||
return context.context.getTagBool(SessionIsFirst)
|
||||
}
|
||||
|
||||
func (context *sessionContext) SetIsFirst(value bool) {
|
||||
context.context.setTagBool(SessionIsFirst, value)
|
||||
}
|
||||
|
||||
func (context *userContext) GetId() string {
|
||||
return context.context.getTagString(UserId)
|
||||
}
|
||||
|
||||
func (context *userContext) SetId(value string) {
|
||||
context.context.setTagString(UserId, value)
|
||||
}
|
||||
|
||||
func (context *userContext) GetAccountId() string {
|
||||
return context.context.getTagString(UserAccountId)
|
||||
}
|
||||
|
||||
func (context *userContext) SetAccountId(value string) {
|
||||
context.context.setTagString(UserAccountId, value)
|
||||
}
|
||||
|
||||
func (context *userContext) GetUserAgent() string {
|
||||
return context.context.getTagString(UserAgent)
|
||||
}
|
||||
|
||||
func (context *userContext) SetUserAgent(value string) {
|
||||
context.context.setTagString(UserAgent, value)
|
||||
}
|
||||
|
||||
func (context *userContext) GetAuthenticatedUserId() string {
|
||||
return context.context.getTagString(UserAuthUserId)
|
||||
}
|
||||
|
||||
func (context *userContext) SetAuthenticatedUserId(value string) {
|
||||
context.context.setTagString(UserAuthUserId, value)
|
||||
}
|
||||
|
||||
func (context *operationContext) GetId() string {
|
||||
return context.context.getTagString(OperationId)
|
||||
}
|
||||
|
||||
func (context *operationContext) SetId(value string) {
|
||||
context.context.setTagString(OperationId, value)
|
||||
}
|
||||
|
||||
func (context *operationContext) GetParentId() string {
|
||||
return context.context.getTagString(OperationParentId)
|
||||
}
|
||||
|
||||
func (context *operationContext) SetParentId(value string) {
|
||||
context.context.setTagString(OperationParentId, value)
|
||||
}
|
||||
|
||||
func (context *operationContext) GetCorrelationVector() string {
|
||||
return context.context.getTagString(OperationCorrelationVector)
|
||||
}
|
||||
|
||||
func (context *operationContext) SetCorrelationVector(value string) {
|
||||
context.context.setTagString(OperationCorrelationVector, value)
|
||||
}
|
||||
|
||||
func (context *operationContext) GetName() string {
|
||||
return context.context.getTagString(OperationName)
|
||||
}
|
||||
|
||||
func (context *operationContext) SetName(value string) {
|
||||
context.context.setTagString(OperationName, value)
|
||||
}
|
||||
|
||||
func (context *operationContext) GetSyntheticSource() string {
|
||||
return context.context.getTagString(OperationSyntheticSource)
|
||||
}
|
||||
|
||||
func (context *operationContext) SetSyntheticSource(value string) {
|
||||
context.context.setTagString(OperationSyntheticSource, value)
|
||||
}
|
||||
|
||||
func (context *locationContext) GetIp() string {
|
||||
return context.context.getTagString(LocationIp)
|
||||
}
|
||||
|
||||
func (context *locationContext) SetIp(value string) {
|
||||
context.context.setTagString(LocationIp, value)
|
||||
}
|
144
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/throttle.go
generated
vendored
Normal file
144
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/throttle.go
generated
vendored
Normal file
|
@ -0,0 +1,144 @@
|
|||
package appinsights
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type throttleManager struct {
|
||||
msgs chan *throttleMessage
|
||||
}
|
||||
|
||||
type throttleMessage struct {
|
||||
query bool
|
||||
wait bool
|
||||
throttle bool
|
||||
stop bool
|
||||
timestamp time.Time
|
||||
result chan bool
|
||||
}
|
||||
|
||||
func newThrottleManager() *throttleManager {
|
||||
result := &throttleManager{
|
||||
msgs: make(chan *throttleMessage),
|
||||
}
|
||||
|
||||
go result.run()
|
||||
return result
|
||||
}
|
||||
|
||||
func (throttle *throttleManager) RetryAfter(t time.Time) {
|
||||
throttle.msgs <- &throttleMessage{
|
||||
throttle: true,
|
||||
timestamp: t,
|
||||
}
|
||||
}
|
||||
|
||||
func (throttle *throttleManager) IsThrottled() bool {
|
||||
ch := make(chan bool)
|
||||
throttle.msgs <- &throttleMessage{
|
||||
query: true,
|
||||
result: ch,
|
||||
}
|
||||
|
||||
result := <-ch
|
||||
close(ch)
|
||||
return result
|
||||
}
|
||||
|
||||
func (throttle *throttleManager) NotifyWhenReady() chan bool {
|
||||
result := make(chan bool, 1)
|
||||
throttle.msgs <- &throttleMessage{
|
||||
wait: true,
|
||||
result: result,
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (throttle *throttleManager) Stop() {
|
||||
result := make(chan bool)
|
||||
throttle.msgs <- &throttleMessage{
|
||||
stop: true,
|
||||
result: result,
|
||||
}
|
||||
|
||||
<-result
|
||||
close(result)
|
||||
}
|
||||
|
||||
func (throttle *throttleManager) run() {
|
||||
for {
|
||||
throttledUntil, ok := throttle.waitForThrottle()
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
|
||||
if !throttle.waitForReady(throttledUntil) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
close(throttle.msgs)
|
||||
}
|
||||
|
||||
func (throttle *throttleManager) waitForThrottle() (time.Time, bool) {
|
||||
for {
|
||||
msg := <-throttle.msgs
|
||||
if msg.query {
|
||||
msg.result <- false
|
||||
} else if msg.wait {
|
||||
msg.result <- true
|
||||
} else if msg.stop {
|
||||
return time.Time{}, false
|
||||
} else if msg.throttle {
|
||||
return msg.timestamp, true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (throttle *throttleManager) waitForReady(throttledUntil time.Time) bool {
|
||||
duration := throttledUntil.Sub(currentClock.Now())
|
||||
if duration <= 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
var notify []chan bool
|
||||
|
||||
// --- Throttled and waiting ---
|
||||
t := currentClock.NewTimer(duration)
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-t.C():
|
||||
for _, n := range notify {
|
||||
n <- true
|
||||
}
|
||||
|
||||
return true
|
||||
case msg := <-throttle.msgs:
|
||||
if msg.query {
|
||||
msg.result <- true
|
||||
} else if msg.wait {
|
||||
notify = append(notify, msg.result)
|
||||
} else if msg.stop {
|
||||
for _, n := range notify {
|
||||
n <- false
|
||||
}
|
||||
|
||||
msg.result <- true
|
||||
|
||||
return false
|
||||
} else if msg.throttle {
|
||||
if msg.timestamp.After(throttledUntil) {
|
||||
throttledUntil = msg.timestamp
|
||||
|
||||
if !t.Stop() {
|
||||
<-t.C()
|
||||
}
|
||||
|
||||
t.Reset(throttledUntil.Sub(currentClock.Now()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
237
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/transmitter.go
generated
vendored
Normal file
237
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/transmitter.go
generated
vendored
Normal file
|
@ -0,0 +1,237 @@
|
|||
package appinsights
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"sort"
|
||||
"time"
|
||||
)
|
||||
|
||||
type transmitter interface {
|
||||
Transmit(payload []byte, items TelemetryBufferItems) (*transmissionResult, error)
|
||||
}
|
||||
|
||||
type httpTransmitter struct {
|
||||
endpoint string
|
||||
}
|
||||
|
||||
type transmissionResult struct {
|
||||
statusCode int
|
||||
retryAfter *time.Time
|
||||
response *backendResponse
|
||||
}
|
||||
|
||||
// Structures returned by data collector
|
||||
type backendResponse struct {
|
||||
ItemsReceived int `json:"itemsReceived"`
|
||||
ItemsAccepted int `json:"itemsAccepted"`
|
||||
Errors itemTransmissionResults `json:"errors"`
|
||||
}
|
||||
|
||||
// This needs to be its own type because it implements sort.Interface
|
||||
type itemTransmissionResults []*itemTransmissionResult
|
||||
|
||||
type itemTransmissionResult struct {
|
||||
Index int `json:"index"`
|
||||
StatusCode int `json:"statusCode"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
const (
|
||||
successResponse = 200
|
||||
partialSuccessResponse = 206
|
||||
requestTimeoutResponse = 408
|
||||
tooManyRequestsResponse = 429
|
||||
tooManyRequestsOverExtendedTimeResponse = 439
|
||||
errorResponse = 500
|
||||
serviceUnavailableResponse = 503
|
||||
)
|
||||
|
||||
func newTransmitter(endpointAddress string) transmitter {
|
||||
return &httpTransmitter{endpointAddress}
|
||||
}
|
||||
|
||||
func (transmitter *httpTransmitter) Transmit(payload []byte, items TelemetryBufferItems) (*transmissionResult, error) {
|
||||
diagnosticsWriter.Printf("----------- Transmitting %d items ---------", len(items))
|
||||
startTime := time.Now()
|
||||
|
||||
// Compress the payload
|
||||
var postBody bytes.Buffer
|
||||
gzipWriter := gzip.NewWriter(&postBody)
|
||||
if _, err := gzipWriter.Write(payload); err != nil {
|
||||
diagnosticsWriter.Printf("Failed to compress the payload: %s", err.Error())
|
||||
gzipWriter.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gzipWriter.Close()
|
||||
|
||||
req, err := http.NewRequest("POST", transmitter.endpoint, &postBody)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Encoding", "gzip")
|
||||
req.Header.Set("Content-Type", "application/x-json-stream")
|
||||
req.Header.Set("Accept-Encoding", "gzip, deflate")
|
||||
|
||||
client := http.DefaultClient
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
diagnosticsWriter.Printf("Failed to transmit telemetry: %s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
diagnosticsWriter.Printf("Failed to read response from server: %s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
duration := time.Since(startTime)
|
||||
|
||||
result := &transmissionResult{statusCode: resp.StatusCode}
|
||||
|
||||
// Grab Retry-After header
|
||||
if retryAfterValue, ok := resp.Header[http.CanonicalHeaderKey("Retry-After")]; ok && len(retryAfterValue) == 1 {
|
||||
if retryAfterTime, err := time.Parse(time.RFC1123, retryAfterValue[0]); err == nil {
|
||||
result.retryAfter = &retryAfterTime
|
||||
}
|
||||
}
|
||||
|
||||
// Parse body, if possible
|
||||
response := &backendResponse{}
|
||||
if err := json.Unmarshal(body, &response); err == nil {
|
||||
result.response = response
|
||||
}
|
||||
|
||||
// Write diagnostics
|
||||
if diagnosticsWriter.hasListeners() {
|
||||
diagnosticsWriter.Printf("Telemetry transmitted in %s", duration)
|
||||
diagnosticsWriter.Printf("Response: %d", result.statusCode)
|
||||
if result.response != nil {
|
||||
diagnosticsWriter.Printf("Items accepted/received: %d/%d", result.response.ItemsAccepted, result.response.ItemsReceived)
|
||||
if len(result.response.Errors) > 0 {
|
||||
diagnosticsWriter.Printf("Errors:")
|
||||
for _, err := range result.response.Errors {
|
||||
if err.Index < len(items) {
|
||||
diagnosticsWriter.Printf("#%d - %d %s", err.Index, err.StatusCode, err.Message)
|
||||
diagnosticsWriter.Printf("Telemetry item:\n\t%s", err.Index, string(items[err.Index:err.Index+1].serialize()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (result *transmissionResult) IsSuccess() bool {
|
||||
return result.statusCode == successResponse ||
|
||||
// Partial response but all items accepted
|
||||
(result.statusCode == partialSuccessResponse &&
|
||||
result.response != nil &&
|
||||
result.response.ItemsReceived == result.response.ItemsAccepted)
|
||||
}
|
||||
|
||||
func (result *transmissionResult) IsFailure() bool {
|
||||
return result.statusCode != successResponse && result.statusCode != partialSuccessResponse
|
||||
}
|
||||
|
||||
func (result *transmissionResult) CanRetry() bool {
|
||||
if result.IsSuccess() {
|
||||
return false
|
||||
}
|
||||
|
||||
return result.statusCode == partialSuccessResponse ||
|
||||
result.retryAfter != nil ||
|
||||
(result.statusCode == requestTimeoutResponse ||
|
||||
result.statusCode == serviceUnavailableResponse ||
|
||||
result.statusCode == errorResponse ||
|
||||
result.statusCode == tooManyRequestsResponse ||
|
||||
result.statusCode == tooManyRequestsOverExtendedTimeResponse)
|
||||
}
|
||||
|
||||
func (result *transmissionResult) IsPartialSuccess() bool {
|
||||
return result.statusCode == partialSuccessResponse &&
|
||||
result.response != nil &&
|
||||
result.response.ItemsReceived != result.response.ItemsAccepted
|
||||
}
|
||||
|
||||
func (result *transmissionResult) IsThrottled() bool {
|
||||
return result.statusCode == tooManyRequestsResponse ||
|
||||
result.statusCode == tooManyRequestsOverExtendedTimeResponse ||
|
||||
result.retryAfter != nil
|
||||
}
|
||||
|
||||
func (result *itemTransmissionResult) CanRetry() bool {
|
||||
return result.StatusCode == requestTimeoutResponse ||
|
||||
result.StatusCode == serviceUnavailableResponse ||
|
||||
result.StatusCode == errorResponse ||
|
||||
result.StatusCode == tooManyRequestsResponse ||
|
||||
result.StatusCode == tooManyRequestsOverExtendedTimeResponse
|
||||
}
|
||||
|
||||
func (result *transmissionResult) GetRetryItems(payload []byte, items TelemetryBufferItems) ([]byte, TelemetryBufferItems) {
|
||||
if result.statusCode == partialSuccessResponse && result.response != nil {
|
||||
// Make sure errors are ordered by index
|
||||
sort.Sort(result.response.Errors)
|
||||
|
||||
var resultPayload bytes.Buffer
|
||||
resultItems := make(TelemetryBufferItems, 0)
|
||||
ptr := 0
|
||||
idx := 0
|
||||
|
||||
// Find each retryable error
|
||||
for _, responseResult := range result.response.Errors {
|
||||
if responseResult.CanRetry() {
|
||||
// Advance ptr to start of desired line
|
||||
for ; idx < responseResult.Index && ptr < len(payload); ptr++ {
|
||||
if payload[ptr] == '\n' {
|
||||
idx++
|
||||
}
|
||||
}
|
||||
|
||||
startPtr := ptr
|
||||
|
||||
// Read to end of line
|
||||
for ; idx == responseResult.Index && ptr < len(payload); ptr++ {
|
||||
if payload[ptr] == '\n' {
|
||||
idx++
|
||||
}
|
||||
}
|
||||
|
||||
// Copy item into output buffer
|
||||
resultPayload.Write(payload[startPtr:ptr])
|
||||
resultItems = append(resultItems, items[responseResult.Index])
|
||||
}
|
||||
}
|
||||
|
||||
return resultPayload.Bytes(), resultItems
|
||||
} else if result.CanRetry() {
|
||||
return payload, items
|
||||
} else {
|
||||
return payload[:0], items[:0]
|
||||
}
|
||||
}
|
||||
|
||||
// sort.Interface implementation for Errors[] list
|
||||
|
||||
func (results itemTransmissionResults) Len() int {
|
||||
return len(results)
|
||||
}
|
||||
|
||||
func (results itemTransmissionResults) Less(i, j int) bool {
|
||||
return results[i].Index < results[j].Index
|
||||
}
|
||||
|
||||
func (results itemTransmissionResults) Swap(i, j int) {
|
||||
tmp := results[i]
|
||||
results[i] = results[j]
|
||||
results[j] = tmp
|
||||
}
|
45
vendor/github.com/containous/traefik-extra-service-fabric/servicefabric.go
generated
vendored
45
vendor/github.com/containous/traefik-extra-service-fabric/servicefabric.go
generated
vendored
|
@ -8,12 +8,14 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/cenk/backoff"
|
||||
"github.com/containous/flaeg"
|
||||
"github.com/containous/traefik/job"
|
||||
"github.com/containous/traefik/log"
|
||||
"github.com/containous/traefik/provider"
|
||||
"github.com/containous/traefik/provider/label"
|
||||
"github.com/containous/traefik/safe"
|
||||
"github.com/containous/traefik/types"
|
||||
"github.com/jjcollinge/logrus-appinsights"
|
||||
sf "github.com/jjcollinge/servicefabric"
|
||||
)
|
||||
|
||||
|
@ -31,13 +33,23 @@ type Provider struct {
|
|||
provider.BaseProvider `mapstructure:",squash"`
|
||||
ClusterManagementURL string `description:"Service Fabric API endpoint"`
|
||||
APIVersion string `description:"Service Fabric API version" export:"true"`
|
||||
RefreshSeconds int `description:"Polling interval (in seconds)" export:"true"`
|
||||
RefreshSeconds flaeg.Duration `description:"Polling interval (in seconds)" export:"true"`
|
||||
TLS *types.ClientTLS `description:"Enable TLS support" export:"true"`
|
||||
AppInsightsClientName string `description:"The client name, Identifies the cloud instance"`
|
||||
AppInsightsKey string `description:"Application Insights Instrumentation Key"`
|
||||
AppInsightsBatchSize int `description:"Number of trace lines per batch, optional"`
|
||||
AppInsightsInterval flaeg.Duration `description:"The interval for sending data to Application Insights, optional"`
|
||||
}
|
||||
|
||||
// Init the provider
|
||||
func (p *Provider) Init(constraints types.Constraints) error {
|
||||
p.BaseProvider.Init(constraints)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Provide allows the ServiceFabric provider to provide configurations to traefik
|
||||
// using the given configuration channel.
|
||||
func (p *Provider) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error {
|
||||
func (p *Provider) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool) error {
|
||||
if p.APIVersion == "" {
|
||||
p.APIVersion = sf.DefaultAPIVersion
|
||||
}
|
||||
|
@ -53,10 +65,20 @@ func (p *Provider) Provide(configurationChan chan<- types.ConfigMessage, pool *s
|
|||
}
|
||||
|
||||
if p.RefreshSeconds <= 0 {
|
||||
p.RefreshSeconds = 10
|
||||
p.RefreshSeconds = flaeg.Duration(10 * time.Second)
|
||||
}
|
||||
|
||||
return p.updateConfig(configurationChan, pool, sfClient, time.Duration(p.RefreshSeconds)*time.Second)
|
||||
if p.AppInsightsClientName != "" && p.AppInsightsKey != "" {
|
||||
if p.AppInsightsBatchSize == 0 {
|
||||
p.AppInsightsBatchSize = 10
|
||||
}
|
||||
if p.AppInsightsInterval == 0 {
|
||||
p.AppInsightsInterval = flaeg.Duration(5 * time.Second)
|
||||
}
|
||||
createAppInsightsHook(p.AppInsightsClientName, p.AppInsightsKey, p.AppInsightsBatchSize, p.AppInsightsInterval)
|
||||
}
|
||||
|
||||
return p.updateConfig(configurationChan, pool, sfClient, time.Duration(p.RefreshSeconds))
|
||||
}
|
||||
|
||||
func (p *Provider) updateConfig(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, sfClient sfClient, pollInterval time.Duration) error {
|
||||
|
@ -263,3 +285,18 @@ func getLabels(sfClient sfClient, service *sf.ServiceItem, app *sf.ApplicationIt
|
|||
}
|
||||
return labels, nil
|
||||
}
|
||||
|
||||
func createAppInsightsHook(appInsightsClientName string, instrumentationKey string, maxBatchSize int, interval flaeg.Duration) {
|
||||
hook, err := logrus_appinsights.New(appInsightsClientName, logrus_appinsights.Config{
|
||||
InstrumentationKey: instrumentationKey,
|
||||
MaxBatchSize: maxBatchSize, // optional
|
||||
MaxBatchInterval: time.Duration(interval), // optional
|
||||
})
|
||||
if err != nil || hook == nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// ignore fields
|
||||
hook.AddIgnore("private")
|
||||
log.AddHook(hook)
|
||||
}
|
||||
|
|
2
vendor/github.com/containous/traefik-extra-service-fabric/servicefabric_config.go
generated
vendored
2
vendor/github.com/containous/traefik-extra-service-fabric/servicefabric_config.go
generated
vendored
|
@ -76,7 +76,7 @@ func getDefaultEndpoint(instance replicaInstance) string {
|
|||
id, data := instance.GetReplicaData()
|
||||
endpoint, err := getReplicaDefaultEndpoint(data)
|
||||
if err != nil {
|
||||
log.Warnf("No default endpoint for replica %s in service %s endpointData: %s", id, data.Address)
|
||||
log.Warnf("No default endpoint for replica %s in service %s endpointData: %s", id, data.Address, err)
|
||||
return ""
|
||||
}
|
||||
return endpoint
|
||||
|
|
21
vendor/github.com/jjcollinge/logrus-appinsights/LICENSE
generated
vendored
Normal file
21
vendor/github.com/jjcollinge/logrus-appinsights/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2018 jjcollinge
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
11
vendor/github.com/jjcollinge/logrus-appinsights/config.go
generated
vendored
Normal file
11
vendor/github.com/jjcollinge/logrus-appinsights/config.go
generated
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
package logrus_appinsights
|
||||
|
||||
import "time"
|
||||
|
||||
// Config for Application Insights settings
|
||||
type Config struct {
|
||||
InstrumentationKey string
|
||||
EndpointUrl string
|
||||
MaxBatchSize int
|
||||
MaxBatchInterval time.Duration
|
||||
}
|
173
vendor/github.com/jjcollinge/logrus-appinsights/hook.go
generated
vendored
Normal file
173
vendor/github.com/jjcollinge/logrus-appinsights/hook.go
generated
vendored
Normal file
|
@ -0,0 +1,173 @@
|
|||
package logrus_appinsights
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/Microsoft/ApplicationInsights-Go/appinsights"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var defaultLevels = []logrus.Level{
|
||||
logrus.PanicLevel,
|
||||
logrus.FatalLevel,
|
||||
logrus.ErrorLevel,
|
||||
logrus.WarnLevel,
|
||||
logrus.InfoLevel,
|
||||
}
|
||||
|
||||
var levelMap = map[logrus.Level]appinsights.SeverityLevel{
|
||||
logrus.PanicLevel: appinsights.Critical,
|
||||
logrus.FatalLevel: appinsights.Critical,
|
||||
logrus.ErrorLevel: appinsights.Error,
|
||||
logrus.WarnLevel: appinsights.Warning,
|
||||
logrus.InfoLevel: appinsights.Information,
|
||||
}
|
||||
|
||||
// AppInsightsHook is a logrus hook for Application Insights
|
||||
type AppInsightsHook struct {
|
||||
client appinsights.TelemetryClient
|
||||
|
||||
async bool
|
||||
levels []logrus.Level
|
||||
ignoreFields map[string]struct{}
|
||||
filters map[string]func(interface{}) interface{}
|
||||
}
|
||||
|
||||
// New returns an initialised logrus hook for Application Insights
|
||||
func New(name string, conf Config) (*AppInsightsHook, error) {
|
||||
if conf.InstrumentationKey == "" {
|
||||
return nil, fmt.Errorf("InstrumentationKey is required and missing from configuration")
|
||||
}
|
||||
telemetryConf := appinsights.NewTelemetryConfiguration(conf.InstrumentationKey)
|
||||
if conf.MaxBatchSize != 0 {
|
||||
telemetryConf.MaxBatchSize = conf.MaxBatchSize
|
||||
}
|
||||
if conf.MaxBatchInterval != 0 {
|
||||
telemetryConf.MaxBatchInterval = conf.MaxBatchInterval
|
||||
}
|
||||
if conf.EndpointUrl != "" {
|
||||
telemetryConf.EndpointUrl = conf.EndpointUrl
|
||||
}
|
||||
telemetryClient := appinsights.NewTelemetryClientFromConfig(telemetryConf)
|
||||
if name != "" {
|
||||
telemetryClient.Context().Cloud().SetRoleName(name)
|
||||
}
|
||||
return &AppInsightsHook{
|
||||
client: telemetryClient,
|
||||
levels: defaultLevels,
|
||||
ignoreFields: make(map[string]struct{}),
|
||||
filters: make(map[string]func(interface{}) interface{}),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// NewWithAppInsightsConfig returns an initialised logrus hook for Application Insights
|
||||
func NewWithAppInsightsConfig(name string, conf *appinsights.TelemetryConfiguration) (*AppInsightsHook, error) {
|
||||
if conf == nil {
|
||||
return nil, fmt.Errorf("Nil configuration provided")
|
||||
}
|
||||
if conf.InstrumentationKey == "" {
|
||||
return nil, fmt.Errorf("InstrumentationKey is required in configuration")
|
||||
}
|
||||
telemetryClient := appinsights.NewTelemetryClientFromConfig(conf)
|
||||
if name != "" {
|
||||
telemetryClient.Context().Cloud().SetRoleName(name)
|
||||
}
|
||||
return &AppInsightsHook{
|
||||
client: telemetryClient,
|
||||
levels: defaultLevels,
|
||||
ignoreFields: make(map[string]struct{}),
|
||||
filters: make(map[string]func(interface{}) interface{}),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Levels returns logging level to fire this hook.
|
||||
func (hook *AppInsightsHook) Levels() []logrus.Level {
|
||||
return hook.levels
|
||||
}
|
||||
|
||||
// SetLevels sets logging level to fire this hook.
|
||||
func (hook *AppInsightsHook) SetLevels(levels []logrus.Level) {
|
||||
hook.levels = levels
|
||||
}
|
||||
|
||||
// SetAsync sets async flag for sending logs asynchronously.
|
||||
// If use this true, Fire() does not return error.
|
||||
func (hook *AppInsightsHook) SetAsync(async bool) {
|
||||
hook.async = async
|
||||
}
|
||||
|
||||
// AddIgnore adds field name to ignore.
|
||||
func (hook *AppInsightsHook) AddIgnore(name string) {
|
||||
hook.ignoreFields[name] = struct{}{}
|
||||
}
|
||||
|
||||
// AddFilter adds a custom filter function.
|
||||
func (hook *AppInsightsHook) AddFilter(name string, fn func(interface{}) interface{}) {
|
||||
hook.filters[name] = fn
|
||||
}
|
||||
|
||||
// Fire is invoked by logrus and sends log data to Application Insights.
|
||||
func (hook *AppInsightsHook) Fire(entry *logrus.Entry) error {
|
||||
if !hook.async {
|
||||
return hook.fire(entry)
|
||||
}
|
||||
// async - fire and forget
|
||||
go hook.fire(entry)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (hook *AppInsightsHook) fire(entry *logrus.Entry) error {
|
||||
trace, err := hook.buildTrace(entry)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hook.client.TrackTraceTelemetry(trace)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (hook *AppInsightsHook) buildTrace(entry *logrus.Entry) (*appinsights.TraceTelemetry, error) {
|
||||
// Add the message as a field if it isn't already
|
||||
if _, ok := entry.Data["message"]; !ok {
|
||||
entry.Data["message"] = entry.Message
|
||||
}
|
||||
|
||||
level := levelMap[entry.Level]
|
||||
trace := appinsights.NewTraceTelemetry(entry.Message, level)
|
||||
if trace == nil {
|
||||
return nil, fmt.Errorf("Could not create telemetry trace with entry %+v", entry)
|
||||
}
|
||||
for k, v := range entry.Data {
|
||||
if _, ok := hook.ignoreFields[k]; ok {
|
||||
continue
|
||||
}
|
||||
if fn, ok := hook.filters[k]; ok {
|
||||
v = fn(v) // apply custom filter
|
||||
} else {
|
||||
v = formatData(v) // use default formatter
|
||||
}
|
||||
vStr := fmt.Sprintf("%v", v)
|
||||
trace.SetProperty(k, vStr)
|
||||
}
|
||||
trace.SetProperty("source_level", entry.Level.String())
|
||||
trace.SetProperty("source_timestamp", entry.Time.String())
|
||||
return trace, nil
|
||||
}
|
||||
|
||||
// formatData returns value as a suitable format.
|
||||
func formatData(value interface{}) (formatted interface{}) {
|
||||
switch value := value.(type) {
|
||||
case json.Marshaler:
|
||||
return value
|
||||
case error:
|
||||
return value.Error()
|
||||
case fmt.Stringer:
|
||||
return value.String()
|
||||
default:
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
func stringPtr(str string) *string {
|
||||
return &str
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue