Dynamic Configuration Refactoring
This commit is contained in:
parent
d3ae88f108
commit
a09dfa3ce1
452 changed files with 21023 additions and 9419 deletions
22
vendor/github.com/Microsoft/ApplicationInsights-Go/LICENSE
generated
vendored
22
vendor/github.com/Microsoft/ApplicationInsights-Go/LICENSE
generated
vendored
|
@ -1,22 +0,0 @@
|
|||
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
122
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/bond.go
generated
vendored
|
@ -1,122 +0,0 @@
|
|||
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
132
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/client.go
generated
vendored
|
@ -1,132 +0,0 @@
|
|||
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
11
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/clock.go
generated
vendored
|
@ -1,11 +0,0 @@
|
|||
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
45
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/concurrentrandom.go
generated
vendored
|
@ -1,45 +0,0 @@
|
|||
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
19
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/configuration.go
generated
vendored
|
@ -1,19 +0,0 @@
|
|||
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
228
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/datacontracts.go
generated
vendored
|
@ -1,228 +0,0 @@
|
|||
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
64
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/diagnostics.go
generated
vendored
|
@ -1,64 +0,0 @@
|
|||
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
408
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/inmemorychannel.go
generated
vendored
|
@ -1,408 +0,0 @@
|
|||
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
45
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/jsonserializer.go
generated
vendored
|
@ -1,45 +0,0 @@
|
|||
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
8
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/package.go
generated
vendored
|
@ -1,8 +0,0 @@
|
|||
// 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
47
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/telemetrychannel.go
generated
vendored
|
@ -1,47 +0,0 @@
|
|||
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
400
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/telemetrycontext.go
generated
vendored
|
@ -1,400 +0,0 @@
|
|||
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
144
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/throttle.go
generated
vendored
|
@ -1,144 +0,0 @@
|
|||
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
237
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/transmitter.go
generated
vendored
|
@ -1,237 +0,0 @@
|
|||
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
|
||||
}
|
20
vendor/github.com/containous/alice/LICENSE
generated
vendored
Normal file
20
vendor/github.com/containous/alice/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Justinas Stankevicius
|
||||
|
||||
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.
|
116
vendor/github.com/containous/alice/chain.go
generated
vendored
Normal file
116
vendor/github.com/containous/alice/chain.go
generated
vendored
Normal file
|
@ -0,0 +1,116 @@
|
|||
// Package alice provides a convenient way to chain http handlers.
|
||||
package alice
|
||||
|
||||
import "net/http"
|
||||
|
||||
// Constructor A constructor for a piece of middleware.
|
||||
// Some middleware use this constructor out of the box,
|
||||
// so in most cases you can just pass somepackage.New
|
||||
type Constructor func(http.Handler) (http.Handler, error)
|
||||
|
||||
// Chain acts as a list of http.Handler constructors.
|
||||
// Chain is effectively immutable:
|
||||
// once created, it will always hold
|
||||
// the same set of constructors in the same order.
|
||||
type Chain struct {
|
||||
constructors []Constructor
|
||||
}
|
||||
|
||||
// New creates a new chain,
|
||||
// memorizing the given list of middleware constructors.
|
||||
// New serves no other function,
|
||||
// constructors are only called upon a call to Then().
|
||||
func New(constructors ...Constructor) Chain {
|
||||
return Chain{constructors: constructors}
|
||||
}
|
||||
|
||||
// Then chains the middleware and returns the final http.Handler.
|
||||
// New(m1, m2, m3).Then(h)
|
||||
// is equivalent to:
|
||||
// m1(m2(m3(h)))
|
||||
// When the request comes in, it will be passed to m1, then m2, then m3
|
||||
// and finally, the given handler
|
||||
// (assuming every middleware calls the following one).
|
||||
//
|
||||
// A chain can be safely reused by calling Then() several times.
|
||||
// stdStack := alice.New(ratelimitHandler, csrfHandler)
|
||||
// indexPipe = stdStack.Then(indexHandler)
|
||||
// authPipe = stdStack.Then(authHandler)
|
||||
// Note that constructors are called on every call to Then()
|
||||
// and thus several instances of the same middleware will be created
|
||||
// when a chain is reused in this way.
|
||||
// For proper middleware, this should cause no problems.
|
||||
//
|
||||
// Then() treats nil as http.DefaultServeMux.
|
||||
func (c Chain) Then(h http.Handler) (http.Handler, error) {
|
||||
if h == nil {
|
||||
h = http.DefaultServeMux
|
||||
}
|
||||
|
||||
for i := range c.constructors {
|
||||
handler, err := c.constructors[len(c.constructors)-1-i](h)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h = handler
|
||||
}
|
||||
|
||||
return h, nil
|
||||
}
|
||||
|
||||
// ThenFunc works identically to Then, but takes
|
||||
// a HandlerFunc instead of a Handler.
|
||||
//
|
||||
// The following two statements are equivalent:
|
||||
// c.Then(http.HandlerFunc(fn))
|
||||
// c.ThenFunc(fn)
|
||||
//
|
||||
// ThenFunc provides all the guarantees of Then.
|
||||
func (c Chain) ThenFunc(fn http.HandlerFunc) (http.Handler, error) {
|
||||
if fn == nil {
|
||||
return c.Then(nil)
|
||||
}
|
||||
return c.Then(fn)
|
||||
}
|
||||
|
||||
// Append extends a chain, adding the specified constructors
|
||||
// as the last ones in the request flow.
|
||||
//
|
||||
// Append returns a new chain, leaving the original one untouched.
|
||||
//
|
||||
// stdChain := alice.New(m1, m2)
|
||||
// extChain := stdChain.Append(m3, m4)
|
||||
// // requests in stdChain go m1 -> m2
|
||||
// // requests in extChain go m1 -> m2 -> m3 -> m4
|
||||
func (c Chain) Append(constructors ...Constructor) Chain {
|
||||
newCons := make([]Constructor, 0, len(c.constructors)+len(constructors))
|
||||
newCons = append(newCons, c.constructors...)
|
||||
newCons = append(newCons, constructors...)
|
||||
|
||||
return Chain{newCons}
|
||||
}
|
||||
|
||||
// Extend extends a chain by adding the specified chain
|
||||
// as the last one in the request flow.
|
||||
//
|
||||
// Extend returns a new chain, leaving the original one untouched.
|
||||
//
|
||||
// stdChain := alice.New(m1, m2)
|
||||
// ext1Chain := alice.New(m3, m4)
|
||||
// ext2Chain := stdChain.Extend(ext1Chain)
|
||||
// // requests in stdChain go m1 -> m2
|
||||
// // requests in ext1Chain go m3 -> m4
|
||||
// // requests in ext2Chain go m1 -> m2 -> m3 -> m4
|
||||
//
|
||||
// Another example:
|
||||
// aHtmlAfterNosurf := alice.New(m2)
|
||||
// aHtml := alice.New(m1, func(h http.Handler) http.Handler {
|
||||
// csrf := nosurf.New(h)
|
||||
// csrf.SetFailureHandler(aHtmlAfterNosurf.ThenFunc(csrfFail))
|
||||
// return csrf
|
||||
// }).Extend(aHtmlAfterNosurf)
|
||||
// // requests to aHtml hitting nosurfs success handler go m1 -> nosurf -> m2 -> target-handler
|
||||
// // requests to aHtml hitting nosurfs failure handler go m1 -> nosurf -> m2 -> csrfFail
|
||||
func (c Chain) Extend(chain Chain) Chain {
|
||||
return c.Append(chain.constructors...)
|
||||
}
|
201
vendor/github.com/containous/traefik-extra-service-fabric/LICENSE
generated
vendored
201
vendor/github.com/containous/traefik-extra-service-fabric/LICENSE
generated
vendored
|
@ -1,201 +0,0 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2017 Containous
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
306
vendor/github.com/containous/traefik-extra-service-fabric/servicefabric.go
generated
vendored
306
vendor/github.com/containous/traefik-extra-service-fabric/servicefabric.go
generated
vendored
|
@ -1,306 +0,0 @@
|
|||
package servicefabric
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
"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"
|
||||
)
|
||||
|
||||
var _ provider.Provider = (*Provider)(nil)
|
||||
|
||||
const traefikServiceFabricExtensionKey = "Traefik"
|
||||
|
||||
const (
|
||||
kindStateful = "Stateful"
|
||||
kindStateless = "Stateless"
|
||||
)
|
||||
|
||||
// Provider holds for configuration for the provider
|
||||
type Provider struct {
|
||||
provider.BaseProvider `mapstructure:",squash"`
|
||||
ClusterManagementURL string `description:"Service Fabric API endpoint"`
|
||||
APIVersion string `description:"Service Fabric API version" 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"`
|
||||
sfClient sfClient
|
||||
}
|
||||
|
||||
// Init the provider
|
||||
func (p *Provider) Init(constraints types.Constraints) error {
|
||||
err := p.BaseProvider.Init(constraints)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if p.APIVersion == "" {
|
||||
p.APIVersion = sf.DefaultAPIVersion
|
||||
}
|
||||
|
||||
tlsConfig, err := p.TLS.CreateTLSConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.sfClient, err = sf.NewClient(http.DefaultClient, p.ClusterManagementURL, p.APIVersion, tlsConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if p.RefreshSeconds <= 0 {
|
||||
p.RefreshSeconds = flaeg.Duration(10 * 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 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) error {
|
||||
return p.updateConfig(configurationChan, pool, time.Duration(p.RefreshSeconds))
|
||||
}
|
||||
|
||||
func (p *Provider) updateConfig(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, pollInterval time.Duration) error {
|
||||
pool.Go(func(stop chan bool) {
|
||||
operation := func() error {
|
||||
ticker := time.NewTicker(pollInterval)
|
||||
for range ticker.C {
|
||||
select {
|
||||
case shouldStop := <-stop:
|
||||
if shouldStop {
|
||||
ticker.Stop()
|
||||
return nil
|
||||
}
|
||||
default:
|
||||
log.Info("Checking service fabric config")
|
||||
}
|
||||
|
||||
configuration, err := p.getConfiguration()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
configurationChan <- types.ConfigMessage{
|
||||
ProviderName: "servicefabric",
|
||||
Configuration: configuration,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
notify := func(err error, time time.Duration) {
|
||||
log.Errorf("Provider connection error: %v; retrying in %s", err, time)
|
||||
}
|
||||
err := backoff.RetryNotify(safe.OperationWithRecover(operation), job.NewBackOff(backoff.NewExponentialBackOff()), notify)
|
||||
if err != nil {
|
||||
log.Errorf("Cannot connect to Provider: %v", err)
|
||||
}
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Provider) getConfiguration() (*types.Configuration, error) {
|
||||
services, err := getClusterServices(p.sfClient)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return p.buildConfiguration(services)
|
||||
}
|
||||
|
||||
func getClusterServices(sfClient sfClient) ([]ServiceItemExtended, error) {
|
||||
apps, err := sfClient.GetApplications()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var results []ServiceItemExtended
|
||||
for _, app := range apps.Items {
|
||||
services, err := sfClient.GetServices(app.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, service := range services.Items {
|
||||
item := ServiceItemExtended{
|
||||
ServiceItem: service,
|
||||
Application: app,
|
||||
}
|
||||
|
||||
if labels, err := getLabels(sfClient, &service, &app); err != nil {
|
||||
log.Error(err)
|
||||
} else {
|
||||
item.Labels = labels
|
||||
}
|
||||
|
||||
if partitions, err := sfClient.GetPartitions(app.ID, service.ID); err != nil {
|
||||
log.Error(err)
|
||||
} else {
|
||||
for _, partition := range partitions.Items {
|
||||
partitionExt := PartitionItemExtended{PartitionItem: partition}
|
||||
|
||||
if isStateful(item) {
|
||||
partitionExt.Replicas = getValidReplicas(sfClient, app, service, partition)
|
||||
} else if isStateless(item) {
|
||||
partitionExt.Instances = getValidInstances(sfClient, app, service, partition)
|
||||
} else {
|
||||
log.Errorf("Unsupported service kind %s in service %s", partition.ServiceKind, service.Name)
|
||||
continue
|
||||
}
|
||||
|
||||
item.Partitions = append(item.Partitions, partitionExt)
|
||||
}
|
||||
}
|
||||
|
||||
results = append(results, item)
|
||||
}
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func getValidReplicas(sfClient sfClient, app sf.ApplicationItem, service sf.ServiceItem, partition sf.PartitionItem) []sf.ReplicaItem {
|
||||
var validReplicas []sf.ReplicaItem
|
||||
|
||||
if replicas, err := sfClient.GetReplicas(app.ID, service.ID, partition.PartitionInformation.ID); err != nil {
|
||||
log.Error(err)
|
||||
} else {
|
||||
for _, instance := range replicas.Items {
|
||||
if isHealthy(instance.ReplicaItemBase) && hasHTTPEndpoint(instance.ReplicaItemBase) {
|
||||
validReplicas = append(validReplicas, instance)
|
||||
}
|
||||
}
|
||||
}
|
||||
return validReplicas
|
||||
}
|
||||
|
||||
func getValidInstances(sfClient sfClient, app sf.ApplicationItem, service sf.ServiceItem, partition sf.PartitionItem) []sf.InstanceItem {
|
||||
var validInstances []sf.InstanceItem
|
||||
|
||||
if instances, err := sfClient.GetInstances(app.ID, service.ID, partition.PartitionInformation.ID); err != nil {
|
||||
log.Error(err)
|
||||
} else {
|
||||
for _, instance := range instances.Items {
|
||||
if isHealthy(instance.ReplicaItemBase) && hasHTTPEndpoint(instance.ReplicaItemBase) {
|
||||
validInstances = append(validInstances, instance)
|
||||
}
|
||||
}
|
||||
}
|
||||
return validInstances
|
||||
}
|
||||
|
||||
func isHealthy(instanceData *sf.ReplicaItemBase) bool {
|
||||
return instanceData != nil && (instanceData.ReplicaStatus == "Ready" && instanceData.HealthState != "Error")
|
||||
}
|
||||
|
||||
func hasHTTPEndpoint(instanceData *sf.ReplicaItemBase) bool {
|
||||
_, err := getReplicaDefaultEndpoint(instanceData)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func getReplicaDefaultEndpoint(replicaData *sf.ReplicaItemBase) (string, error) {
|
||||
endpoints, err := decodeEndpointData(replicaData.Address)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var defaultHTTPEndpoint string
|
||||
for _, v := range endpoints {
|
||||
if strings.Contains(v, "http") {
|
||||
defaultHTTPEndpoint = v
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if len(defaultHTTPEndpoint) == 0 {
|
||||
return "", errors.New("no default endpoint found")
|
||||
}
|
||||
return defaultHTTPEndpoint, nil
|
||||
}
|
||||
|
||||
func decodeEndpointData(endpointData string) (map[string]string, error) {
|
||||
var endpointsMap map[string]map[string]string
|
||||
|
||||
if endpointData == "" {
|
||||
return nil, errors.New("endpoint data is empty")
|
||||
}
|
||||
|
||||
err := json.Unmarshal([]byte(endpointData), &endpointsMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
endpoints, endpointsExist := endpointsMap["Endpoints"]
|
||||
if !endpointsExist {
|
||||
return nil, errors.New("endpoint doesn't exist in endpoint data")
|
||||
}
|
||||
|
||||
return endpoints, nil
|
||||
}
|
||||
|
||||
func isStateful(service ServiceItemExtended) bool {
|
||||
return service.ServiceKind == kindStateful
|
||||
}
|
||||
|
||||
func isStateless(service ServiceItemExtended) bool {
|
||||
return service.ServiceKind == kindStateless
|
||||
}
|
||||
|
||||
// Return a set of labels from the Extension and Property manager
|
||||
// Allow Extension labels to disable importing labels from the property manager.
|
||||
func getLabels(sfClient sfClient, service *sf.ServiceItem, app *sf.ApplicationItem) (map[string]string, error) {
|
||||
labels, err := sfClient.GetServiceExtensionMap(service, app, traefikServiceFabricExtensionKey)
|
||||
if err != nil {
|
||||
log.Errorf("Error retrieving serviceExtensionMap: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if label.GetBoolValue(labels, traefikSFEnableLabelOverrides, traefikSFEnableLabelOverridesDefault) {
|
||||
if exists, properties, err := sfClient.GetProperties(service.ID); err == nil && exists {
|
||||
for key, value := range properties {
|
||||
labels[key] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
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)
|
||||
}
|
174
vendor/github.com/containous/traefik-extra-service-fabric/servicefabric_config.go
generated
vendored
174
vendor/github.com/containous/traefik-extra-service-fabric/servicefabric_config.go
generated
vendored
|
@ -1,174 +0,0 @@
|
|||
package servicefabric
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/containous/traefik/log"
|
||||
"github.com/containous/traefik/provider"
|
||||
"github.com/containous/traefik/provider/label"
|
||||
"github.com/containous/traefik/types"
|
||||
sf "github.com/jjcollinge/servicefabric"
|
||||
)
|
||||
|
||||
func (p *Provider) buildConfiguration(services []ServiceItemExtended) (*types.Configuration, error) {
|
||||
var sfFuncMap = template.FuncMap{
|
||||
// Services
|
||||
"getServices": getServices,
|
||||
"hasLabel": hasService,
|
||||
"getLabelValue": getServiceStringLabel,
|
||||
"getLabelsWithPrefix": getServiceLabelsWithPrefix,
|
||||
"isPrimary": isPrimary,
|
||||
"isStateful": isStateful,
|
||||
"isStateless": isStateless,
|
||||
"isEnabled": getFuncBoolLabel(label.TraefikEnable, false),
|
||||
"getBackendName": getBackendName,
|
||||
"getDefaultEndpoint": getDefaultEndpoint,
|
||||
"getNamedEndpoint": getNamedEndpoint, // FIXME unused
|
||||
"getApplicationParameter": getApplicationParameter, // FIXME unused
|
||||
"doesAppParamContain": doesAppParamContain, // FIXME unused
|
||||
"filterServicesByLabelValue": filterServicesByLabelValue, // FIXME unused
|
||||
|
||||
// Backend functions
|
||||
"getWeight": getFuncServiceIntLabel(label.TraefikWeight, label.DefaultWeight),
|
||||
"getProtocol": getFuncServiceStringLabel(label.TraefikProtocol, label.DefaultProtocol),
|
||||
"getMaxConn": getMaxConn,
|
||||
"getHealthCheck": getHealthCheck,
|
||||
"getCircuitBreaker": getCircuitBreaker,
|
||||
"getLoadBalancer": getLoadBalancer,
|
||||
|
||||
// Frontend Functions
|
||||
"getPriority": getFuncServiceIntLabel(label.TraefikFrontendPriority, label.DefaultFrontendPriority),
|
||||
"getPassHostHeader": getFuncServiceBoolLabel(label.TraefikFrontendPassHostHeader, label.DefaultPassHostHeader),
|
||||
"getPassTLSCert": getFuncBoolLabel(label.TraefikFrontendPassTLSCert, label.DefaultPassTLSCert),
|
||||
"getEntryPoints": getFuncServiceSliceStringLabel(label.TraefikFrontendEntryPoints),
|
||||
"getBasicAuth": getFuncServiceSliceStringLabel(label.TraefikFrontendAuthBasic),
|
||||
"getFrontendRules": getFuncServiceLabelWithPrefix(label.TraefikFrontendRule),
|
||||
"getWhiteList": getWhiteList,
|
||||
"getHeaders": getHeaders,
|
||||
"getRedirect": getRedirect,
|
||||
|
||||
// SF Service Grouping
|
||||
"getGroupedServices": getFuncServicesGroupedByLabel(traefikSFGroupName),
|
||||
"getGroupedWeight": getFuncServiceStringLabel(traefikSFGroupWeight, "1"),
|
||||
}
|
||||
|
||||
templateObjects := struct {
|
||||
Services []ServiceItemExtended
|
||||
}{
|
||||
Services: services,
|
||||
}
|
||||
|
||||
return p.GetConfiguration(tmpl, sfFuncMap, templateObjects)
|
||||
}
|
||||
|
||||
func isPrimary(instance replicaInstance) bool {
|
||||
_, data := instance.GetReplicaData()
|
||||
return data.ReplicaRole == "Primary"
|
||||
}
|
||||
|
||||
func getBackendName(service ServiceItemExtended, partition PartitionItemExtended) string {
|
||||
return provider.Normalize(service.Name + partition.PartitionInformation.ID)
|
||||
}
|
||||
|
||||
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, err)
|
||||
return ""
|
||||
}
|
||||
return endpoint
|
||||
}
|
||||
|
||||
func getNamedEndpoint(instance replicaInstance, endpointName string) string {
|
||||
id, data := instance.GetReplicaData()
|
||||
endpoint, err := getReplicaNamedEndpoint(data, endpointName)
|
||||
if err != nil {
|
||||
log.Warnf("No names endpoint of %s for replica %s in endpointData: %s. Error: %v", endpointName, id, data.Address, err)
|
||||
return ""
|
||||
}
|
||||
return endpoint
|
||||
}
|
||||
|
||||
func getReplicaNamedEndpoint(replicaData *sf.ReplicaItemBase, endpointName string) (string, error) {
|
||||
endpoints, err := decodeEndpointData(replicaData.Address)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
endpoint, exists := endpoints[endpointName]
|
||||
if !exists {
|
||||
return "", errors.New("endpoint doesn't exist")
|
||||
}
|
||||
return endpoint, nil
|
||||
}
|
||||
|
||||
func getApplicationParameter(app sf.ApplicationItem, key string) string {
|
||||
for _, param := range app.Parameters {
|
||||
if param.Key == key {
|
||||
return param.Value
|
||||
}
|
||||
}
|
||||
log.Errorf("Parameter %s doesn't exist in app %s", key, app.Name)
|
||||
return ""
|
||||
}
|
||||
|
||||
func getServices(services []ServiceItemExtended, key string) map[string][]ServiceItemExtended {
|
||||
result := map[string][]ServiceItemExtended{}
|
||||
for _, service := range services {
|
||||
if value, exists := service.Labels[key]; exists {
|
||||
if matchingServices, hasKeyAlready := result[value]; hasKeyAlready {
|
||||
result[value] = append(matchingServices, service)
|
||||
} else {
|
||||
result[value] = []ServiceItemExtended{service}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func doesAppParamContain(app sf.ApplicationItem, key, shouldContain string) bool {
|
||||
value := getApplicationParameter(app, key)
|
||||
return strings.Contains(value, shouldContain)
|
||||
}
|
||||
|
||||
func filterServicesByLabelValue(services []ServiceItemExtended, key, expectedValue string) []ServiceItemExtended {
|
||||
var srvWithLabel []ServiceItemExtended
|
||||
for _, service := range services {
|
||||
value, exists := service.Labels[key]
|
||||
if exists && value == expectedValue {
|
||||
srvWithLabel = append(srvWithLabel, service)
|
||||
}
|
||||
}
|
||||
return srvWithLabel
|
||||
}
|
||||
|
||||
func getHeaders(service ServiceItemExtended) *types.Headers {
|
||||
return label.GetHeaders(service.Labels)
|
||||
}
|
||||
|
||||
func getWhiteList(service ServiceItemExtended) *types.WhiteList {
|
||||
return label.GetWhiteList(service.Labels)
|
||||
}
|
||||
|
||||
func getRedirect(service ServiceItemExtended) *types.Redirect {
|
||||
return label.GetRedirect(service.Labels)
|
||||
}
|
||||
|
||||
func getMaxConn(service ServiceItemExtended) *types.MaxConn {
|
||||
return label.GetMaxConn(service.Labels)
|
||||
}
|
||||
|
||||
func getHealthCheck(service ServiceItemExtended) *types.HealthCheck {
|
||||
return label.GetHealthCheck(service.Labels)
|
||||
}
|
||||
|
||||
func getCircuitBreaker(service ServiceItemExtended) *types.CircuitBreaker {
|
||||
return label.GetCircuitBreaker(service.Labels)
|
||||
}
|
||||
|
||||
func getLoadBalancer(service ServiceItemExtended) *types.LoadBalancer {
|
||||
return label.GetLoadBalancer(service.Labels)
|
||||
}
|
75
vendor/github.com/containous/traefik-extra-service-fabric/servicefabric_labelfuncs.go
generated
vendored
75
vendor/github.com/containous/traefik-extra-service-fabric/servicefabric_labelfuncs.go
generated
vendored
|
@ -1,75 +0,0 @@
|
|||
package servicefabric
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/containous/traefik/provider/label"
|
||||
)
|
||||
|
||||
// SF Specific Traefik Labels
|
||||
const (
|
||||
traefikSFGroupName = "traefik.servicefabric.groupname"
|
||||
traefikSFGroupWeight = "traefik.servicefabric.groupweight"
|
||||
traefikSFEnableLabelOverrides = "traefik.servicefabric.enablelabeloverrides"
|
||||
traefikSFEnableLabelOverridesDefault = true
|
||||
)
|
||||
|
||||
func getFuncBoolLabel(labelName string, defaultValue bool) func(service ServiceItemExtended) bool {
|
||||
return func(service ServiceItemExtended) bool {
|
||||
return label.GetBoolValue(service.Labels, labelName, defaultValue)
|
||||
}
|
||||
}
|
||||
|
||||
func getServiceStringLabel(service ServiceItemExtended, labelName string, defaultValue string) string {
|
||||
return label.GetStringValue(service.Labels, labelName, defaultValue)
|
||||
}
|
||||
|
||||
func getFuncServiceStringLabel(labelName string, defaultValue string) func(service ServiceItemExtended) string {
|
||||
return func(service ServiceItemExtended) string {
|
||||
return label.GetStringValue(service.Labels, labelName, defaultValue)
|
||||
}
|
||||
}
|
||||
|
||||
func getFuncServiceIntLabel(labelName string, defaultValue int) func(service ServiceItemExtended) int {
|
||||
return func(service ServiceItemExtended) int {
|
||||
return label.GetIntValue(service.Labels, labelName, defaultValue)
|
||||
}
|
||||
}
|
||||
|
||||
func getFuncServiceBoolLabel(labelName string, defaultValue bool) func(service ServiceItemExtended) bool {
|
||||
return func(service ServiceItemExtended) bool {
|
||||
return label.GetBoolValue(service.Labels, labelName, defaultValue)
|
||||
}
|
||||
}
|
||||
|
||||
func getFuncServiceSliceStringLabel(labelName string) func(service ServiceItemExtended) []string {
|
||||
return func(service ServiceItemExtended) []string {
|
||||
return label.GetSliceStringValue(service.Labels, labelName)
|
||||
}
|
||||
}
|
||||
|
||||
func hasService(service ServiceItemExtended, labelName string) bool {
|
||||
return label.Has(service.Labels, labelName)
|
||||
}
|
||||
|
||||
func getFuncServiceLabelWithPrefix(labelName string) func(service ServiceItemExtended) map[string]string {
|
||||
return func(service ServiceItemExtended) map[string]string {
|
||||
return getServiceLabelsWithPrefix(service, labelName)
|
||||
}
|
||||
}
|
||||
|
||||
func getFuncServicesGroupedByLabel(labelName string) func(services []ServiceItemExtended) map[string][]ServiceItemExtended {
|
||||
return func(services []ServiceItemExtended) map[string][]ServiceItemExtended {
|
||||
return getServices(services, labelName)
|
||||
}
|
||||
}
|
||||
|
||||
func getServiceLabelsWithPrefix(service ServiceItemExtended, prefix string) map[string]string {
|
||||
results := make(map[string]string)
|
||||
for k, v := range service.Labels {
|
||||
if strings.HasPrefix(k, prefix) {
|
||||
results[k] = v
|
||||
}
|
||||
}
|
||||
return results
|
||||
}
|
228
vendor/github.com/containous/traefik-extra-service-fabric/servicefabric_tmpl.go
generated
vendored
228
vendor/github.com/containous/traefik-extra-service-fabric/servicefabric_tmpl.go
generated
vendored
|
@ -1,228 +0,0 @@
|
|||
package servicefabric
|
||||
|
||||
const tmpl = `
|
||||
[backends]
|
||||
{{range $aggName, $aggServices := getGroupedServices .Services }}
|
||||
[backends."{{ $aggName }}"]
|
||||
{{range $service := $aggServices }}
|
||||
{{range $partition := $service.Partitions }}
|
||||
{{range $instance := $partition.Instances }}
|
||||
[backends."{{ $aggName }}".servers."{{ $service.ID }}-{{ $instance.ID }}"]
|
||||
url = "{{ getDefaultEndpoint $instance }}"
|
||||
weight = {{ getGroupedWeight $service }}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{range $service := .Services }}
|
||||
{{if isEnabled $service }}
|
||||
{{range $partition := $service.Partitions }}
|
||||
|
||||
{{if isStateless $service }}
|
||||
|
||||
{{ $backendName := $service.Name }}
|
||||
[backends."{{ $backendName }}"]
|
||||
|
||||
{{ $circuitBreaker := getCircuitBreaker $service }}
|
||||
{{if $circuitBreaker }}
|
||||
[backends."{{ $backendName }}".circuitBreaker]
|
||||
expression = "{{ $circuitBreaker.Expression }}"
|
||||
{{end}}
|
||||
|
||||
{{ $loadBalancer := getLoadBalancer $service }}
|
||||
{{if $loadBalancer }}
|
||||
[backends."{{ $backendName }}".loadBalancer]
|
||||
method = "{{ $loadBalancer.Method }}"
|
||||
sticky = {{ $loadBalancer.Sticky }}
|
||||
{{if $loadBalancer.Stickiness }}
|
||||
[backends."{{ $backendName }}".loadBalancer.stickiness]
|
||||
cookieName = "{{ $loadBalancer.Stickiness.CookieName }}"
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{ $maxConn := getMaxConn $service }}
|
||||
{{if $maxConn }}
|
||||
[backends."{{ $backendName }}".maxConn]
|
||||
extractorFunc = "{{ $maxConn.ExtractorFunc }}"
|
||||
amount = {{ $maxConn.Amount }}
|
||||
{{end}}
|
||||
|
||||
{{ $healthCheck := getHealthCheck $service }}
|
||||
{{if $healthCheck }}
|
||||
[backends."{{ $backendName }}".healthCheck]
|
||||
path = "{{ $healthCheck.Path }}"
|
||||
port = {{ $healthCheck.Port }}
|
||||
interval = "{{ $healthCheck.Interval }}"
|
||||
hostname = "{{ $healthCheck.Hostname }}"
|
||||
{{if $healthCheck.Headers }}
|
||||
[backends."{{ $backendName }}".healthCheck.headers]
|
||||
{{range $k, $v := $healthCheck.Headers }}
|
||||
{{$k}} = "{{$v}}"
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{range $instance := $partition.Instances}}
|
||||
[backends."{{ $service.Name }}".servers."{{ $instance.ID }}"]
|
||||
url = "{{ getDefaultEndpoint $instance }}"
|
||||
weight = {{ getWeight $service }}
|
||||
{{end}}
|
||||
|
||||
{{else if isStateful $service}}
|
||||
|
||||
{{range $replica := $partition.Replicas}}
|
||||
{{if isPrimary $replica}}
|
||||
{{ $backendName := getBackendName $service $partition }}
|
||||
[backends."{{ $backendName }}".servers."{{ $replica.ID }}"]
|
||||
url = "{{ getDefaultEndpoint $replica }}"
|
||||
weight = 1
|
||||
|
||||
[backends."{{$backendName}}".LoadBalancer]
|
||||
method = "drr"
|
||||
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{end}}
|
||||
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
[frontends]
|
||||
{{range $groupName, $groupServices := getGroupedServices .Services }}
|
||||
{{ $service := index $groupServices 0 }}
|
||||
[frontends."{{ $groupName }}"]
|
||||
backend = "{{ $groupName }}"
|
||||
priority = 50
|
||||
|
||||
{{range $key, $value := getFrontendRules $service }}
|
||||
[frontends."{{ $groupName }}".routes."{{ $key }}"]
|
||||
rule = "{{ $value }}"
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{range $service := .Services }}
|
||||
{{if isEnabled $service }}
|
||||
{{ $frontendName := $service.Name }}
|
||||
|
||||
{{if isStateless $service }}
|
||||
|
||||
[frontends."frontend-{{ $frontendName }}"]
|
||||
backend = "{{ $service.Name }}"
|
||||
passHostHeader = {{ getPassHostHeader $service }}
|
||||
passTLSCert = {{ getPassTLSCert $service }}
|
||||
priority = {{ getPriority $service }}
|
||||
|
||||
{{ $entryPoints := getEntryPoints $service }}
|
||||
{{if $entryPoints }}
|
||||
entryPoints = [{{range $entryPoints }}
|
||||
"{{.}}",
|
||||
{{end}}]
|
||||
{{end}}
|
||||
|
||||
{{ $basicAuth := getBasicAuth $service }}
|
||||
{{if $basicAuth }}
|
||||
basicAuth = [{{range $basicAuth }}
|
||||
"{{.}}",
|
||||
{{end}}]
|
||||
{{end}}
|
||||
|
||||
{{ $whitelist := getWhiteList $service }}
|
||||
{{if $whitelist }}
|
||||
[frontends."frontend-{{ $frontendName }}".whiteList]
|
||||
sourceRange = [{{range $whitelist.SourceRange }}
|
||||
"{{.}}",
|
||||
{{end}}]
|
||||
useXForwardedFor = {{ $whitelist.UseXForwardedFor }}
|
||||
{{end}}
|
||||
|
||||
{{ $redirect := getRedirect $service }}
|
||||
{{if $redirect }}
|
||||
[frontends."frontend-{{ $frontendName }}".redirect]
|
||||
entryPoint = "{{ $redirect.EntryPoint }}"
|
||||
regex = "{{ $redirect.Regex }}"
|
||||
replacement = "{{ $redirect.Replacement }}"
|
||||
permanent = {{ $redirect.Permanent }}
|
||||
{{end}}
|
||||
|
||||
{{ $headers := getHeaders $service }}
|
||||
{{if $headers }}
|
||||
[frontends."frontend-{{ $frontendName }}".headers]
|
||||
SSLRedirect = {{ $headers.SSLRedirect }}
|
||||
SSLTemporaryRedirect = {{ $headers.SSLTemporaryRedirect }}
|
||||
SSLHost = "{{ $headers.SSLHost }}"
|
||||
STSSeconds = {{ $headers.STSSeconds }}
|
||||
STSIncludeSubdomains = {{ $headers.STSIncludeSubdomains }}
|
||||
STSPreload = {{ $headers.STSPreload }}
|
||||
ForceSTSHeader = {{ $headers.ForceSTSHeader }}
|
||||
FrameDeny = {{ $headers.FrameDeny }}
|
||||
CustomFrameOptionsValue = "{{ $headers.CustomFrameOptionsValue }}"
|
||||
ContentTypeNosniff = {{ $headers.ContentTypeNosniff }}
|
||||
BrowserXSSFilter = {{ $headers.BrowserXSSFilter }}
|
||||
CustomBrowserXSSValue = "{{ $headers.CustomBrowserXSSValue }}"
|
||||
ContentSecurityPolicy = "{{ $headers.ContentSecurityPolicy }}"
|
||||
PublicKey = "{{ $headers.PublicKey }}"
|
||||
ReferrerPolicy = "{{ $headers.ReferrerPolicy }}"
|
||||
IsDevelopment = {{ $headers.IsDevelopment }}
|
||||
|
||||
{{if $headers.AllowedHosts }}
|
||||
AllowedHosts = [{{range $headers.AllowedHosts }}
|
||||
"{{.}}",
|
||||
{{end}}]
|
||||
{{end}}
|
||||
|
||||
{{if $headers.HostsProxyHeaders }}
|
||||
HostsProxyHeaders = [{{range $headers.HostsProxyHeaders }}
|
||||
"{{.}}",
|
||||
{{end}}]
|
||||
{{end}}
|
||||
|
||||
{{if $headers.CustomRequestHeaders }}
|
||||
[frontends."frontend-{{ $frontendName }}".headers.customRequestHeaders]
|
||||
{{range $k, $v := $headers.CustomRequestHeaders }}
|
||||
{{$k}} = "{{$v}}"
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{if $headers.CustomResponseHeaders }}
|
||||
[frontends."frontend-{{ $frontendName }}".headers.customResponseHeaders]
|
||||
{{range $k, $v := $headers.CustomResponseHeaders }}
|
||||
{{$k}} = "{{$v}}"
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{if $headers.SSLProxyHeaders }}
|
||||
[frontends."frontend-{{ $frontendName }}".headers.SSLProxyHeaders]
|
||||
{{range $k, $v := $headers.SSLProxyHeaders }}
|
||||
{{$k}} = "{{$v}}"
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{range $key, $value := getFrontendRules $service }}
|
||||
[frontends."frontend-{{ $frontendName }}".routes."{{ $key }}"]
|
||||
rule = "{{ $value }}"
|
||||
{{end}}
|
||||
|
||||
{{else if isStateful $service }}
|
||||
|
||||
{{range $partition := $service.Partitions }}
|
||||
{{ $partitionId := $partition.PartitionInformation.ID }}
|
||||
|
||||
{{ $rule := getLabelValue $service (print "traefik.frontend.rule.partition." $partitionId) "" }}
|
||||
{{if $rule }}
|
||||
[frontends."{{ $service.Name }}/{{ $partitionId }}"]
|
||||
backend = "{{ getBackendName $service $partition }}"
|
||||
|
||||
[frontends."{{ $service.Name }}/{{ $partitionId }}".routes.default]
|
||||
rule = "{{ $rule }}"
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{end}}
|
||||
|
||||
{{end}}
|
||||
{{end}}
|
||||
`
|
42
vendor/github.com/containous/traefik-extra-service-fabric/types.go
generated
vendored
42
vendor/github.com/containous/traefik-extra-service-fabric/types.go
generated
vendored
|
@ -1,42 +0,0 @@
|
|||
package servicefabric
|
||||
|
||||
import (
|
||||
sf "github.com/jjcollinge/servicefabric"
|
||||
)
|
||||
|
||||
// ServiceItemExtended provides a flattened view
|
||||
// of the service with details of the application
|
||||
// it belongs too and the replicas/partitions
|
||||
type ServiceItemExtended struct {
|
||||
sf.ServiceItem
|
||||
Application sf.ApplicationItem
|
||||
Partitions []PartitionItemExtended
|
||||
Labels map[string]string
|
||||
}
|
||||
|
||||
// PartitionItemExtended provides a flattened view
|
||||
// of a services partitions
|
||||
type PartitionItemExtended struct {
|
||||
sf.PartitionItem
|
||||
Replicas []sf.ReplicaItem
|
||||
Instances []sf.InstanceItem
|
||||
}
|
||||
|
||||
// sfClient is an interface for Service Fabric client's to implement.
|
||||
// This is purposely a subset of the total Service Fabric API surface.
|
||||
type sfClient interface {
|
||||
GetApplications() (*sf.ApplicationItemsPage, error)
|
||||
GetServices(appName string) (*sf.ServiceItemsPage, error)
|
||||
GetPartitions(appName, serviceName string) (*sf.PartitionItemsPage, error)
|
||||
GetReplicas(appName, serviceName, partitionName string) (*sf.ReplicaItemsPage, error)
|
||||
GetInstances(appName, serviceName, partitionName string) (*sf.InstanceItemsPage, error)
|
||||
GetServiceExtensionMap(service *sf.ServiceItem, app *sf.ApplicationItem, extensionKey string) (map[string]string, error)
|
||||
GetServiceLabels(service *sf.ServiceItem, app *sf.ApplicationItem, prefix string) (map[string]string, error)
|
||||
GetProperties(name string) (bool, map[string]string, error)
|
||||
}
|
||||
|
||||
// replicaInstance interface provides a unified interface
|
||||
// over replicas and instances
|
||||
type replicaInstance interface {
|
||||
GetReplicaData() (string, *sf.ReplicaItemBase)
|
||||
}
|
21
vendor/github.com/jjcollinge/logrus-appinsights/LICENSE
generated
vendored
21
vendor/github.com/jjcollinge/logrus-appinsights/LICENSE
generated
vendored
|
@ -1,21 +0,0 @@
|
|||
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
11
vendor/github.com/jjcollinge/logrus-appinsights/config.go
generated
vendored
|
@ -1,11 +0,0 @@
|
|||
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
173
vendor/github.com/jjcollinge/logrus-appinsights/hook.go
generated
vendored
|
@ -1,173 +0,0 @@
|
|||
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
|
||||
}
|
21
vendor/github.com/jjcollinge/servicefabric/LICENSE
generated
vendored
21
vendor/github.com/jjcollinge/servicefabric/LICENSE
generated
vendored
|
@ -1,21 +0,0 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2017 Joni Collinge
|
||||
|
||||
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.
|
20
vendor/github.com/jjcollinge/servicefabric/query.go
generated
vendored
20
vendor/github.com/jjcollinge/servicefabric/query.go
generated
vendored
|
@ -1,20 +0,0 @@
|
|||
package servicefabric
|
||||
|
||||
type queryParamsFunc func(params []string) []string
|
||||
|
||||
func withContinue(token string) queryParamsFunc {
|
||||
if len(token) == 0 {
|
||||
return noOp
|
||||
}
|
||||
return withParam("continue", token)
|
||||
}
|
||||
|
||||
func withParam(name, value string) queryParamsFunc {
|
||||
return func(params []string) []string {
|
||||
return append(params, name+"="+value)
|
||||
}
|
||||
}
|
||||
|
||||
func noOp(params []string) []string {
|
||||
return params
|
||||
}
|
392
vendor/github.com/jjcollinge/servicefabric/servicefabric.go
generated
vendored
392
vendor/github.com/jjcollinge/servicefabric/servicefabric.go
generated
vendored
|
@ -1,392 +0,0 @@
|
|||
// Package servicefabric is an opinionated Service Fabric client written in Golang
|
||||
package servicefabric
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// DefaultAPIVersion is a default Service Fabric REST API version
|
||||
const DefaultAPIVersion = "3.0"
|
||||
|
||||
// Client for Service Fabric.
|
||||
// This is purposely a subset of the total Service Fabric API surface.
|
||||
type Client struct {
|
||||
// endpoint Service Fabric cluster management endpoint
|
||||
endpoint string
|
||||
// apiVersion Service Fabric API version
|
||||
apiVersion string
|
||||
// httpClient HTTP client
|
||||
httpClient *http.Client
|
||||
}
|
||||
|
||||
// NewClient returns a new provider client that can query the
|
||||
// Service Fabric management API externally or internally
|
||||
func NewClient(httpClient *http.Client, endpoint, apiVersion string, tlsConfig *tls.Config) (*Client, error) {
|
||||
if endpoint == "" {
|
||||
return nil, errors.New("endpoint missing for httpClient configuration")
|
||||
}
|
||||
if apiVersion == "" {
|
||||
apiVersion = DefaultAPIVersion
|
||||
}
|
||||
|
||||
if tlsConfig != nil {
|
||||
tlsConfig.Renegotiation = tls.RenegotiateFreelyAsClient
|
||||
tlsConfig.BuildNameToCertificate()
|
||||
httpClient.Transport = &http.Transport{TLSClientConfig: tlsConfig}
|
||||
}
|
||||
|
||||
return &Client{
|
||||
endpoint: endpoint,
|
||||
apiVersion: apiVersion,
|
||||
httpClient: httpClient,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetApplications returns all the registered applications
|
||||
// within the Service Fabric cluster.
|
||||
func (c Client) GetApplications() (*ApplicationItemsPage, error) {
|
||||
var aggregateAppItemsPages ApplicationItemsPage
|
||||
var continueToken string
|
||||
for {
|
||||
res, err := c.getHTTP("Applications/", withContinue(continueToken))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var appItemsPage ApplicationItemsPage
|
||||
err = json.Unmarshal(res, &appItemsPage)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not deserialise JSON response: %+v", err)
|
||||
}
|
||||
|
||||
aggregateAppItemsPages.Items = append(aggregateAppItemsPages.Items, appItemsPage.Items...)
|
||||
|
||||
continueToken = getString(appItemsPage.ContinuationToken)
|
||||
if continueToken == "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
return &aggregateAppItemsPages, nil
|
||||
}
|
||||
|
||||
// GetServices returns all the services associated
|
||||
// with a Service Fabric application.
|
||||
func (c Client) GetServices(appName string) (*ServiceItemsPage, error) {
|
||||
var aggregateServiceItemsPages ServiceItemsPage
|
||||
var continueToken string
|
||||
for {
|
||||
res, err := c.getHTTP("Applications/"+appName+"/$/GetServices", withContinue(continueToken))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var servicesItemsPage ServiceItemsPage
|
||||
err = json.Unmarshal(res, &servicesItemsPage)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not deserialise JSON response: %+v", err)
|
||||
}
|
||||
|
||||
aggregateServiceItemsPages.Items = append(aggregateServiceItemsPages.Items, servicesItemsPage.Items...)
|
||||
|
||||
continueToken = getString(servicesItemsPage.ContinuationToken)
|
||||
if continueToken == "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
return &aggregateServiceItemsPages, nil
|
||||
}
|
||||
|
||||
// GetPartitions returns all the partitions associated
|
||||
// with a Service Fabric service.
|
||||
func (c Client) GetPartitions(appName, serviceName string) (*PartitionItemsPage, error) {
|
||||
var aggregatePartitionItemsPages PartitionItemsPage
|
||||
var continueToken string
|
||||
for {
|
||||
basePath := "Applications/" + appName + "/$/GetServices/" + serviceName + "/$/GetPartitions/"
|
||||
res, err := c.getHTTP(basePath, withContinue(continueToken))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var partitionsItemsPage PartitionItemsPage
|
||||
err = json.Unmarshal(res, &partitionsItemsPage)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not deserialise JSON response: %+v", err)
|
||||
}
|
||||
|
||||
aggregatePartitionItemsPages.Items = append(aggregatePartitionItemsPages.Items, partitionsItemsPage.Items...)
|
||||
|
||||
continueToken = getString(partitionsItemsPage.ContinuationToken)
|
||||
if continueToken == "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
return &aggregatePartitionItemsPages, nil
|
||||
}
|
||||
|
||||
// GetInstances returns all the instances associated
|
||||
// with a stateless Service Fabric partition.
|
||||
func (c Client) GetInstances(appName, serviceName, partitionName string) (*InstanceItemsPage, error) {
|
||||
var aggregateInstanceItemsPages InstanceItemsPage
|
||||
var continueToken string
|
||||
for {
|
||||
basePath := "Applications/" + appName + "/$/GetServices/" + serviceName + "/$/GetPartitions/" + partitionName + "/$/GetReplicas"
|
||||
res, err := c.getHTTP(basePath, withContinue(continueToken))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var instanceItemsPage InstanceItemsPage
|
||||
err = json.Unmarshal(res, &instanceItemsPage)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not deserialise JSON response: %+v", err)
|
||||
}
|
||||
|
||||
aggregateInstanceItemsPages.Items = append(aggregateInstanceItemsPages.Items, instanceItemsPage.Items...)
|
||||
|
||||
continueToken = getString(instanceItemsPage.ContinuationToken)
|
||||
if continueToken == "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
return &aggregateInstanceItemsPages, nil
|
||||
}
|
||||
|
||||
// GetReplicas returns all the replicas associated
|
||||
// with a stateful Service Fabric partition.
|
||||
func (c Client) GetReplicas(appName, serviceName, partitionName string) (*ReplicaItemsPage, error) {
|
||||
var aggregateReplicaItemsPages ReplicaItemsPage
|
||||
var continueToken string
|
||||
for {
|
||||
basePath := "Applications/" + appName + "/$/GetServices/" + serviceName + "/$/GetPartitions/" + partitionName + "/$/GetReplicas"
|
||||
res, err := c.getHTTP(basePath, withContinue(continueToken))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var replicasItemsPage ReplicaItemsPage
|
||||
err = json.Unmarshal(res, &replicasItemsPage)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not deserialise JSON response: %+v", err)
|
||||
}
|
||||
|
||||
aggregateReplicaItemsPages.Items = append(aggregateReplicaItemsPages.Items, replicasItemsPage.Items...)
|
||||
|
||||
continueToken = getString(replicasItemsPage.ContinuationToken)
|
||||
if continueToken == "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
return &aggregateReplicaItemsPages, nil
|
||||
}
|
||||
|
||||
// GetServiceExtension returns all the extensions specified
|
||||
// in a Service's manifest file. If the XML schema does not
|
||||
// map to the provided interface, the default type interface will
|
||||
// be returned.
|
||||
func (c Client) GetServiceExtension(appType, applicationVersion, serviceTypeName, extensionKey string, response interface{}) error {
|
||||
res, err := c.getHTTP("ApplicationTypes/"+appType+"/$/GetServiceTypes", withParam("ApplicationTypeVersion", applicationVersion))
|
||||
if err != nil {
|
||||
return fmt.Errorf("error requesting service extensions: %v", err)
|
||||
}
|
||||
|
||||
var serviceTypes []ServiceType
|
||||
err = json.Unmarshal(res, &serviceTypes)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not deserialise JSON response: %+v", err)
|
||||
}
|
||||
|
||||
for _, serviceTypeInfo := range serviceTypes {
|
||||
if serviceTypeInfo.ServiceTypeDescription.ServiceTypeName == serviceTypeName {
|
||||
for _, extension := range serviceTypeInfo.ServiceTypeDescription.Extensions {
|
||||
if strings.EqualFold(extension.Key, extensionKey) {
|
||||
err = xml.Unmarshal([]byte(extension.Value), &response)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not deserialise extension's XML value: %+v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetServiceExtensionMap returns all the extension xml specified
|
||||
// in a Service's manifest file into (which must conform to ServiceExtensionLabels)
|
||||
// a map[string]string
|
||||
func (c Client) GetServiceExtensionMap(service *ServiceItem, app *ApplicationItem, extensionKey string) (map[string]string, error) {
|
||||
extensionData := ServiceExtensionLabels{}
|
||||
err := c.GetServiceExtension(app.TypeName, app.TypeVersion, service.TypeName, extensionKey, &extensionData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
labels := map[string]string{}
|
||||
if extensionData.Label != nil {
|
||||
for _, label := range extensionData.Label {
|
||||
labels[label.Key] = label.Value
|
||||
}
|
||||
}
|
||||
|
||||
return labels, nil
|
||||
}
|
||||
|
||||
// GetProperties uses the Property Manager API to retrieve
|
||||
// string properties from a name as a dictionary
|
||||
// Property name is the path to the properties you would like to list.
|
||||
// for example a serviceID
|
||||
func (c Client) GetProperties(name string) (bool, map[string]string, error) {
|
||||
nameExists, err := c.nameExists(name)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
|
||||
if !nameExists {
|
||||
return false, nil, nil
|
||||
}
|
||||
|
||||
properties := make(map[string]string)
|
||||
|
||||
var continueToken string
|
||||
for {
|
||||
res, err := c.getHTTP("Names/"+name+"/$/GetProperties", withContinue(continueToken), withParam("IncludeValues", "true"))
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
|
||||
var propertiesListPage PropertiesListPage
|
||||
err = json.Unmarshal(res, &propertiesListPage)
|
||||
if err != nil {
|
||||
return false, nil, fmt.Errorf("could not deserialise JSON response: %+v", err)
|
||||
}
|
||||
|
||||
for _, property := range propertiesListPage.Properties {
|
||||
if property.Value.Kind != "String" {
|
||||
continue
|
||||
}
|
||||
properties[property.Name] = property.Value.Data
|
||||
}
|
||||
|
||||
continueToken = propertiesListPage.ContinuationToken
|
||||
if continueToken == "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return true, properties, nil
|
||||
}
|
||||
|
||||
// GetServiceLabels add labels from service manifest extensions and properties manager
|
||||
// expects extension xml in <Label key="key">value</Label>
|
||||
//
|
||||
// Deprecated: Use GetProperties and GetServiceExtensionMap instead.
|
||||
func (c Client) GetServiceLabels(service *ServiceItem, app *ApplicationItem, prefix string) (map[string]string, error) {
|
||||
extensionData := ServiceExtensionLabels{}
|
||||
err := c.GetServiceExtension(app.TypeName, app.TypeVersion, service.TypeName, prefix, &extensionData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
prefixPeriod := prefix + "."
|
||||
|
||||
labels := map[string]string{}
|
||||
if extensionData.Label != nil {
|
||||
for _, label := range extensionData.Label {
|
||||
if strings.HasPrefix(label.Key, prefixPeriod) {
|
||||
labelKey := strings.Replace(label.Key, prefixPeriod, "", -1)
|
||||
labels[labelKey] = label.Value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exists, properties, err := c.GetProperties(service.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if exists {
|
||||
for k, v := range properties {
|
||||
if strings.HasPrefix(k, prefixPeriod) {
|
||||
labelKey := strings.Replace(k, prefixPeriod, "", -1)
|
||||
labels[labelKey] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return labels, nil
|
||||
}
|
||||
|
||||
func (c Client) nameExists(propertyName string) (bool, error) {
|
||||
res, err := c.getHTTPRaw("Names/" + propertyName)
|
||||
// Get http will return error for any non 200 response code.
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return res.StatusCode == http.StatusOK, nil
|
||||
}
|
||||
|
||||
func (c Client) getHTTP(basePath string, paramsFuncs ...queryParamsFunc) ([]byte, error) {
|
||||
if c.httpClient == nil {
|
||||
return nil, errors.New("invalid http client provided")
|
||||
}
|
||||
|
||||
url := c.getURL(basePath, paramsFuncs...)
|
||||
res, err := c.httpClient.Get(url)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to connect to Service Fabric server %+v on %s", err, url)
|
||||
}
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("Service Fabric responded with error code %s to request %s with body %v", res.Status, url, res.Body)
|
||||
}
|
||||
|
||||
if res.Body == nil {
|
||||
return nil, errors.New("empty response body from Service Fabric")
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
body, readErr := ioutil.ReadAll(res.Body)
|
||||
if readErr != nil {
|
||||
return nil, fmt.Errorf("failed to read response body from Service Fabric response %+v", readErr)
|
||||
}
|
||||
return body, nil
|
||||
}
|
||||
|
||||
func (c Client) getHTTPRaw(basePath string) (*http.Response, error) {
|
||||
if c.httpClient == nil {
|
||||
return nil, fmt.Errorf("invalid http client provided")
|
||||
}
|
||||
|
||||
url := c.getURL(basePath)
|
||||
|
||||
res, err := c.httpClient.Get(url)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to connect to Service Fabric server %+v on %s", err, url)
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (c Client) getURL(basePath string, paramsFuncs ...queryParamsFunc) string {
|
||||
params := []string{"api-version=" + c.apiVersion}
|
||||
|
||||
for _, paramsFunc := range paramsFuncs {
|
||||
params = paramsFunc(params)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s/%s?%s", c.endpoint, basePath, strings.Join(params, "&"))
|
||||
}
|
||||
|
||||
func getString(str *string) string {
|
||||
if str == nil {
|
||||
return ""
|
||||
}
|
||||
return *str
|
||||
}
|
199
vendor/github.com/jjcollinge/servicefabric/types.go
generated
vendored
199
vendor/github.com/jjcollinge/servicefabric/types.go
generated
vendored
|
@ -1,199 +0,0 @@
|
|||
package servicefabric
|
||||
|
||||
import "encoding/xml"
|
||||
|
||||
// ApplicationItemsPage encapsulates the paged response
|
||||
// model for Applications in the Service Fabric API
|
||||
type ApplicationItemsPage struct {
|
||||
ContinuationToken *string `json:"ContinuationToken"`
|
||||
Items []ApplicationItem `json:"Items"`
|
||||
}
|
||||
|
||||
// AppParameter Application parameter
|
||||
type AppParameter struct {
|
||||
Key string `json:"Key"`
|
||||
Value string `json:"Value"`
|
||||
}
|
||||
|
||||
// ApplicationItem encapsulates the embedded model for
|
||||
// ApplicationItems within the ApplicationItemsPage model
|
||||
type ApplicationItem struct {
|
||||
HealthState string `json:"HealthState"`
|
||||
ID string `json:"Id"`
|
||||
Name string `json:"Name"`
|
||||
Parameters []*AppParameter `json:"Parameters"`
|
||||
Status string `json:"Status"`
|
||||
TypeName string `json:"TypeName"`
|
||||
TypeVersion string `json:"TypeVersion"`
|
||||
}
|
||||
|
||||
// ServiceItemsPage encapsulates the paged response
|
||||
// model for Services in the Service Fabric API
|
||||
type ServiceItemsPage struct {
|
||||
ContinuationToken *string `json:"ContinuationToken"`
|
||||
Items []ServiceItem `json:"Items"`
|
||||
}
|
||||
|
||||
// ServiceItem encapsulates the embedded model for
|
||||
// ServiceItems within the ServiceItemsPage model
|
||||
type ServiceItem struct {
|
||||
HasPersistedState bool `json:"HasPersistedState"`
|
||||
HealthState string `json:"HealthState"`
|
||||
ID string `json:"Id"`
|
||||
IsServiceGroup bool `json:"IsServiceGroup"`
|
||||
ManifestVersion string `json:"ManifestVersion"`
|
||||
Name string `json:"Name"`
|
||||
ServiceKind string `json:"ServiceKind"`
|
||||
ServiceStatus string `json:"ServiceStatus"`
|
||||
TypeName string `json:"TypeName"`
|
||||
}
|
||||
|
||||
// PartitionItemsPage encapsulates the paged response
|
||||
// model for PartitionItems in the Service Fabric API
|
||||
type PartitionItemsPage struct {
|
||||
ContinuationToken *string `json:"ContinuationToken"`
|
||||
Items []PartitionItem `json:"Items"`
|
||||
}
|
||||
|
||||
// PartitionItem encapsulates the service information
|
||||
// returned for each PartitionItem under the service
|
||||
type PartitionItem struct {
|
||||
CurrentConfigurationEpoch ConfigurationEpoch `json:"CurrentConfigurationEpoch"`
|
||||
HealthState string `json:"HealthState"`
|
||||
MinReplicaSetSize int64 `json:"MinReplicaSetSize"`
|
||||
PartitionInformation PartitionInformation `json:"PartitionInformation"`
|
||||
PartitionStatus string `json:"PartitionStatus"`
|
||||
ServiceKind string `json:"ServiceKind"`
|
||||
TargetReplicaSetSize int64 `json:"TargetReplicaSetSize"`
|
||||
}
|
||||
|
||||
// ConfigurationEpoch Partition configuration epoch
|
||||
type ConfigurationEpoch struct {
|
||||
ConfigurationVersion string `json:"ConfigurationVersion"`
|
||||
DataLossVersion string `json:"DataLossVersion"`
|
||||
}
|
||||
|
||||
// PartitionInformation Partition information
|
||||
type PartitionInformation struct {
|
||||
HighKey string `json:"HighKey"`
|
||||
ID string `json:"Id"`
|
||||
LowKey string `json:"LowKey"`
|
||||
ServicePartitionKind string `json:"ServicePartitionKind"`
|
||||
}
|
||||
|
||||
// ReplicaItemBase shared data used
|
||||
// in both replicas and instances
|
||||
type ReplicaItemBase struct {
|
||||
Address string `json:"Address"`
|
||||
HealthState string `json:"HealthState"`
|
||||
LastInBuildDurationInSeconds string `json:"LastInBuildDurationInSeconds"`
|
||||
NodeName string `json:"NodeName"`
|
||||
ReplicaRole string `json:"ReplicaRole"`
|
||||
ReplicaStatus string `json:"ReplicaStatus"`
|
||||
ServiceKind string `json:"ServiceKind"`
|
||||
}
|
||||
|
||||
// ReplicaItemsPage encapsulates the response
|
||||
// model for Replicas in the Service Fabric API
|
||||
type ReplicaItemsPage struct {
|
||||
ContinuationToken *string `json:"ContinuationToken"`
|
||||
Items []ReplicaItem `json:"Items"`
|
||||
}
|
||||
|
||||
// ReplicaItem holds replica specific data
|
||||
type ReplicaItem struct {
|
||||
*ReplicaItemBase
|
||||
ID string `json:"ReplicaId"`
|
||||
}
|
||||
|
||||
// GetReplicaData returns replica data
|
||||
func (m *ReplicaItem) GetReplicaData() (string, *ReplicaItemBase) {
|
||||
return m.ID, m.ReplicaItemBase
|
||||
}
|
||||
|
||||
// InstanceItemsPage encapsulates the response
|
||||
// model for Instances in the Service Fabric API
|
||||
type InstanceItemsPage struct {
|
||||
ContinuationToken *string `json:"ContinuationToken"`
|
||||
Items []InstanceItem `json:"Items"`
|
||||
}
|
||||
|
||||
// InstanceItem hold instance specific data
|
||||
type InstanceItem struct {
|
||||
*ReplicaItemBase
|
||||
ID string `json:"InstanceId"`
|
||||
}
|
||||
|
||||
// GetReplicaData returns replica data from an instance
|
||||
func (m *InstanceItem) GetReplicaData() (string, *ReplicaItemBase) {
|
||||
return m.ID, m.ReplicaItemBase
|
||||
}
|
||||
|
||||
// ServiceType encapsulates the response model for
|
||||
// Service types in the Service Fabric API
|
||||
type ServiceType struct {
|
||||
ServiceTypeDescription ServiceTypeDescription `json:"ServiceTypeDescription"`
|
||||
ServiceManifestVersion string `json:"ServiceManifestVersion"`
|
||||
ServiceManifestName string `json:"ServiceManifestName"`
|
||||
IsServiceGroup bool `json:"IsServiceGroup"`
|
||||
}
|
||||
|
||||
// ServiceTypeDescription Service Type Description
|
||||
type ServiceTypeDescription struct {
|
||||
IsStateful bool `json:"IsStateful"`
|
||||
ServiceTypeName string `json:"ServiceTypeName"`
|
||||
PlacementConstraints string `json:"PlacementConstraints"`
|
||||
HasPersistedState bool `json:"HasPersistedState"`
|
||||
Kind string `json:"Kind"`
|
||||
Extensions []KeyValuePair `json:"Extensions"`
|
||||
LoadMetrics []interface{} `json:"LoadMetrics"`
|
||||
ServicePlacementPolicies []interface{} `json:"ServicePlacementPolicies"`
|
||||
}
|
||||
|
||||
// PropertiesListPage encapsulates the response model for
|
||||
// PagedPropertyInfoList in the Service Fabric API
|
||||
type PropertiesListPage struct {
|
||||
ContinuationToken string `json:"ContinuationToken"`
|
||||
IsConsistent bool `json:"IsConsistent"`
|
||||
Properties []Property `json:"Properties"`
|
||||
}
|
||||
|
||||
// Property Paged Property Info
|
||||
type Property struct {
|
||||
Metadata Metadata `json:"Metadata"`
|
||||
Name string `json:"Name"`
|
||||
Value PropValue `json:"Value"`
|
||||
}
|
||||
|
||||
// Metadata Property Metadata
|
||||
type Metadata struct {
|
||||
CustomTypeID string `json:"CustomTypeId"`
|
||||
LastModifiedUtcTimestamp string `json:"LastModifiedUtcTimestamp"`
|
||||
Parent string `json:"Parent"`
|
||||
SequenceNumber string `json:"SequenceNumber"`
|
||||
SizeInBytes int64 `json:"SizeInBytes"`
|
||||
TypeID string `json:"TypeId"`
|
||||
}
|
||||
|
||||
// PropValue Property value
|
||||
type PropValue struct {
|
||||
Data string `json:"Data"`
|
||||
Kind string `json:"Kind"`
|
||||
}
|
||||
|
||||
// KeyValuePair represents a key value pair structure
|
||||
type KeyValuePair struct {
|
||||
Key string `json:"Key"`
|
||||
Value string `json:"Value"`
|
||||
}
|
||||
|
||||
// ServiceExtensionLabels provides the structure for
|
||||
// deserialising the XML document used to store labels in an Extension
|
||||
type ServiceExtensionLabels struct {
|
||||
XMLName xml.Name `xml:"Labels"`
|
||||
Label []struct {
|
||||
XMLName xml.Name `xml:"Label"`
|
||||
Value string `xml:",chardata"`
|
||||
Key string `xml:"Key,attr"`
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue