added application insights telemetry package to send metrics and logs (#421)

* added application insights telemetry package to send metrics and logs to appinsights

* moved a function common to both packages
acquired a lock before writing to file

* added read write lock as per chandan comment. Addressed jaeryn comments

* fixed telemetry unit test

* defined interface and added appinsights package as vendor to acn

* added vendor package.go(appinsights)

* dependencies of appinsights

* added AI dependencies

* updated unit tests

* addressed review comments
This commit is contained in:
tamilmani1989 2019-10-16 13:08:42 -07:00 коммит произвёл GitHub
Родитель decd0d466c
Коммит e0605e90f6
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
63 изменённых файлов: 5776 добавлений и 104 удалений

149
Gopkg.lock сгенерированный
Просмотреть файл

@ -2,12 +2,23 @@
[[projects]]
digest = "1:57d862d83c6c53d8d645827878df9667ac3d1ac7f22717190a698110dfb7aabe"
name = "code.cloudfoundry.org/clock"
packages = ["."]
pruneopts = "UT"
revision = "02e53af36e6c978af692887ed449b74026d76fec"
version = "1.0.0"
[[projects]]
digest = "1:f9ae348e1f793dcf9ed930ed47136a67343dbd6809c5c91391322267f4476892"
name = "github.com/Microsoft/go-winio"
packages = ["."]
pruneopts = "UT"
revision = "1a8911d1ed007260465c3bfbbc785ac6915a0bb8"
version = "v0.4.12"
[[projects]]
digest = "1:6a16b820c16f0587d63a3c462a9d787106f966adae5056aa430ebca18c7fba46"
name = "github.com/Microsoft/hcsshim"
packages = [
".",
@ -24,12 +35,14 @@
"internal/schema1",
"internal/schema2",
"internal/timeout",
"internal/wclayer"
"internal/wclayer",
]
pruneopts = "UT"
revision = "f92b8fb9c92e17da496af5a69e3ee13fbe9916e1"
version = "v0.8.6"
[[projects]]
digest = "1:eb56b03a240f4ae8de520edf525f75d4d26ea41b99f5972b449cbd5ba9f0adf6"
name = "github.com/containernetworking/cni"
packages = [
"libcni",
@ -38,116 +51,164 @@
"pkg/types",
"pkg/types/020",
"pkg/types/current",
"pkg/version"
"pkg/version",
]
pruneopts = "UT"
revision = "fbb95fff8a5239a4295c991efa8a397d43118f7e"
[[projects]]
digest = "1:ffe9824d294da03b391f44e1ae8281281b4afc1bdaa9588c9097785e3af10cec"
name = "github.com/davecgh/go-spew"
packages = ["spew"]
pruneopts = "UT"
revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73"
version = "v1.1.1"
[[projects]]
digest = "1:190198fd3c956b1383a31273d6b7e76cb926e9b68f7eaf1f6b9e487b50113d6e"
name = "github.com/docker/libnetwork"
packages = [
"driverapi",
"drivers/remote/api",
"types"
"types",
]
pruneopts = "UT"
revision = "1ee720e18fe98dceda6039bdd005ffbcb359d343"
version = "v0.5.6"
[[projects]]
digest = "1:4d02824a56d268f74a6b6fdd944b20b58a77c3d70e81008b3ee0c4f1a6777340"
name = "github.com/gogo/protobuf"
packages = [
"proto",
"sortkeys"
"sortkeys",
]
pruneopts = "UT"
revision = "ba06b47c162d49f2af050fb4c75bcbc86a159d5c"
version = "v1.2.1"
[[projects]]
digest = "1:239c4c7fd2159585454003d9be7207167970194216193a8a210b8d29576f19c9"
name = "github.com/golang/protobuf"
packages = [
"proto",
"ptypes",
"ptypes/any",
"ptypes/duration",
"ptypes/timestamp"
"ptypes/timestamp",
]
pruneopts = "UT"
revision = "b5d812f8a3706043e23a9cd5babf2e5423744d30"
version = "v1.3.1"
[[projects]]
digest = "1:a6181aca1fd5e27103f9a920876f29ac72854df7345a39f3b01e61c8c94cc8af"
name = "github.com/google/gofuzz"
packages = ["."]
pruneopts = "UT"
revision = "f140a6486e521aad38f5917de355cbf147cc0496"
version = "v1.0.0"
[[projects]]
digest = "1:582b704bebaa06b48c29b0cec224a6058a09c86883aaddabde889cd1a5f73e1b"
name = "github.com/google/uuid"
packages = ["."]
pruneopts = "UT"
revision = "0cd6bf5da1e1c83f8b45653022c74f71af0538a4"
version = "v1.1.1"
[[projects]]
digest = "1:65c4414eeb350c47b8de71110150d0ea8a281835b1f386eacaa3ad7325929c21"
name = "github.com/googleapis/gnostic"
packages = [
"OpenAPIv2",
"compiler",
"extensions"
"extensions",
]
pruneopts = "UT"
revision = "7c663266750e7d82587642f65e60bc4083f1f84e"
version = "v0.2.0"
[[projects]]
digest = "1:d15ee511aa0f56baacc1eb4c6b922fa1c03b38413b6be18166b996d82a0156ea"
name = "github.com/hashicorp/golang-lru"
packages = [
".",
"simplelru"
"simplelru",
]
pruneopts = "UT"
revision = "7087cb70de9f7a8bc0a10c375cb0d2280a8edf9c"
version = "v0.5.1"
[[projects]]
digest = "1:f5a2051c55d05548d2d4fd23d244027b59fbd943217df8aa3b5e170ac2fd6e1b"
name = "github.com/json-iterator/go"
packages = ["."]
pruneopts = "UT"
revision = "0ff49de124c6f76f8494e194af75bde0f1a49a29"
version = "v1.1.6"
[[projects]]
digest = "1:31e761d97c76151dde79e9d28964a812c46efc5baee4085b86f68f0c654450de"
name = "github.com/konsorten/go-windows-terminal-sequences"
packages = ["."]
pruneopts = "UT"
revision = "f55edac94c9bbba5d6182a4be46d86a2c9b5b50e"
version = "v1.0.2"
[[projects]]
digest = "1:2d54ea234b5487eb9c651f55d8ccf30978b1c2116e2f547ba7cf8cb0932bacc7"
name = "github.com/microsoft/ApplicationInsights-Go"
packages = [
"appinsights",
"appinsights/contracts",
]
pruneopts = "UT"
revision = "d813d7725313000ad1b71627b8951323635f0572"
[[projects]]
digest = "1:33422d238f147d247752996a26574ac48dcf472976eda7f5134015f06bf16563"
name = "github.com/modern-go/concurrent"
packages = ["."]
pruneopts = "UT"
revision = "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94"
version = "1.0.3"
[[projects]]
digest = "1:e32bdbdb7c377a07a9a46378290059822efdce5c8d96fe71940d87cb4f918855"
name = "github.com/modern-go/reflect2"
packages = ["."]
pruneopts = "UT"
revision = "4b7aa43c6742a2c18fdef89dd197aaae7dac7ccd"
version = "1.0.1"
[[projects]]
digest = "1:274f67cb6fed9588ea2521ecdac05a6d62a8c51c074c1fccc6a49a40ba80e925"
name = "github.com/satori/go.uuid"
packages = ["."]
pruneopts = "UT"
revision = "f58768cc1a7a7e77a3bd49e98cdd21419399b6a3"
version = "v1.2.0"
[[projects]]
digest = "1:fd61cf4ae1953d55df708acb6b91492d538f49c305b364a014049914495db426"
name = "github.com/sirupsen/logrus"
packages = ["."]
pruneopts = "UT"
revision = "8bdbc7bcc01dcbb8ec23dc8a28e332258d25251f"
version = "v1.4.1"
[[projects]]
branch = "master"
digest = "1:bbe51412d9915d64ffaa96b51d409e070665efc5194fcf145c4a27d4133107a4"
name = "golang.org/x/crypto"
packages = ["ssh/terminal"]
pruneopts = "UT"
revision = "a29dc8fdc73485234dbef99ebedb95d2eced08de"
[[projects]]
branch = "master"
digest = "1:b9bf9ddb713916ca0fe4630b135cc937c81a00378a97083a906c9669d56ab23f"
name = "golang.org/x/net"
packages = [
"context",
@ -155,29 +216,35 @@
"http/httpguts",
"http2",
"http2/hpack",
"idna"
"idna",
]
pruneopts = "UT"
revision = "7f726cade0ab7c929c16ce0b5b25bd201e25f39f"
[[projects]]
branch = "master"
digest = "1:9927d6aceb89d188e21485f42a7a254e67e6fdcf4260aba375fe18e3c300dfb4"
name = "golang.org/x/oauth2"
packages = [
".",
"internal"
"internal",
]
pruneopts = "UT"
revision = "9f3314589c9a9136388751d9adae6b0ed400978a"
[[projects]]
branch = "master"
digest = "1:4cf0abce65ca9e0e906fdd0d76ad1dd1dcc94afe5901473cbc7f8d623cceabb4"
name = "golang.org/x/sys"
packages = [
"unix",
"windows"
"windows",
]
pruneopts = "UT"
revision = "a43fa875dd822b81eb6d2ad538bc1f4caba169bd"
[[projects]]
digest = "1:8d8faad6b12a3a4c819a3f9618cb6ee1fa1cfc33253abeeea8b55336721e3405"
name = "golang.org/x/text"
packages = [
"collate",
@ -195,18 +262,22 @@
"unicode/bidi",
"unicode/cldr",
"unicode/norm",
"unicode/rangetable"
"unicode/rangetable",
]
pruneopts = "UT"
revision = "342b2e1fbaa52c93f31447ad2c6abc048c63e475"
version = "v0.3.2"
[[projects]]
branch = "master"
digest = "1:9fdc2b55e8e0fafe4b41884091e51e77344f7dc511c5acedcfd98200003bff90"
name = "golang.org/x/time"
packages = ["rate"]
pruneopts = "UT"
revision = "9d24e82272b4f38b78bc8cff74fa936d31ccd8ef"
[[projects]]
digest = "1:6eb6e3b6d9fffb62958cf7f7d88dbbe1dd6839436b0802e194c590667a40412a"
name = "google.golang.org/appengine"
packages = [
"internal",
@ -215,25 +286,31 @@
"internal/log",
"internal/remote_api",
"internal/urlfetch",
"urlfetch"
"urlfetch",
]
pruneopts = "UT"
revision = "54a98f90d1c46b7731eb8fb305d2a321c30ef610"
version = "v1.5.0"
[[projects]]
digest = "1:2d1fbdc6777e5408cabeb02bf336305e724b925ff4546ded0fa8715a7267922a"
name = "gopkg.in/inf.v0"
packages = ["."]
pruneopts = "UT"
revision = "d2d2541c53f18d2a059457998ce2876cc8e67cbf"
version = "v0.9.1"
[[projects]]
digest = "1:4d2e5a73dc1500038e504a8d78b986630e3626dc027bc030ba5c75da257cdb96"
name = "gopkg.in/yaml.v2"
packages = ["."]
pruneopts = "UT"
revision = "51d6538a90f86fe93ac480b35f37b2be17fef232"
version = "v2.2.2"
[[projects]]
branch = "master"
digest = "1:3d206da0c5871a719863cbf3a2d44fa5c0a77670491c19e2274b05799e84879a"
name = "k8s.io/api"
packages = [
"admissionregistration/v1beta1",
@ -271,11 +348,13 @@
"settings/v1alpha1",
"storage/v1",
"storage/v1alpha1",
"storage/v1beta1"
"storage/v1beta1",
]
pruneopts = "UT"
revision = "61630f889b3c3efb8c3a4ba377da1a421d9ff6ce"
[[projects]]
digest = "1:d43bb672b3e811c5ea37b48a0a73bea7fcbcb348a45ce7ba349006145c76418d"
name = "k8s.io/apimachinery"
packages = [
"pkg/api/errors",
@ -316,11 +395,13 @@
"pkg/util/yaml",
"pkg/version",
"pkg/watch",
"third_party/forked/golang/reflect"
"third_party/forked/golang/reflect",
]
pruneopts = "UT"
revision = "d7deff9243b165ee192f5551710ea4285dcfd615"
[[projects]]
digest = "1:a3712b06370e1f92902bc22151b31bbfef00f520945bd51716fe498375923864"
name = "k8s.io/client-go"
packages = [
"discovery",
@ -462,36 +543,70 @@
"util/connrotation",
"util/flowcontrol",
"util/keyutil",
"util/retry"
"util/retry",
]
pruneopts = "UT"
revision = "6ee68ca5fd8355d024d02f9db0b3b667e8357a0f"
version = "v11.0.0"
[[projects]]
digest = "1:c696379ad201c1e86591785579e16bf6cf886c362e9a7534e8eb0d1028b20582"
name = "k8s.io/klog"
packages = ["."]
pruneopts = "UT"
revision = "e531227889390a39d9533dde61f590fe9f4b0035"
version = "v0.3.0"
[[projects]]
branch = "master"
digest = "1:14e8a3b53e6d8cb5f44783056b71bb2ca1ac7e333939cc97f3e50b579c920845"
name = "k8s.io/utils"
packages = [
"buffer",
"integer",
"trace"
"trace",
]
pruneopts = "UT"
revision = "21c4ce38f2a793ec01e925ddc31216500183b773"
[[projects]]
digest = "1:7719608fe0b52a4ece56c2dde37bedd95b938677d1ab0f84b8a7852e4c59f849"
name = "sigs.k8s.io/yaml"
packages = ["."]
pruneopts = "UT"
revision = "fd68e9863619f6ec2fdd8625fe1f02e7c877e480"
version = "v1.1.0"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "6355bb8af9b2a11f4dbe507402aefb79e843ca1c0191829cd76c3e5de4b8ef1d"
input-imports = [
"github.com/Microsoft/go-winio",
"github.com/Microsoft/hcsshim",
"github.com/containernetworking/cni/libcni",
"github.com/containernetworking/cni/pkg/invoke",
"github.com/containernetworking/cni/pkg/skel",
"github.com/containernetworking/cni/pkg/types",
"github.com/containernetworking/cni/pkg/types/current",
"github.com/containernetworking/cni/pkg/version",
"github.com/docker/libnetwork/driverapi",
"github.com/docker/libnetwork/drivers/remote/api",
"github.com/google/uuid",
"github.com/microsoft/ApplicationInsights-Go/appinsights",
"golang.org/x/sys/unix",
"k8s.io/api/core/v1",
"k8s.io/api/networking/v1",
"k8s.io/apimachinery/pkg/apis/meta/v1",
"k8s.io/apimachinery/pkg/types",
"k8s.io/apimachinery/pkg/util/intstr",
"k8s.io/apimachinery/pkg/util/wait",
"k8s.io/apimachinery/pkg/version",
"k8s.io/client-go/informers",
"k8s.io/client-go/informers/core/v1",
"k8s.io/client-go/informers/networking/v1",
"k8s.io/client-go/kubernetes",
"k8s.io/client-go/rest",
"k8s.io/client-go/tools/cache",
]
solver-name = "gps-cdcl"
solver-version = 1

Просмотреть файл

@ -61,6 +61,10 @@
name = "github.com/containernetworking/cni"
revision = "fbb95fff8a5239a4295c991efa8a397d43118f7e"
[[constraint]]
name = "github.com/microsoft/ApplicationInsights-Go"
revision = "d813d7725313000ad1b71627b8951323635f0572"
[prune]
go-tests = true
unused-packages = true

Просмотреть файл

@ -7,6 +7,7 @@ COREFILES = \
$(wildcard netlink/*.go) \
$(wildcard network/*.go) \
$(wildcard telemetry/*.go) \
$(wildcard aitelemetry/*.go) \
$(wildcard network/epcommon/*.go) \
$(wildcard network/policy/*.go) \
$(wildcard platform/*.go) \
@ -313,6 +314,7 @@ test-all:
./netlink/ \
./store/ \
./telemetry/ \
./aitelemetry/ \
./cnm/network/ \
./cni/ipam/ \
./cns/ipamclient/ \

47
aitelemetry/api.go Normal file
Просмотреть файл

@ -0,0 +1,47 @@
package aitelemetry
import (
"sync"
"github.com/Azure/azure-container-networking/common"
"github.com/microsoft/ApplicationInsights-Go/appinsights"
)
// Application trace/log structure
type Report struct {
Message string
Context string
CustomDimensions map[string]string
}
// Application metrics structure
type Metric struct {
Name string
Value float64
CustomDimensions map[string]string
}
// TelmetryHandle holds appinsight handles and metadata
type telemetryHandle struct {
telemetryConfig *appinsights.TelemetryConfiguration
appName string
appVersion string
metadata common.Metadata
diagListener appinsights.DiagnosticsMessageListener
client appinsights.TelemetryClient
enableMetadataRefreshThread bool
refreshTimeout int
rwmutex sync.RWMutex
}
// Telemetry Interface to send metrics/Logs to appinsights
type TelemetryHandle interface {
// TrackLog function sends report (trace) to appinsights resource. It overrides few of the existing columns with app information
// and for rest it uses custom dimesion
TrackLog(report Report)
// TrackMetric function sends metric to appinsights resource. It overrides few of the existing columns with app information
// and for rest it uses custom dimesion
TrackMetric(metric Metric)
// Close - should be called for each NewAITelemetry call. Will release resources acquired
Close(timeout int)
}

Просмотреть файл

@ -0,0 +1 @@
{"location":"eastus","name":"k8s-agentpool1-42685608-0","offer":"aks","osType":"Linux","placementGroupId":"","platformFaultDomain":"0","platformUpdateDomain":"0","publisher":"microsoft-aks","resourceGroupName":"rgcnideftesttamil","sku":"aks-ubuntu-1604-201902","subscriptionId":"ea821859-912a-4d20-a4dd-e18a3ce5ba2c","tags":"aksEngineVersion:canary;creationSource:aksengine-k8s-agentpool1-42685608-0;orchestrator:Kubernetes:1.10.13;poolName:agentpool1;resourceNameSuffix:42685608","version":"2019.02.12","vmId":"6baf785b-397c-4967-9f75-cdb3d0df66c4","vmSize":"Standard_DS2_v2","KernelVersion":""}

Просмотреть файл

@ -0,0 +1,176 @@
package aitelemetry
import (
"runtime"
"time"
"github.com/Azure/azure-container-networking/common"
"github.com/Azure/azure-container-networking/log"
"github.com/Azure/azure-container-networking/store"
"github.com/microsoft/ApplicationInsights-Go/appinsights"
)
const (
resourceGroupStr = "ResourceGroup"
vmSizeStr = "VMSize"
osVersionStr = "OSVersion"
locationStr = "Region"
appVersionStr = "Appversion"
subscriptionIDStr = "SubscriptionID"
defaultTimeout = 10
)
func messageListener() appinsights.DiagnosticsMessageListener {
return appinsights.NewDiagnosticsMessageListener(func(msg string) error {
log.Printf("[AppInsights] [%s] %s\n", time.Now().Format(time.UnixDate), msg)
return nil
})
}
func getMetadata(th *telemetryHandle) {
var metadata common.Metadata
var err error
// check if metadata in memory otherwise initiate wireserver request
for {
metadata, err = common.GetHostMetadata(metadataFile)
if err == nil || !th.enableMetadataRefreshThread {
break
}
log.Printf("[AppInsights] Error getting metadata %v. Sleep for %d", err, th.refreshTimeout)
time.Sleep(time.Duration(th.refreshTimeout) * time.Second)
}
//acquire write lock before writing metadata to telemetry handle
th.rwmutex.Lock()
th.metadata = metadata
th.rwmutex.Unlock()
// Save metadata retrieved from wireserver to a file
kvs, err := store.NewJsonFileStore(metadataFile)
if err != nil {
log.Printf("[AppInsights] Error initializing kvs store: %v", err)
return
}
kvs.Lock(true)
err = common.SaveHostMetadata(th.metadata, metadataFile)
kvs.Unlock(true)
if err != nil {
log.Printf("[AppInsights] saving host metadata failed with :%v", err)
}
}
// NewAITelemetry creates telemetry handle with user specified appinsights key.
func NewAITelemetry(
key string,
appName string,
appVersion string,
batchSize int,
batchInterval int,
enableMetadataRefreshThread bool,
refreshTimeout int,
) TelemetryHandle {
telemetryConfig := appinsights.NewTelemetryConfiguration(key)
telemetryConfig.MaxBatchSize = batchSize
telemetryConfig.MaxBatchInterval = time.Duration(batchInterval) * time.Second
th := &telemetryHandle{
client: appinsights.NewTelemetryClientFromConfig(telemetryConfig),
appName: appName,
appVersion: appVersion,
diagListener: messageListener(),
enableMetadataRefreshThread: enableMetadataRefreshThread,
refreshTimeout: refreshTimeout,
}
if th.enableMetadataRefreshThread {
go getMetadata(th)
} else {
getMetadata(th)
}
return th
}
// TrackLog function sends report (trace) to appinsights resource. It overrides few of the existing columns with app information
// and for rest it uses custom dimesion
func (th *telemetryHandle) TrackLog(report Report) {
// Initialize new trace message
trace := appinsights.NewTraceTelemetry(report.Message, appinsights.Warning)
//Override few of existing columns with metadata
trace.Tags.User().SetAuthUserId(runtime.GOOS)
trace.Tags.Operation().SetId(report.Context)
trace.Tags.Operation().SetParentId(th.appName)
// copy app specified custom dimension
for key, value := range report.CustomDimensions {
trace.Properties[key] = value
}
trace.Properties[appVersionStr] = th.appVersion
// Acquire read lock to read metadata
th.rwmutex.RLock()
metadata := th.metadata
th.rwmutex.RUnlock()
// Check if metadata is populated
if metadata.SubscriptionID != "" {
// copy metadata from wireserver to trace
trace.Tags.User().SetAccountId(th.metadata.SubscriptionID)
trace.Tags.User().SetId(th.metadata.VMName)
trace.Properties[locationStr] = th.metadata.Location
trace.Properties[resourceGroupStr] = th.metadata.ResourceGroupName
trace.Properties[vmSizeStr] = th.metadata.VMSize
trace.Properties[osVersionStr] = th.metadata.OSVersion
}
// send to appinsights resource
th.client.Track(trace)
}
// TrackMetric function sends metric to appinsights resource. It overrides few of the existing columns with app information
// and for rest it uses custom dimesion
func (th *telemetryHandle) TrackMetric(metric Metric) {
// Initialize new metric
aimetric := appinsights.NewMetricTelemetry(metric.Name, metric.Value)
// Acquire read lock to read metadata
th.rwmutex.RLock()
metadata := th.metadata
th.rwmutex.RUnlock()
// Check if metadata is populated
if metadata.SubscriptionID != "" {
aimetric.Properties[locationStr] = th.metadata.Location
aimetric.Properties[subscriptionIDStr] = th.metadata.SubscriptionID
}
// copy custom dimensions
for key, value := range metric.CustomDimensions {
aimetric.Properties[key] = value
}
// send metric to appinsights
th.client.Track(aimetric)
}
// Close - should be called for each NewAITelemetry call. Will release resources acquired
func (th *telemetryHandle) Close(timeout int) {
if timeout <= 0 {
timeout = defaultTimeout
}
// wait for items to be sent otherwise timeout
<-th.client.Channel().Close(time.Duration(timeout) * time.Second)
// Remove diganostic message listener
if th.diagListener != nil {
th.diagListener.Remove()
th.diagListener = nil
}
}

Просмотреть файл

@ -0,0 +1,5 @@
package aitelemetry
const (
metadataFile = "/tmp/azuremetadata.json"
)

Просмотреть файл

@ -0,0 +1,63 @@
package aitelemetry
import (
"os"
"runtime"
"testing"
"github.com/Azure/azure-container-networking/platform"
)
var th TelemetryHandle
func TestMain(m *testing.M) {
if runtime.GOOS == "linux" {
platform.ExecuteCommand("cp metadata_test.json /tmp/azuremetadata.json")
} else {
platform.ExecuteCommand("copy metadata_test.json azuremetadata.json")
}
exitCode := m.Run()
if runtime.GOOS == "linux" {
platform.ExecuteCommand("rm /tmp/azuremetadata.json")
} else {
platform.ExecuteCommand("del azuremetadata.json")
}
os.Exit(exitCode)
}
func TestNewAITelemetry(t *testing.T) {
th = NewAITelemetry("00ca2a73-c8d6-4929-a0c2-cf84545ec225", "testapp", "v1.0.26", 4096, 2, false, 10)
if th == nil {
t.Errorf("Error intializing AI telemetry")
}
}
func TestTrackMetric(t *testing.T) {
metric := Metric{
Name: "test",
Value: 1.0,
CustomDimensions: make(map[string]string),
}
metric.CustomDimensions["dim1"] = "col1"
th.TrackMetric(metric)
}
func TestTrackLog(t *testing.T) {
report := Report{
Message: "test",
Context: "10a",
CustomDimensions: make(map[string]string),
}
report.CustomDimensions["dim1"] = "col1"
th.TrackLog(report)
}
func TestClose(t *testing.T) {
th.Close(10)
}

Просмотреть файл

@ -0,0 +1,10 @@
package aitelemetry
import (
"os"
"path/filepath"
)
var (
metadataFile = filepath.FromSlash(os.Getenv("TEMP")) + "\\azuremetadata.json"
)

Просмотреть файл

@ -6,15 +6,25 @@ package common
import (
"bufio"
"encoding/binary"
"encoding/json"
"encoding/xml"
"fmt"
"io"
"io/ioutil"
"net"
"net/http"
"os"
"time"
"github.com/Azure/azure-container-networking/log"
)
const (
metadataURL = "http://169.254.169.254/metadata/instance?api-version=2017-08-01&format=json"
httpConnectionTimeout = 10
headerTimeout = 20
)
// XmlDocument - Azure host agent XML document format.
type XmlDocument struct {
XMLName xml.Name `xml:"Interfaces"`
@ -36,6 +46,31 @@ type XmlDocument struct {
}
}
// Metadata retrieved from wireserver
type Metadata struct {
Location string `json:"location"`
VMName string `json:"name"`
Offer string `json:"offer"`
OsType string `json:"osType"`
PlacementGroupID string `json:"placementGroupId"`
PlatformFaultDomain string `json:"platformFaultDomain"`
PlatformUpdateDomain string `json:"platformUpdateDomain"`
Publisher string `json:"publisher"`
ResourceGroupName string `json:"resourceGroupName"`
Sku string `json:"sku"`
SubscriptionID string `json:"subscriptionId"`
Tags string `json:"tags"`
OSVersion string `json:"version"`
VMID string `json:"vmId"`
VMSize string `json:"vmSize"`
KernelVersion string
}
// This is how metadata server returns in response for querying metadata
type metadataWrapper struct {
Metadata Metadata `json:"compute"`
}
// LogNetworkInterfaces logs the host's network interfaces in the default namespace.
func LogNetworkInterfaces() {
interfaces, err := net.Interfaces()
@ -158,3 +193,68 @@ func ReadFileByLines(filename string) ([]string, error) {
return lineStrArr, nil
}
// GetHostMetadata - retrieve VM metadata from wireserver
func GetHostMetadata(fileName string) (Metadata, error) {
content, err := ioutil.ReadFile(fileName)
if err == nil {
var metadata Metadata
if err = json.Unmarshal(content, &metadata); err == nil {
return metadata, nil
}
}
log.Printf("[Telemetry] Request metadata from wireserver")
req, err := http.NewRequest("GET", metadataURL, nil)
if err != nil {
return Metadata{}, err
}
req.Header.Set("Metadata", "True")
client := &http.Client{
Transport: &http.Transport{
DialContext: (&net.Dialer{
Timeout: time.Duration(httpConnectionTimeout) * time.Second,
}).DialContext,
ResponseHeaderTimeout: time.Duration(headerTimeout) * time.Second,
},
}
resp, err := client.Do(req)
if err != nil {
return Metadata{}, err
}
defer resp.Body.Close()
metareport := metadataWrapper{}
if resp.StatusCode != http.StatusOK {
err = fmt.Errorf("[Telemetry] Request failed with HTTP error %d", resp.StatusCode)
} else if resp.Body != nil {
err = json.NewDecoder(resp.Body).Decode(&metareport)
if err != nil {
err = fmt.Errorf("[Telemetry] Unable to decode response body due to error: %s", err.Error())
}
} else {
err = fmt.Errorf("[Telemetry] Response body is empty")
}
return metareport.Metadata, err
}
// SaveHostMetadata - save metadata got from wireserver to json file
func SaveHostMetadata(metadata Metadata, fileName string) error {
dataBytes, err := json.Marshal(metadata)
if err != nil {
return fmt.Errorf("[Telemetry] marshal data failed with err %+v", err)
}
if err = ioutil.WriteFile(fileName, dataBytes, 0644); err != nil {
log.Printf("[Telemetry] Writing metadata to file failed: %v", err)
}
return err
}

Просмотреть файл

@ -75,30 +75,6 @@ type OrchestratorInfo struct {
ErrorMessage string
}
// Metadata retrieved from wireserver
type Metadata struct {
Location string `json:"location"`
VMName string `json:"name"`
Offer string `json:"offer"`
OsType string `json:"osType"`
PlacementGroupID string `json:"placementGroupId"`
PlatformFaultDomain string `json:"platformFaultDomain"`
PlatformUpdateDomain string `json:"platformUpdateDomain"`
Publisher string `json:"publisher"`
ResourceGroupName string `json:"resourceGroupName"`
Sku string `json:"sku"`
SubscriptionID string `json:"subscriptionId"`
Tags string `json:"tags"`
OSVersion string `json:"version"`
VMID string `json:"vmId"`
VMSize string `json:"vmSize"`
KernelVersion string
}
type metadataWrapper struct {
Metadata Metadata `json:"compute"`
}
// Azure CNI Telemetry Report structure.
type CNIReport struct {
IsNewInstance bool
@ -121,7 +97,7 @@ type CNIReport struct {
SystemDetails SystemInfo
InterfaceDetails InterfaceInfo
BridgeDetails BridgeInfo
Metadata Metadata `json:"compute"`
Metadata common.Metadata `json:"compute"`
}
// Azure CNS Telemetry Report structure.
@ -135,7 +111,7 @@ type CNSReport struct {
Timestamp string
UUID string
Errorcode string
Metadata Metadata `json:"compute"`
Metadata common.Metadata `json:"compute"`
}
// ClusterState contains the current kubernetes cluster state.
@ -158,7 +134,7 @@ type NPMReport struct {
UpTime string
Timestamp string
ClusterState ClusterState
Metadata Metadata `json:"compute"`
Metadata common.Metadata `json:"compute"`
}
// DNCReport structure.
@ -176,7 +152,7 @@ type DNCReport struct {
Orchestrator string
ContainerType string
Errorcode string
Metadata Metadata `json:"compute"`
Metadata common.Metadata `json:"compute"`
}
// ReportManager structure.

Просмотреть файл

@ -45,7 +45,7 @@ var sampleCniReport = CNIReport{
IsNewInstance: false,
EventMessage: "[azure-cns] Code:UnknownContainerID {IPConfiguration:{IPSubnet:{IPAddress: PrefixLength:0} DNSServers:[] GatewayIPAddress:} Routes:[] CnetAddressSpace:[] MultiTenancyInfo:{EncapType: ID:0} PrimaryInterfaceIdentifier: LocalIPConfiguration:{IPSubnet:{IPAddress: PrefixLength:0} DNSServers:[] GatewayIPAddress:} {ReturnCode:18 Message:NetworkContainer doesn't exist.}}.",
Timestamp: "2019-02-27 17:44:47.319911225 +0000 UTC",
Metadata: Metadata{
Metadata: common.Metadata{
Location: "EastUS2EUAP",
VMName: "k8s-agentpool1-65609007-0",
Offer: "aks",

Просмотреть файл

@ -22,6 +22,7 @@ import (
"github.com/Azure/azure-container-networking/common"
"github.com/Azure/azure-container-networking/log"
"github.com/Azure/azure-container-networking/platform"
"github.com/Azure/azure-container-networking/store"
)
// TelemetryConfig - telemetry config read by telemetry service
@ -411,14 +412,21 @@ func (tb *TelemetryBuffer) sendToHost() error {
// push - push the report (x) to corresponding slice
func (buf *Buffer) push(x interface{}) {
metadata, err := getHostMetadata()
metadata, err := common.GetHostMetadata(metadataFile)
if err != nil {
log.Logf("Error getting metadata %v", err)
} else {
err = saveHostMetadata(metadata)
kvs, err := store.NewJsonFileStore(metadataFile)
if err != nil {
log.Printf("Error acuiring lock for writing metadata file: %v", err)
}
kvs.Lock(true)
err = common.SaveHostMetadata(metadata, metadataFile)
if err != nil {
log.Logf("saving host metadata failed with :%v", err)
}
kvs.Unlock(true)
}
switch x.(type) {
@ -466,62 +474,6 @@ func (buf *Buffer) reset() {
payloadSize = 0
}
// saveHostMetadata - save metadata got from wireserver to json file
func saveHostMetadata(metadata Metadata) error {
dataBytes, err := json.Marshal(metadata)
if err != nil {
return fmt.Errorf("[Telemetry] marshal data failed with err %+v", err)
}
if err = ioutil.WriteFile(metadataFile, dataBytes, 0644); err != nil {
log.Logf("[Telemetry] Writing metadata to file failed: %v", err)
}
return err
}
// getHostMetadata - retrieve metadata from host
func getHostMetadata() (Metadata, error) {
content, err := ioutil.ReadFile(metadataFile)
if err == nil {
var metadata Metadata
if err = json.Unmarshal(content, &metadata); err == nil {
return metadata, nil
}
}
log.Logf("[Telemetry] Request metadata from wireserver")
req, err := http.NewRequest("GET", metadataURL, nil)
if err != nil {
return Metadata{}, err
}
req.Header.Set("Metadata", "True")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return Metadata{}, err
}
defer resp.Body.Close()
metareport := metadataWrapper{}
if resp.StatusCode != http.StatusOK {
err = fmt.Errorf("[Telemetry] Request failed with HTTP error %d", resp.StatusCode)
} else if resp.Body != nil {
err = json.NewDecoder(resp.Body).Decode(&metareport)
if err != nil {
err = fmt.Errorf("[Telemetry] Unable to decode response body due to error: %s", err.Error())
}
} else {
err = fmt.Errorf("[Telemetry] Response body is empty")
}
return metareport.Metadata, err
}
// WaitForTelemetrySocket - Block still pipe/sock created or until max attempts retried
func WaitForTelemetrySocket(maxAttempt int, waitTimeInMillisecs time.Duration) {
for attempt := 0; attempt < maxAttempt; attempt++ {

201
vendor/code.cloudfoundry.org/clock/LICENSE сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,201 @@
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 [yyyy] [name of copyright owner]
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.

20
vendor/code.cloudfoundry.org/clock/NOTICE сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,20 @@
Copyright (c) 2015-Present CloudFoundry.org Foundation, Inc. All Rights Reserved.
This project contains software that is Copyright (c) 2015 Pivotal Software, Inc.
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.
This project may include a number of subcomponents with separate
copyright notices and license terms. Your use of these subcomponents
is subject to the terms and conditions of each subcomponent's license,
as noted in the LICENSE file.

5
vendor/code.cloudfoundry.org/clock/README.md сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,5 @@
# clock
**Note**: This repository should be imported as `code.cloudfoundry.org/clock`.
Provides a `Clock` interface, useful for injecting time dependencies in tests.

53
vendor/code.cloudfoundry.org/clock/clock.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,53 @@
package clock
import "time"
type Clock interface {
Now() time.Time
Sleep(d time.Duration)
Since(t time.Time) time.Duration
// After waits for the duration to elapse and then sends the current time
// on the returned channel.
// It is equivalent to clock.NewTimer(d).C.
// The underlying Timer is not recovered by the garbage collector
// until the timer fires. If efficiency is a concern, use clock.NewTimer
// instead and call Timer.Stop if the timer is no longer needed.
After(d time.Duration) <-chan time.Time
NewTimer(d time.Duration) Timer
NewTicker(d time.Duration) Ticker
}
type realClock struct{}
func NewClock() Clock {
return &realClock{}
}
func (clock *realClock) Now() time.Time {
return time.Now()
}
func (clock *realClock) Since(t time.Time) time.Duration {
return time.Now().Sub(t)
}
func (clock *realClock) Sleep(d time.Duration) {
<-clock.NewTimer(d).C()
}
func (clock *realClock) After(d time.Duration) <-chan time.Time {
return clock.NewTimer(d).C()
}
func (clock *realClock) NewTimer(d time.Duration) Timer {
return &realTimer{
t: time.NewTimer(d),
}
}
func (clock *realClock) NewTicker(d time.Duration) Ticker {
return &realTicker{
t: time.NewTicker(d),
}
}

1
vendor/code.cloudfoundry.org/clock/package.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
package clock // import "code.cloudfoundry.org/clock"

20
vendor/code.cloudfoundry.org/clock/ticker.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,20 @@
package clock
import "time"
type Ticker interface {
C() <-chan time.Time
Stop()
}
type realTicker struct {
t *time.Ticker
}
func (t *realTicker) C() <-chan time.Time {
return t.t.C
}
func (t *realTicker) Stop() {
t.t.Stop()
}

25
vendor/code.cloudfoundry.org/clock/timer.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,25 @@
package clock
import "time"
type Timer interface {
C() <-chan time.Time
Reset(d time.Duration) bool
Stop() bool
}
type realTimer struct {
t *time.Timer
}
func (t *realTimer) C() <-chan time.Time {
return t.t.C
}
func (t *realTimer) Reset(d time.Duration) bool {
return t.t.Reset(d)
}
func (t *realTimer) Stop() bool {
return t.t.Stop()
}

22
vendor/github.com/Microsoft/ApplicationInsights-Go/LICENSE сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2015-2017 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

155
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/client.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,155 @@
package appinsights
import (
"time"
"github.com/microsoft/ApplicationInsights-Go/appinsights/contracts"
)
// Application Insights telemetry client provides interface to track telemetry
// items.
type TelemetryClient interface {
// Gets the telemetry context for this client. Values found on this
// context will get written out to every telemetry item tracked by
// this client.
Context() *TelemetryContext
// Gets the instrumentation key assigned to this telemetry client.
InstrumentationKey() string
// Gets the telemetry channel used to submit data to the backend.
Channel() TelemetryChannel
// Gets whether this client is enabled and will accept telemetry.
IsEnabled() bool
// Enables or disables the telemetry client. When disabled, telemetry
// is silently swallowed by the client. Defaults to enabled.
SetIsEnabled(enabled bool)
// Submits the specified telemetry item.
Track(telemetry Telemetry)
// Log a user action with the specified name
TrackEvent(name string)
// Log a numeric value that is not specified with a specific event.
// Typically used to send regular reports of performance indicators.
TrackMetric(name string, value float64)
// Log a trace message with the specified severity level.
TrackTrace(name string, severity contracts.SeverityLevel)
// Log an HTTP request with the specified method, URL, duration and
// response code.
TrackRequest(method, url string, duration time.Duration, responseCode string)
// Log a dependency with the specified name, type, target, and
// success status.
TrackRemoteDependency(name, dependencyType, target string, success bool)
// Log an availability test result with the specified test name,
// duration, and success status.
TrackAvailability(name string, duration time.Duration, success bool)
// Log an exception with the specified error, which may be a string,
// error or Stringer. The current callstack is collected
// automatically.
TrackException(err interface{})
}
type telemetryClient struct {
channel TelemetryChannel
context *TelemetryContext
isEnabled bool
}
// Creates a new telemetry client instance that submits telemetry with the
// specified instrumentation key.
func NewTelemetryClient(iKey string) TelemetryClient {
return NewTelemetryClientFromConfig(NewTelemetryConfiguration(iKey))
}
// Creates a new telemetry client instance configured by the specified
// TelemetryConfiguration object.
func NewTelemetryClientFromConfig(config *TelemetryConfiguration) TelemetryClient {
return &telemetryClient{
channel: NewInMemoryChannel(config),
context: config.setupContext(),
isEnabled: true,
}
}
// Gets the telemetry context for this client. Values found on this context
// will get written out to every telemetry item tracked by this client.
func (tc *telemetryClient) Context() *TelemetryContext {
return tc.context
}
// Gets the telemetry channel used to submit data to the backend.
func (tc *telemetryClient) Channel() TelemetryChannel {
return tc.channel
}
// Gets the instrumentation key assigned to this telemetry client.
func (tc *telemetryClient) InstrumentationKey() string {
return tc.context.InstrumentationKey()
}
// Gets whether this client is enabled and will accept telemetry.
func (tc *telemetryClient) IsEnabled() bool {
return tc.isEnabled
}
// Enables or disables the telemetry client. When disabled, telemetry is
// silently swallowed by the client. Defaults to enabled.
func (tc *telemetryClient) SetIsEnabled(isEnabled bool) {
tc.isEnabled = isEnabled
}
// Submits the specified telemetry item.
func (tc *telemetryClient) Track(item Telemetry) {
if tc.isEnabled && item != nil {
tc.channel.Send(tc.context.envelop(item))
}
}
// Log a user action with the specified name
func (tc *telemetryClient) TrackEvent(name string) {
tc.Track(NewEventTelemetry(name))
}
// Log a numeric value that is not specified with a specific event.
// Typically used to send regular reports of performance indicators.
func (tc *telemetryClient) TrackMetric(name string, value float64) {
tc.Track(NewMetricTelemetry(name, value))
}
// Log a trace message with the specified severity level.
func (tc *telemetryClient) TrackTrace(message string, severity contracts.SeverityLevel) {
tc.Track(NewTraceTelemetry(message, severity))
}
// Log an HTTP request with the specified method, URL, duration and response
// code.
func (tc *telemetryClient) TrackRequest(method, url string, duration time.Duration, responseCode string) {
tc.Track(NewRequestTelemetry(method, url, duration, responseCode))
}
// Log a dependency with the specified name, type, target, and success
// status.
func (tc *telemetryClient) TrackRemoteDependency(name, dependencyType, target string, success bool) {
tc.Track(NewRemoteDependencyTelemetry(name, dependencyType, target, success))
}
// Log an availability test result with the specified test name, duration,
// and success status.
func (tc *telemetryClient) TrackAvailability(name string, duration time.Duration, success bool) {
tc.Track(NewAvailabilityTelemetry(name, duration, success))
}
// Log an exception with the specified error, which may be a string, error
// or Stringer. The current callstack is collected automatically.
func (tc *telemetryClient) TrackException(err interface{}) {
tc.Track(newExceptionTelemetry(err, 1))
}

11
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/clock.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,11 @@
package appinsights
// We need to mock out the clock for tests; we'll use this to do it.
import "code.cloudfoundry.org/clock"
var currentClock clock.Clock
func init() {
currentClock = clock.NewClock()
}

48
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/configuration.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,48 @@
package appinsights
import (
"os"
"runtime"
"time"
)
// Configuration data used to initialize a new TelemetryClient.
type TelemetryConfiguration struct {
// Instrumentation key for the client.
InstrumentationKey string
// Endpoint URL where data will be submitted.
EndpointUrl string
// Maximum number of telemetry items that can be submitted in each
// request. If this many items are buffered, the buffer will be
// flushed before MaxBatchInterval expires.
MaxBatchSize int
// Maximum time to wait before sending a batch of telemetry.
MaxBatchInterval time.Duration
}
// Creates a new TelemetryConfiguration object with the specified
// instrumentation key and default values.
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,
}
}
func (config *TelemetryConfiguration) setupContext() *TelemetryContext {
context := NewTelemetryContext(config.InstrumentationKey)
context.Tags.Internal().SetSdkVersion(sdkName + ":" + Version)
context.Tags.Device().SetOsVersion(runtime.GOOS)
if hostname, err := os.Hostname(); err == nil {
context.Tags.Device().SetId(hostname)
context.Tags.Cloud().SetRoleInstance(hostname)
}
return context
}

20
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/constants.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,20 @@
package appinsights
// NOTE: This file was automatically generated.
import "github.com/microsoft/ApplicationInsights-Go/appinsights/contracts"
// Type of the metric data measurement.
const (
Measurement contracts.DataPointType = contracts.Measurement
Aggregation contracts.DataPointType = contracts.Aggregation
)
// Defines the level of severity for the event.
const (
Verbose contracts.SeverityLevel = contracts.Verbose
Information contracts.SeverityLevel = contracts.Information
Warning contracts.SeverityLevel = contracts.Warning
Error contracts.SeverityLevel = contracts.Error
Critical contracts.SeverityLevel = contracts.Critical
)

111
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/contracts/availabilitydata.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,111 @@
package contracts
// NOTE: This file was automatically generated.
// Instances of AvailabilityData represent the result of executing an
// availability test.
type AvailabilityData struct {
Domain
// Schema version
Ver int `json:"ver"`
// Identifier of a test run. Use it to correlate steps of test run and
// telemetry generated by the service.
Id string `json:"id"`
// Name of the test that these availability results represent.
Name string `json:"name"`
// Duration in format: DD.HH:MM:SS.MMMMMM. Must be less than 1000 days.
Duration string `json:"duration"`
// Success flag.
Success bool `json:"success"`
// Name of the location where the test was run from.
RunLocation string `json:"runLocation"`
// Diagnostic message for the result.
Message string `json:"message"`
// Collection of custom properties.
Properties map[string]string `json:"properties,omitempty"`
// Collection of custom measurements.
Measurements map[string]float64 `json:"measurements,omitempty"`
}
// Returns the name used when this is embedded within an Envelope container.
func (data *AvailabilityData) EnvelopeName(key string) string {
if key != "" {
return "Microsoft.ApplicationInsights." + key + ".Availability"
} else {
return "Microsoft.ApplicationInsights.Availability"
}
}
// Returns the base type when placed within a Data object container.
func (data *AvailabilityData) BaseType() string {
return "AvailabilityData"
}
// Truncates string fields that exceed their maximum supported sizes for this
// object and all objects it references. Returns a warning for each affected
// field.
func (data *AvailabilityData) Sanitize() []string {
var warnings []string
if len(data.Id) > 64 {
data.Id = data.Id[:64]
warnings = append(warnings, "AvailabilityData.Id exceeded maximum length of 64")
}
if len(data.Name) > 1024 {
data.Name = data.Name[:1024]
warnings = append(warnings, "AvailabilityData.Name exceeded maximum length of 1024")
}
if len(data.RunLocation) > 1024 {
data.RunLocation = data.RunLocation[:1024]
warnings = append(warnings, "AvailabilityData.RunLocation exceeded maximum length of 1024")
}
if len(data.Message) > 8192 {
data.Message = data.Message[:8192]
warnings = append(warnings, "AvailabilityData.Message exceeded maximum length of 8192")
}
if data.Properties != nil {
for k, v := range data.Properties {
if len(v) > 8192 {
data.Properties[k] = v[:8192]
warnings = append(warnings, "AvailabilityData.Properties has value with length exceeding max of 8192: "+k)
}
if len(k) > 150 {
data.Properties[k[:150]] = data.Properties[k]
delete(data.Properties, k)
warnings = append(warnings, "AvailabilityData.Properties has key with length exceeding max of 150: "+k)
}
}
}
if data.Measurements != nil {
for k, v := range data.Measurements {
if len(k) > 150 {
data.Measurements[k[:150]] = v
delete(data.Measurements, k)
warnings = append(warnings, "AvailabilityData.Measurements has key with length exceeding max of 150: "+k)
}
}
}
return warnings
}
// Creates a new AvailabilityData instance with default values set by the schema.
func NewAvailabilityData() *AvailabilityData {
return &AvailabilityData{
Ver: 2,
}
}

25
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/contracts/base.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,25 @@
package contracts
// NOTE: This file was automatically generated.
// Data struct to contain only C section with custom fields.
type Base struct {
// Name of item (B section) if any. If telemetry data is derived straight from
// this, this should be null.
BaseType string `json:"baseType"`
}
// Truncates string fields that exceed their maximum supported sizes for this
// object and all objects it references. Returns a warning for each affected
// field.
func (data *Base) Sanitize() []string {
var warnings []string
return warnings
}
// Creates a new Base instance with default values set by the schema.
func NewBase() *Base {
return &Base{}
}

153
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/contracts/contexttagkeys.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,153 @@
package contracts
// NOTE: This file was automatically generated.
import "strconv"
const (
// Application version. Information in the application context fields is
// always about the application that is sending the telemetry.
ApplicationVersion string = "ai.application.ver"
// Unique client device id. Computer name in most cases.
DeviceId string = "ai.device.id"
// Device locale using <language>-<REGION> pattern, following RFC 5646.
// Example 'en-US'.
DeviceLocale string = "ai.device.locale"
// Model of the device the end user of the application is using. Used for
// client scenarios. If this field is empty then it is derived from the user
// agent.
DeviceModel string = "ai.device.model"
// Client device OEM name taken from the browser.
DeviceOEMName string = "ai.device.oemName"
// Operating system name and version of the device the end user of the
// application is using. If this field is empty then it is derived from the
// user agent. Example 'Windows 10 Pro 10.0.10586.0'
DeviceOSVersion string = "ai.device.osVersion"
// The type of the device the end user of the application is using. Used
// primarily to distinguish JavaScript telemetry from server side telemetry.
// Examples: 'PC', 'Phone', 'Browser'. 'PC' is the default value.
DeviceType string = "ai.device.type"
// The IP address of the client device. IPv4 and IPv6 are supported.
// Information in the location context fields is always about the end user.
// When telemetry is sent from a service, the location context is about the
// user that initiated the operation in the service.
LocationIp string = "ai.location.ip"
// A unique identifier for the operation instance. The operation.id is created
// by either a request or a page view. All other telemetry sets this to the
// value for the containing request or page view. Operation.id is used for
// finding all the telemetry items for a specific operation instance.
OperationId string = "ai.operation.id"
// The name (group) of the operation. The operation.name is created by either
// a request or a page view. All other telemetry items set this to the value
// for the containing request or page view. Operation.name is used for finding
// all the telemetry items for a group of operations (i.e. 'GET Home/Index').
OperationName string = "ai.operation.name"
// The unique identifier of the telemetry item's immediate parent.
OperationParentId string = "ai.operation.parentId"
// Name of synthetic source. Some telemetry from the application may represent
// a synthetic traffic. It may be web crawler indexing the web site, site
// availability tests or traces from diagnostic libraries like Application
// Insights SDK itself.
OperationSyntheticSource string = "ai.operation.syntheticSource"
// The correlation vector is a light weight vector clock which can be used to
// identify and order related events across clients and services.
OperationCorrelationVector string = "ai.operation.correlationVector"
// Session ID - the instance of the user's interaction with the app.
// Information in the session context fields is always about the end user.
// When telemetry is sent from a service, the session context is about the
// user that initiated the operation in the service.
SessionId string = "ai.session.id"
// Boolean value indicating whether the session identified by ai.session.id is
// first for the user or not.
SessionIsFirst string = "ai.session.isFirst"
// In multi-tenant applications this is the account ID or name which the user
// is acting with. Examples may be subscription ID for Azure portal or blog
// name blogging platform.
UserAccountId string = "ai.user.accountId"
// Anonymous user id. Represents the end user of the application. When
// telemetry is sent from a service, the user context is about the user that
// initiated the operation in the service.
UserId string = "ai.user.id"
// Authenticated user id. The opposite of ai.user.id, this represents the user
// with a friendly name. Since it's PII information it is not collected by
// default by most SDKs.
UserAuthUserId string = "ai.user.authUserId"
// Name of the role the application is a part of. Maps directly to the role
// name in azure.
CloudRole string = "ai.cloud.role"
// Name of the instance where the application is running. Computer name for
// on-premisis, instance name for Azure.
CloudRoleInstance string = "ai.cloud.roleInstance"
// SDK version. See
// https://github.com/microsoft/ApplicationInsights-Home/blob/master/SDK-AUTHORING.md#sdk-version-specification
// for information.
InternalSdkVersion string = "ai.internal.sdkVersion"
// Agent version. Used to indicate the version of StatusMonitor installed on
// the computer if it is used for data collection.
InternalAgentVersion string = "ai.internal.agentVersion"
// This is the node name used for billing purposes. Use it to override the
// standard detection of nodes.
InternalNodeName string = "ai.internal.nodeName"
)
var tagMaxLengths = map[string]int{
"ai.application.ver": 1024,
"ai.device.id": 1024,
"ai.device.locale": 64,
"ai.device.model": 256,
"ai.device.oemName": 256,
"ai.device.osVersion": 256,
"ai.device.type": 64,
"ai.location.ip": 46,
"ai.operation.id": 128,
"ai.operation.name": 1024,
"ai.operation.parentId": 128,
"ai.operation.syntheticSource": 1024,
"ai.operation.correlationVector": 64,
"ai.session.id": 64,
"ai.session.isFirst": 5,
"ai.user.accountId": 1024,
"ai.user.id": 128,
"ai.user.authUserId": 1024,
"ai.cloud.role": 256,
"ai.cloud.roleInstance": 256,
"ai.internal.sdkVersion": 64,
"ai.internal.agentVersion": 64,
"ai.internal.nodeName": 256,
}
// Truncates tag values that exceed their maximum supported lengths. Returns
// warnings for each affected field.
func SanitizeTags(tags map[string]string) []string {
var warnings []string
for k, v := range tags {
if maxlen, ok := tagMaxLengths[k]; ok && len(v) > maxlen {
tags[k] = v[:maxlen]
warnings = append(warnings, "Value for "+k+" exceeded maximum length of "+strconv.Itoa(maxlen))
}
}
return warnings
}

565
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/contracts/contexttags.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,565 @@
package contracts
// NOTE: This file was automatically generated.
type ContextTags map[string]string
// Helper type that provides access to context fields grouped under 'application'.
// This is returned by TelemetryContext.Tags.Application()
type ApplicationContextTags ContextTags
// Helper type that provides access to context fields grouped under 'device'.
// This is returned by TelemetryContext.Tags.Device()
type DeviceContextTags ContextTags
// Helper type that provides access to context fields grouped under 'location'.
// This is returned by TelemetryContext.Tags.Location()
type LocationContextTags ContextTags
// Helper type that provides access to context fields grouped under 'operation'.
// This is returned by TelemetryContext.Tags.Operation()
type OperationContextTags ContextTags
// Helper type that provides access to context fields grouped under 'session'.
// This is returned by TelemetryContext.Tags.Session()
type SessionContextTags ContextTags
// Helper type that provides access to context fields grouped under 'user'.
// This is returned by TelemetryContext.Tags.User()
type UserContextTags ContextTags
// Helper type that provides access to context fields grouped under 'cloud'.
// This is returned by TelemetryContext.Tags.Cloud()
type CloudContextTags ContextTags
// Helper type that provides access to context fields grouped under 'internal'.
// This is returned by TelemetryContext.Tags.Internal()
type InternalContextTags ContextTags
// Returns a helper to access context fields grouped under 'application'.
func (tags ContextTags) Application() ApplicationContextTags {
return ApplicationContextTags(tags)
}
// Returns a helper to access context fields grouped under 'device'.
func (tags ContextTags) Device() DeviceContextTags {
return DeviceContextTags(tags)
}
// Returns a helper to access context fields grouped under 'location'.
func (tags ContextTags) Location() LocationContextTags {
return LocationContextTags(tags)
}
// Returns a helper to access context fields grouped under 'operation'.
func (tags ContextTags) Operation() OperationContextTags {
return OperationContextTags(tags)
}
// Returns a helper to access context fields grouped under 'session'.
func (tags ContextTags) Session() SessionContextTags {
return SessionContextTags(tags)
}
// Returns a helper to access context fields grouped under 'user'.
func (tags ContextTags) User() UserContextTags {
return UserContextTags(tags)
}
// Returns a helper to access context fields grouped under 'cloud'.
func (tags ContextTags) Cloud() CloudContextTags {
return CloudContextTags(tags)
}
// Returns a helper to access context fields grouped under 'internal'.
func (tags ContextTags) Internal() InternalContextTags {
return InternalContextTags(tags)
}
// Application version. Information in the application context fields is
// always about the application that is sending the telemetry.
func (tags ApplicationContextTags) GetVer() string {
if result, ok := tags["ai.application.ver"]; ok {
return result
}
return ""
}
// Application version. Information in the application context fields is
// always about the application that is sending the telemetry.
func (tags ApplicationContextTags) SetVer(value string) {
if value != "" {
tags["ai.application.ver"] = value
} else {
delete(tags, "ai.application.ver")
}
}
// Unique client device id. Computer name in most cases.
func (tags DeviceContextTags) GetId() string {
if result, ok := tags["ai.device.id"]; ok {
return result
}
return ""
}
// Unique client device id. Computer name in most cases.
func (tags DeviceContextTags) SetId(value string) {
if value != "" {
tags["ai.device.id"] = value
} else {
delete(tags, "ai.device.id")
}
}
// Device locale using <language>-<REGION> pattern, following RFC 5646.
// Example 'en-US'.
func (tags DeviceContextTags) GetLocale() string {
if result, ok := tags["ai.device.locale"]; ok {
return result
}
return ""
}
// Device locale using <language>-<REGION> pattern, following RFC 5646.
// Example 'en-US'.
func (tags DeviceContextTags) SetLocale(value string) {
if value != "" {
tags["ai.device.locale"] = value
} else {
delete(tags, "ai.device.locale")
}
}
// Model of the device the end user of the application is using. Used for
// client scenarios. If this field is empty then it is derived from the user
// agent.
func (tags DeviceContextTags) GetModel() string {
if result, ok := tags["ai.device.model"]; ok {
return result
}
return ""
}
// Model of the device the end user of the application is using. Used for
// client scenarios. If this field is empty then it is derived from the user
// agent.
func (tags DeviceContextTags) SetModel(value string) {
if value != "" {
tags["ai.device.model"] = value
} else {
delete(tags, "ai.device.model")
}
}
// Client device OEM name taken from the browser.
func (tags DeviceContextTags) GetOemName() string {
if result, ok := tags["ai.device.oemName"]; ok {
return result
}
return ""
}
// Client device OEM name taken from the browser.
func (tags DeviceContextTags) SetOemName(value string) {
if value != "" {
tags["ai.device.oemName"] = value
} else {
delete(tags, "ai.device.oemName")
}
}
// Operating system name and version of the device the end user of the
// application is using. If this field is empty then it is derived from the
// user agent. Example 'Windows 10 Pro 10.0.10586.0'
func (tags DeviceContextTags) GetOsVersion() string {
if result, ok := tags["ai.device.osVersion"]; ok {
return result
}
return ""
}
// Operating system name and version of the device the end user of the
// application is using. If this field is empty then it is derived from the
// user agent. Example 'Windows 10 Pro 10.0.10586.0'
func (tags DeviceContextTags) SetOsVersion(value string) {
if value != "" {
tags["ai.device.osVersion"] = value
} else {
delete(tags, "ai.device.osVersion")
}
}
// The type of the device the end user of the application is using. Used
// primarily to distinguish JavaScript telemetry from server side telemetry.
// Examples: 'PC', 'Phone', 'Browser'. 'PC' is the default value.
func (tags DeviceContextTags) GetType() string {
if result, ok := tags["ai.device.type"]; ok {
return result
}
return ""
}
// The type of the device the end user of the application is using. Used
// primarily to distinguish JavaScript telemetry from server side telemetry.
// Examples: 'PC', 'Phone', 'Browser'. 'PC' is the default value.
func (tags DeviceContextTags) SetType(value string) {
if value != "" {
tags["ai.device.type"] = value
} else {
delete(tags, "ai.device.type")
}
}
// The IP address of the client device. IPv4 and IPv6 are supported.
// Information in the location context fields is always about the end user.
// When telemetry is sent from a service, the location context is about the
// user that initiated the operation in the service.
func (tags LocationContextTags) GetIp() string {
if result, ok := tags["ai.location.ip"]; ok {
return result
}
return ""
}
// The IP address of the client device. IPv4 and IPv6 are supported.
// Information in the location context fields is always about the end user.
// When telemetry is sent from a service, the location context is about the
// user that initiated the operation in the service.
func (tags LocationContextTags) SetIp(value string) {
if value != "" {
tags["ai.location.ip"] = value
} else {
delete(tags, "ai.location.ip")
}
}
// A unique identifier for the operation instance. The operation.id is created
// by either a request or a page view. All other telemetry sets this to the
// value for the containing request or page view. Operation.id is used for
// finding all the telemetry items for a specific operation instance.
func (tags OperationContextTags) GetId() string {
if result, ok := tags["ai.operation.id"]; ok {
return result
}
return ""
}
// A unique identifier for the operation instance. The operation.id is created
// by either a request or a page view. All other telemetry sets this to the
// value for the containing request or page view. Operation.id is used for
// finding all the telemetry items for a specific operation instance.
func (tags OperationContextTags) SetId(value string) {
if value != "" {
tags["ai.operation.id"] = value
} else {
delete(tags, "ai.operation.id")
}
}
// The name (group) of the operation. The operation.name is created by either
// a request or a page view. All other telemetry items set this to the value
// for the containing request or page view. Operation.name is used for finding
// all the telemetry items for a group of operations (i.e. 'GET Home/Index').
func (tags OperationContextTags) GetName() string {
if result, ok := tags["ai.operation.name"]; ok {
return result
}
return ""
}
// The name (group) of the operation. The operation.name is created by either
// a request or a page view. All other telemetry items set this to the value
// for the containing request or page view. Operation.name is used for finding
// all the telemetry items for a group of operations (i.e. 'GET Home/Index').
func (tags OperationContextTags) SetName(value string) {
if value != "" {
tags["ai.operation.name"] = value
} else {
delete(tags, "ai.operation.name")
}
}
// The unique identifier of the telemetry item's immediate parent.
func (tags OperationContextTags) GetParentId() string {
if result, ok := tags["ai.operation.parentId"]; ok {
return result
}
return ""
}
// The unique identifier of the telemetry item's immediate parent.
func (tags OperationContextTags) SetParentId(value string) {
if value != "" {
tags["ai.operation.parentId"] = value
} else {
delete(tags, "ai.operation.parentId")
}
}
// Name of synthetic source. Some telemetry from the application may represent
// a synthetic traffic. It may be web crawler indexing the web site, site
// availability tests or traces from diagnostic libraries like Application
// Insights SDK itself.
func (tags OperationContextTags) GetSyntheticSource() string {
if result, ok := tags["ai.operation.syntheticSource"]; ok {
return result
}
return ""
}
// Name of synthetic source. Some telemetry from the application may represent
// a synthetic traffic. It may be web crawler indexing the web site, site
// availability tests or traces from diagnostic libraries like Application
// Insights SDK itself.
func (tags OperationContextTags) SetSyntheticSource(value string) {
if value != "" {
tags["ai.operation.syntheticSource"] = value
} else {
delete(tags, "ai.operation.syntheticSource")
}
}
// The correlation vector is a light weight vector clock which can be used to
// identify and order related events across clients and services.
func (tags OperationContextTags) GetCorrelationVector() string {
if result, ok := tags["ai.operation.correlationVector"]; ok {
return result
}
return ""
}
// The correlation vector is a light weight vector clock which can be used to
// identify and order related events across clients and services.
func (tags OperationContextTags) SetCorrelationVector(value string) {
if value != "" {
tags["ai.operation.correlationVector"] = value
} else {
delete(tags, "ai.operation.correlationVector")
}
}
// Session ID - the instance of the user's interaction with the app.
// Information in the session context fields is always about the end user.
// When telemetry is sent from a service, the session context is about the
// user that initiated the operation in the service.
func (tags SessionContextTags) GetId() string {
if result, ok := tags["ai.session.id"]; ok {
return result
}
return ""
}
// Session ID - the instance of the user's interaction with the app.
// Information in the session context fields is always about the end user.
// When telemetry is sent from a service, the session context is about the
// user that initiated the operation in the service.
func (tags SessionContextTags) SetId(value string) {
if value != "" {
tags["ai.session.id"] = value
} else {
delete(tags, "ai.session.id")
}
}
// Boolean value indicating whether the session identified by ai.session.id is
// first for the user or not.
func (tags SessionContextTags) GetIsFirst() string {
if result, ok := tags["ai.session.isFirst"]; ok {
return result
}
return ""
}
// Boolean value indicating whether the session identified by ai.session.id is
// first for the user or not.
func (tags SessionContextTags) SetIsFirst(value string) {
if value != "" {
tags["ai.session.isFirst"] = value
} else {
delete(tags, "ai.session.isFirst")
}
}
// In multi-tenant applications this is the account ID or name which the user
// is acting with. Examples may be subscription ID for Azure portal or blog
// name blogging platform.
func (tags UserContextTags) GetAccountId() string {
if result, ok := tags["ai.user.accountId"]; ok {
return result
}
return ""
}
// In multi-tenant applications this is the account ID or name which the user
// is acting with. Examples may be subscription ID for Azure portal or blog
// name blogging platform.
func (tags UserContextTags) SetAccountId(value string) {
if value != "" {
tags["ai.user.accountId"] = value
} else {
delete(tags, "ai.user.accountId")
}
}
// Anonymous user id. Represents the end user of the application. When
// telemetry is sent from a service, the user context is about the user that
// initiated the operation in the service.
func (tags UserContextTags) GetId() string {
if result, ok := tags["ai.user.id"]; ok {
return result
}
return ""
}
// Anonymous user id. Represents the end user of the application. When
// telemetry is sent from a service, the user context is about the user that
// initiated the operation in the service.
func (tags UserContextTags) SetId(value string) {
if value != "" {
tags["ai.user.id"] = value
} else {
delete(tags, "ai.user.id")
}
}
// Authenticated user id. The opposite of ai.user.id, this represents the user
// with a friendly name. Since it's PII information it is not collected by
// default by most SDKs.
func (tags UserContextTags) GetAuthUserId() string {
if result, ok := tags["ai.user.authUserId"]; ok {
return result
}
return ""
}
// Authenticated user id. The opposite of ai.user.id, this represents the user
// with a friendly name. Since it's PII information it is not collected by
// default by most SDKs.
func (tags UserContextTags) SetAuthUserId(value string) {
if value != "" {
tags["ai.user.authUserId"] = value
} else {
delete(tags, "ai.user.authUserId")
}
}
// Name of the role the application is a part of. Maps directly to the role
// name in azure.
func (tags CloudContextTags) GetRole() string {
if result, ok := tags["ai.cloud.role"]; ok {
return result
}
return ""
}
// Name of the role the application is a part of. Maps directly to the role
// name in azure.
func (tags CloudContextTags) SetRole(value string) {
if value != "" {
tags["ai.cloud.role"] = value
} else {
delete(tags, "ai.cloud.role")
}
}
// Name of the instance where the application is running. Computer name for
// on-premisis, instance name for Azure.
func (tags CloudContextTags) GetRoleInstance() string {
if result, ok := tags["ai.cloud.roleInstance"]; ok {
return result
}
return ""
}
// Name of the instance where the application is running. Computer name for
// on-premisis, instance name for Azure.
func (tags CloudContextTags) SetRoleInstance(value string) {
if value != "" {
tags["ai.cloud.roleInstance"] = value
} else {
delete(tags, "ai.cloud.roleInstance")
}
}
// SDK version. See
// https://github.com/microsoft/ApplicationInsights-Home/blob/master/SDK-AUTHORING.md#sdk-version-specification
// for information.
func (tags InternalContextTags) GetSdkVersion() string {
if result, ok := tags["ai.internal.sdkVersion"]; ok {
return result
}
return ""
}
// SDK version. See
// https://github.com/microsoft/ApplicationInsights-Home/blob/master/SDK-AUTHORING.md#sdk-version-specification
// for information.
func (tags InternalContextTags) SetSdkVersion(value string) {
if value != "" {
tags["ai.internal.sdkVersion"] = value
} else {
delete(tags, "ai.internal.sdkVersion")
}
}
// Agent version. Used to indicate the version of StatusMonitor installed on
// the computer if it is used for data collection.
func (tags InternalContextTags) GetAgentVersion() string {
if result, ok := tags["ai.internal.agentVersion"]; ok {
return result
}
return ""
}
// Agent version. Used to indicate the version of StatusMonitor installed on
// the computer if it is used for data collection.
func (tags InternalContextTags) SetAgentVersion(value string) {
if value != "" {
tags["ai.internal.agentVersion"] = value
} else {
delete(tags, "ai.internal.agentVersion")
}
}
// This is the node name used for billing purposes. Use it to override the
// standard detection of nodes.
func (tags InternalContextTags) GetNodeName() string {
if result, ok := tags["ai.internal.nodeName"]; ok {
return result
}
return ""
}
// This is the node name used for billing purposes. Use it to override the
// standard detection of nodes.
func (tags InternalContextTags) SetNodeName(value string) {
if value != "" {
tags["ai.internal.nodeName"] = value
} else {
delete(tags, "ai.internal.nodeName")
}
}

25
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/contracts/data.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,25 @@
package contracts
// NOTE: This file was automatically generated.
// Data struct to contain both B and C sections.
type Data struct {
Base
// Container for data item (B section).
BaseData interface{} `json:"baseData"`
}
// Truncates string fields that exceed their maximum supported sizes for this
// object and all objects it references. Returns a warning for each affected
// field.
func (data *Data) Sanitize() []string {
var warnings []string
return warnings
}
// Creates a new Data instance with default values set by the schema.
func NewData() *Data {
return &Data{}
}

54
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/contracts/datapoint.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,54 @@
package contracts
// NOTE: This file was automatically generated.
// Metric data single measurement.
type DataPoint struct {
// Name of the metric.
Name string `json:"name"`
// Metric type. Single measurement or the aggregated value.
Kind DataPointType `json:"kind"`
// Single value for measurement. Sum of individual measurements for the
// aggregation.
Value float64 `json:"value"`
// Metric weight of the aggregated metric. Should not be set for a
// measurement.
Count int `json:"count"`
// Minimum value of the aggregated metric. Should not be set for a
// measurement.
Min float64 `json:"min"`
// Maximum value of the aggregated metric. Should not be set for a
// measurement.
Max float64 `json:"max"`
// Standard deviation of the aggregated metric. Should not be set for a
// measurement.
StdDev float64 `json:"stdDev"`
}
// Truncates string fields that exceed their maximum supported sizes for this
// object and all objects it references. Returns a warning for each affected
// field.
func (data *DataPoint) Sanitize() []string {
var warnings []string
if len(data.Name) > 1024 {
data.Name = data.Name[:1024]
warnings = append(warnings, "DataPoint.Name exceeded maximum length of 1024")
}
return warnings
}
// Creates a new DataPoint instance with default values set by the schema.
func NewDataPoint() *DataPoint {
return &DataPoint{
Kind: Measurement,
}
}

22
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/contracts/datapointtype.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,22 @@
package contracts
// NOTE: This file was automatically generated.
// Type of the metric data measurement.
type DataPointType int
const (
Measurement DataPointType = 0
Aggregation DataPointType = 1
)
func (value DataPointType) String() string {
switch int(value) {
case 0:
return "Measurement"
case 1:
return "Aggregation"
default:
return "<unknown DataPointType>"
}
}

21
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/contracts/domain.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,21 @@
package contracts
// NOTE: This file was automatically generated.
// The abstract common base of all domains.
type Domain struct {
}
// Truncates string fields that exceed their maximum supported sizes for this
// object and all objects it references. Returns a warning for each affected
// field.
func (data *Domain) Sanitize() []string {
var warnings []string
return warnings
}
// Creates a new Domain instance with default values set by the schema.
func NewDomain() *Domain {
return &Domain{}
}

82
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/contracts/envelope.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,82 @@
package contracts
// NOTE: This file was automatically generated.
// System variables for a telemetry item.
type Envelope struct {
// Envelope version. For internal use only. By assigning this the default, it
// will not be serialized within the payload unless changed to a value other
// than #1.
Ver int `json:"ver"`
// Type name of telemetry data item.
Name string `json:"name"`
// Event date time when telemetry item was created. This is the wall clock
// time on the client when the event was generated. There is no guarantee that
// the client's time is accurate. This field must be formatted in UTC ISO 8601
// format, with a trailing 'Z' character, as described publicly on
// https://en.wikipedia.org/wiki/ISO_8601#UTC. Note: the number of decimal
// seconds digits provided are variable (and unspecified). Consumers should
// handle this, i.e. managed code consumers should not use format 'O' for
// parsing as it specifies a fixed length. Example:
// 2009-06-15T13:45:30.0000000Z.
Time string `json:"time"`
// Sampling rate used in application. This telemetry item represents 1 /
// sampleRate actual telemetry items.
SampleRate float64 `json:"sampleRate"`
// Sequence field used to track absolute order of uploaded events.
Seq string `json:"seq"`
// The application's instrumentation key. The key is typically represented as
// a GUID, but there are cases when it is not a guid. No code should rely on
// iKey being a GUID. Instrumentation key is case insensitive.
IKey string `json:"iKey"`
// Key/value collection of context properties. See ContextTagKeys for
// information on available properties.
Tags map[string]string `json:"tags,omitempty"`
// Telemetry data item.
Data interface{} `json:"data"`
}
// Truncates string fields that exceed their maximum supported sizes for this
// object and all objects it references. Returns a warning for each affected
// field.
func (data *Envelope) Sanitize() []string {
var warnings []string
if len(data.Name) > 1024 {
data.Name = data.Name[:1024]
warnings = append(warnings, "Envelope.Name exceeded maximum length of 1024")
}
if len(data.Time) > 64 {
data.Time = data.Time[:64]
warnings = append(warnings, "Envelope.Time exceeded maximum length of 64")
}
if len(data.Seq) > 64 {
data.Seq = data.Seq[:64]
warnings = append(warnings, "Envelope.Seq exceeded maximum length of 64")
}
if len(data.IKey) > 40 {
data.IKey = data.IKey[:40]
warnings = append(warnings, "Envelope.IKey exceeded maximum length of 40")
}
return warnings
}
// Creates a new Envelope instance with default values set by the schema.
func NewEnvelope() *Envelope {
return &Envelope{
Ver: 1,
SampleRate: 100.0,
}
}

82
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/contracts/eventdata.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,82 @@
package contracts
// NOTE: This file was automatically generated.
// Instances of Event represent structured event records that can be grouped
// and searched by their properties. Event data item also creates a metric of
// event count by name.
type EventData struct {
Domain
// Schema version
Ver int `json:"ver"`
// Event name. Keep it low cardinality to allow proper grouping and useful
// metrics.
Name string `json:"name"`
// Collection of custom properties.
Properties map[string]string `json:"properties,omitempty"`
// Collection of custom measurements.
Measurements map[string]float64 `json:"measurements,omitempty"`
}
// Returns the name used when this is embedded within an Envelope container.
func (data *EventData) EnvelopeName(key string) string {
if key != "" {
return "Microsoft.ApplicationInsights." + key + ".Event"
} else {
return "Microsoft.ApplicationInsights.Event"
}
}
// Returns the base type when placed within a Data object container.
func (data *EventData) BaseType() string {
return "EventData"
}
// Truncates string fields that exceed their maximum supported sizes for this
// object and all objects it references. Returns a warning for each affected
// field.
func (data *EventData) Sanitize() []string {
var warnings []string
if len(data.Name) > 512 {
data.Name = data.Name[:512]
warnings = append(warnings, "EventData.Name exceeded maximum length of 512")
}
if data.Properties != nil {
for k, v := range data.Properties {
if len(v) > 8192 {
data.Properties[k] = v[:8192]
warnings = append(warnings, "EventData.Properties has value with length exceeding max of 8192: "+k)
}
if len(k) > 150 {
data.Properties[k[:150]] = data.Properties[k]
delete(data.Properties, k)
warnings = append(warnings, "EventData.Properties has key with length exceeding max of 150: "+k)
}
}
}
if data.Measurements != nil {
for k, v := range data.Measurements {
if len(k) > 150 {
data.Measurements[k[:150]] = v
delete(data.Measurements, k)
warnings = append(warnings, "EventData.Measurements has key with length exceeding max of 150: "+k)
}
}
}
return warnings
}
// Creates a new EventData instance with default values set by the schema.
func NewEventData() *EventData {
return &EventData{
Ver: 2,
}
}

93
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/contracts/exceptiondata.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,93 @@
package contracts
// NOTE: This file was automatically generated.
// An instance of Exception represents a handled or unhandled exception that
// occurred during execution of the monitored application.
type ExceptionData struct {
Domain
// Schema version
Ver int `json:"ver"`
// Exception chain - list of inner exceptions.
Exceptions []*ExceptionDetails `json:"exceptions"`
// Severity level. Mostly used to indicate exception severity level when it is
// reported by logging library.
SeverityLevel SeverityLevel `json:"severityLevel"`
// Identifier of where the exception was thrown in code. Used for exceptions
// grouping. Typically a combination of exception type and a function from the
// call stack.
ProblemId string `json:"problemId"`
// Collection of custom properties.
Properties map[string]string `json:"properties,omitempty"`
// Collection of custom measurements.
Measurements map[string]float64 `json:"measurements,omitempty"`
}
// Returns the name used when this is embedded within an Envelope container.
func (data *ExceptionData) EnvelopeName(key string) string {
if key != "" {
return "Microsoft.ApplicationInsights." + key + ".Exception"
} else {
return "Microsoft.ApplicationInsights.Exception"
}
}
// Returns the base type when placed within a Data object container.
func (data *ExceptionData) BaseType() string {
return "ExceptionData"
}
// Truncates string fields that exceed their maximum supported sizes for this
// object and all objects it references. Returns a warning for each affected
// field.
func (data *ExceptionData) Sanitize() []string {
var warnings []string
for _, ptr := range data.Exceptions {
warnings = append(warnings, ptr.Sanitize()...)
}
if len(data.ProblemId) > 1024 {
data.ProblemId = data.ProblemId[:1024]
warnings = append(warnings, "ExceptionData.ProblemId exceeded maximum length of 1024")
}
if data.Properties != nil {
for k, v := range data.Properties {
if len(v) > 8192 {
data.Properties[k] = v[:8192]
warnings = append(warnings, "ExceptionData.Properties has value with length exceeding max of 8192: "+k)
}
if len(k) > 150 {
data.Properties[k[:150]] = data.Properties[k]
delete(data.Properties, k)
warnings = append(warnings, "ExceptionData.Properties has key with length exceeding max of 150: "+k)
}
}
}
if data.Measurements != nil {
for k, v := range data.Measurements {
if len(k) > 150 {
data.Measurements[k[:150]] = v
delete(data.Measurements, k)
warnings = append(warnings, "ExceptionData.Measurements has key with length exceeding max of 150: "+k)
}
}
}
return warnings
}
// Creates a new ExceptionData instance with default values set by the schema.
func NewExceptionData() *ExceptionData {
return &ExceptionData{
Ver: 2,
}
}

66
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/contracts/exceptiondetails.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,66 @@
package contracts
// NOTE: This file was automatically generated.
// Exception details of the exception in a chain.
type ExceptionDetails struct {
// In case exception is nested (outer exception contains inner one), the id
// and outerId properties are used to represent the nesting.
Id int `json:"id"`
// The value of outerId is a reference to an element in ExceptionDetails that
// represents the outer exception
OuterId int `json:"outerId"`
// Exception type name.
TypeName string `json:"typeName"`
// Exception message.
Message string `json:"message"`
// Indicates if full exception stack is provided in the exception. The stack
// may be trimmed, such as in the case of a StackOverflow exception.
HasFullStack bool `json:"hasFullStack"`
// Text describing the stack. Either stack or parsedStack should have a value.
Stack string `json:"stack"`
// List of stack frames. Either stack or parsedStack should have a value.
ParsedStack []*StackFrame `json:"parsedStack,omitempty"`
}
// Truncates string fields that exceed their maximum supported sizes for this
// object and all objects it references. Returns a warning for each affected
// field.
func (data *ExceptionDetails) Sanitize() []string {
var warnings []string
if len(data.TypeName) > 1024 {
data.TypeName = data.TypeName[:1024]
warnings = append(warnings, "ExceptionDetails.TypeName exceeded maximum length of 1024")
}
if len(data.Message) > 32768 {
data.Message = data.Message[:32768]
warnings = append(warnings, "ExceptionDetails.Message exceeded maximum length of 32768")
}
if len(data.Stack) > 32768 {
data.Stack = data.Stack[:32768]
warnings = append(warnings, "ExceptionDetails.Stack exceeded maximum length of 32768")
}
for _, ptr := range data.ParsedStack {
warnings = append(warnings, ptr.Sanitize()...)
}
return warnings
}
// Creates a new ExceptionDetails instance with default values set by the schema.
func NewExceptionDetails() *ExceptionDetails {
return &ExceptionDetails{
HasFullStack: true,
}
}

72
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/contracts/messagedata.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,72 @@
package contracts
// NOTE: This file was automatically generated.
// Instances of Message represent printf-like trace statements that are
// text-searched. Log4Net, NLog and other text-based log file entries are
// translated into intances of this type. The message does not have
// measurements.
type MessageData struct {
Domain
// Schema version
Ver int `json:"ver"`
// Trace message
Message string `json:"message"`
// Trace severity level.
SeverityLevel SeverityLevel `json:"severityLevel"`
// Collection of custom properties.
Properties map[string]string `json:"properties,omitempty"`
}
// Returns the name used when this is embedded within an Envelope container.
func (data *MessageData) EnvelopeName(key string) string {
if key != "" {
return "Microsoft.ApplicationInsights." + key + ".Message"
} else {
return "Microsoft.ApplicationInsights.Message"
}
}
// Returns the base type when placed within a Data object container.
func (data *MessageData) BaseType() string {
return "MessageData"
}
// Truncates string fields that exceed their maximum supported sizes for this
// object and all objects it references. Returns a warning for each affected
// field.
func (data *MessageData) Sanitize() []string {
var warnings []string
if len(data.Message) > 32768 {
data.Message = data.Message[:32768]
warnings = append(warnings, "MessageData.Message exceeded maximum length of 32768")
}
if data.Properties != nil {
for k, v := range data.Properties {
if len(v) > 8192 {
data.Properties[k] = v[:8192]
warnings = append(warnings, "MessageData.Properties has value with length exceeding max of 8192: "+k)
}
if len(k) > 150 {
data.Properties[k[:150]] = data.Properties[k]
delete(data.Properties, k)
warnings = append(warnings, "MessageData.Properties has key with length exceeding max of 150: "+k)
}
}
}
return warnings
}
// Creates a new MessageData instance with default values set by the schema.
func NewMessageData() *MessageData {
return &MessageData{
Ver: 2,
}
}

68
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/contracts/metricdata.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,68 @@
package contracts
// NOTE: This file was automatically generated.
// An instance of the Metric item is a list of measurements (single data
// points) and/or aggregations.
type MetricData struct {
Domain
// Schema version
Ver int `json:"ver"`
// List of metrics. Only one metric in the list is currently supported by
// Application Insights storage. If multiple data points were sent only the
// first one will be used.
Metrics []*DataPoint `json:"metrics"`
// Collection of custom properties.
Properties map[string]string `json:"properties,omitempty"`
}
// Returns the name used when this is embedded within an Envelope container.
func (data *MetricData) EnvelopeName(key string) string {
if key != "" {
return "Microsoft.ApplicationInsights." + key + ".Metric"
} else {
return "Microsoft.ApplicationInsights.Metric"
}
}
// Returns the base type when placed within a Data object container.
func (data *MetricData) BaseType() string {
return "MetricData"
}
// Truncates string fields that exceed their maximum supported sizes for this
// object and all objects it references. Returns a warning for each affected
// field.
func (data *MetricData) Sanitize() []string {
var warnings []string
for _, ptr := range data.Metrics {
warnings = append(warnings, ptr.Sanitize()...)
}
if data.Properties != nil {
for k, v := range data.Properties {
if len(v) > 8192 {
data.Properties[k] = v[:8192]
warnings = append(warnings, "MetricData.Properties has value with length exceeding max of 8192: "+k)
}
if len(k) > 150 {
data.Properties[k[:150]] = data.Properties[k]
delete(data.Properties, k)
warnings = append(warnings, "MetricData.Properties has key with length exceeding max of 150: "+k)
}
}
}
return warnings
}
// Creates a new MetricData instance with default values set by the schema.
func NewMetricData() *MetricData {
return &MetricData{
Ver: 2,
}
}

4
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/contracts/package.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,4 @@
// Data contract definitions for telemetry submitted to Application Insights.
// This is generated from the schemas found at
// https://github.com/microsoft/ApplicationInsights-Home/tree/master/EndpointSpecs/Schemas/Bond
package contracts

85
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/contracts/pageviewdata.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,85 @@
package contracts
// NOTE: This file was automatically generated.
// An instance of PageView represents a generic action on a page like a button
// click. It is also the base type for PageView.
type PageViewData struct {
Domain
EventData
// Request URL with all query string parameters
Url string `json:"url"`
// Request duration in format: DD.HH:MM:SS.MMMMMM. For a page view
// (PageViewData), this is the duration. For a page view with performance
// information (PageViewPerfData), this is the page load time. Must be less
// than 1000 days.
Duration string `json:"duration"`
}
// Returns the name used when this is embedded within an Envelope container.
func (data *PageViewData) EnvelopeName(key string) string {
if key != "" {
return "Microsoft.ApplicationInsights." + key + ".PageView"
} else {
return "Microsoft.ApplicationInsights.PageView"
}
}
// Returns the base type when placed within a Data object container.
func (data *PageViewData) BaseType() string {
return "PageViewData"
}
// Truncates string fields that exceed their maximum supported sizes for this
// object and all objects it references. Returns a warning for each affected
// field.
func (data *PageViewData) Sanitize() []string {
var warnings []string
if len(data.Url) > 2048 {
data.Url = data.Url[:2048]
warnings = append(warnings, "PageViewData.Url exceeded maximum length of 2048")
}
if len(data.Name) > 512 {
data.Name = data.Name[:512]
warnings = append(warnings, "PageViewData.Name exceeded maximum length of 512")
}
if data.Properties != nil {
for k, v := range data.Properties {
if len(v) > 8192 {
data.Properties[k] = v[:8192]
warnings = append(warnings, "PageViewData.Properties has value with length exceeding max of 8192: "+k)
}
if len(k) > 150 {
data.Properties[k[:150]] = data.Properties[k]
delete(data.Properties, k)
warnings = append(warnings, "PageViewData.Properties has key with length exceeding max of 150: "+k)
}
}
}
if data.Measurements != nil {
for k, v := range data.Measurements {
if len(k) > 150 {
data.Measurements[k[:150]] = v
delete(data.Measurements, k)
warnings = append(warnings, "PageViewData.Measurements has key with length exceeding max of 150: "+k)
}
}
}
return warnings
}
// Creates a new PageViewData instance with default values set by the schema.
func NewPageViewData() *PageViewData {
return &PageViewData{
EventData: EventData{
Ver: 2,
},
}
}

134
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/contracts/remotedependencydata.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,134 @@
package contracts
// NOTE: This file was automatically generated.
// An instance of Remote Dependency represents an interaction of the monitored
// component with a remote component/service like SQL or an HTTP endpoint.
type RemoteDependencyData struct {
Domain
// Schema version
Ver int `json:"ver"`
// Name of the command initiated with this dependency call. Low cardinality
// value. Examples are stored procedure name and URL path template.
Name string `json:"name"`
// Identifier of a dependency call instance. Used for correlation with the
// request telemetry item corresponding to this dependency call.
Id string `json:"id"`
// Result code of a dependency call. Examples are SQL error code and HTTP
// status code.
ResultCode string `json:"resultCode"`
// Request duration in format: DD.HH:MM:SS.MMMMMM. Must be less than 1000
// days.
Duration string `json:"duration"`
// Indication of successfull or unsuccessfull call.
Success bool `json:"success"`
// Command initiated by this dependency call. Examples are SQL statement and
// HTTP URL's with all query parameters.
Data string `json:"data"`
// Target site of a dependency call. Examples are server name, host address.
Target string `json:"target"`
// Dependency type name. Very low cardinality value for logical grouping of
// dependencies and interpretation of other fields like commandName and
// resultCode. Examples are SQL, Azure table, and HTTP.
Type string `json:"type"`
// Collection of custom properties.
Properties map[string]string `json:"properties,omitempty"`
// Collection of custom measurements.
Measurements map[string]float64 `json:"measurements,omitempty"`
}
// Returns the name used when this is embedded within an Envelope container.
func (data *RemoteDependencyData) EnvelopeName(key string) string {
if key != "" {
return "Microsoft.ApplicationInsights." + key + ".RemoteDependency"
} else {
return "Microsoft.ApplicationInsights.RemoteDependency"
}
}
// Returns the base type when placed within a Data object container.
func (data *RemoteDependencyData) BaseType() string {
return "RemoteDependencyData"
}
// Truncates string fields that exceed their maximum supported sizes for this
// object and all objects it references. Returns a warning for each affected
// field.
func (data *RemoteDependencyData) Sanitize() []string {
var warnings []string
if len(data.Name) > 1024 {
data.Name = data.Name[:1024]
warnings = append(warnings, "RemoteDependencyData.Name exceeded maximum length of 1024")
}
if len(data.Id) > 128 {
data.Id = data.Id[:128]
warnings = append(warnings, "RemoteDependencyData.Id exceeded maximum length of 128")
}
if len(data.ResultCode) > 1024 {
data.ResultCode = data.ResultCode[:1024]
warnings = append(warnings, "RemoteDependencyData.ResultCode exceeded maximum length of 1024")
}
if len(data.Data) > 8192 {
data.Data = data.Data[:8192]
warnings = append(warnings, "RemoteDependencyData.Data exceeded maximum length of 8192")
}
if len(data.Target) > 1024 {
data.Target = data.Target[:1024]
warnings = append(warnings, "RemoteDependencyData.Target exceeded maximum length of 1024")
}
if len(data.Type) > 1024 {
data.Type = data.Type[:1024]
warnings = append(warnings, "RemoteDependencyData.Type exceeded maximum length of 1024")
}
if data.Properties != nil {
for k, v := range data.Properties {
if len(v) > 8192 {
data.Properties[k] = v[:8192]
warnings = append(warnings, "RemoteDependencyData.Properties has value with length exceeding max of 8192: "+k)
}
if len(k) > 150 {
data.Properties[k[:150]] = data.Properties[k]
delete(data.Properties, k)
warnings = append(warnings, "RemoteDependencyData.Properties has key with length exceeding max of 150: "+k)
}
}
}
if data.Measurements != nil {
for k, v := range data.Measurements {
if len(k) > 150 {
data.Measurements[k[:150]] = v
delete(data.Measurements, k)
warnings = append(warnings, "RemoteDependencyData.Measurements has key with length exceeding max of 150: "+k)
}
}
}
return warnings
}
// Creates a new RemoteDependencyData instance with default values set by the schema.
func NewRemoteDependencyData() *RemoteDependencyData {
return &RemoteDependencyData{
Ver: 2,
Success: true,
}
}

125
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/contracts/requestdata.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,125 @@
package contracts
// NOTE: This file was automatically generated.
// An instance of Request represents completion of an external request to the
// application to do work and contains a summary of that request execution and
// the results.
type RequestData struct {
Domain
// Schema version
Ver int `json:"ver"`
// Identifier of a request call instance. Used for correlation between request
// and other telemetry items.
Id string `json:"id"`
// Source of the request. Examples are the instrumentation key of the caller
// or the ip address of the caller.
Source string `json:"source"`
// Name of the request. Represents code path taken to process request. Low
// cardinality value to allow better grouping of requests. For HTTP requests
// it represents the HTTP method and URL path template like 'GET
// /values/{id}'.
Name string `json:"name"`
// Request duration in format: DD.HH:MM:SS.MMMMMM. Must be less than 1000
// days.
Duration string `json:"duration"`
// Result of a request execution. HTTP status code for HTTP requests.
ResponseCode string `json:"responseCode"`
// Indication of successfull or unsuccessfull call.
Success bool `json:"success"`
// Request URL with all query string parameters.
Url string `json:"url"`
// Collection of custom properties.
Properties map[string]string `json:"properties,omitempty"`
// Collection of custom measurements.
Measurements map[string]float64 `json:"measurements,omitempty"`
}
// Returns the name used when this is embedded within an Envelope container.
func (data *RequestData) EnvelopeName(key string) string {
if key != "" {
return "Microsoft.ApplicationInsights." + key + ".Request"
} else {
return "Microsoft.ApplicationInsights.Request"
}
}
// Returns the base type when placed within a Data object container.
func (data *RequestData) BaseType() string {
return "RequestData"
}
// Truncates string fields that exceed their maximum supported sizes for this
// object and all objects it references. Returns a warning for each affected
// field.
func (data *RequestData) Sanitize() []string {
var warnings []string
if len(data.Id) > 128 {
data.Id = data.Id[:128]
warnings = append(warnings, "RequestData.Id exceeded maximum length of 128")
}
if len(data.Source) > 1024 {
data.Source = data.Source[:1024]
warnings = append(warnings, "RequestData.Source exceeded maximum length of 1024")
}
if len(data.Name) > 1024 {
data.Name = data.Name[:1024]
warnings = append(warnings, "RequestData.Name exceeded maximum length of 1024")
}
if len(data.ResponseCode) > 1024 {
data.ResponseCode = data.ResponseCode[:1024]
warnings = append(warnings, "RequestData.ResponseCode exceeded maximum length of 1024")
}
if len(data.Url) > 2048 {
data.Url = data.Url[:2048]
warnings = append(warnings, "RequestData.Url exceeded maximum length of 2048")
}
if data.Properties != nil {
for k, v := range data.Properties {
if len(v) > 8192 {
data.Properties[k] = v[:8192]
warnings = append(warnings, "RequestData.Properties has value with length exceeding max of 8192: "+k)
}
if len(k) > 150 {
data.Properties[k[:150]] = data.Properties[k]
delete(data.Properties, k)
warnings = append(warnings, "RequestData.Properties has key with length exceeding max of 150: "+k)
}
}
}
if data.Measurements != nil {
for k, v := range data.Measurements {
if len(k) > 150 {
data.Measurements[k[:150]] = v
delete(data.Measurements, k)
warnings = append(warnings, "RequestData.Measurements has key with length exceeding max of 150: "+k)
}
}
}
return warnings
}
// Creates a new RequestData instance with default values set by the schema.
func NewRequestData() *RequestData {
return &RequestData{
Ver: 2,
}
}

31
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/contracts/severitylevel.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,31 @@
package contracts
// NOTE: This file was automatically generated.
// Defines the level of severity for the event.
type SeverityLevel int
const (
Verbose SeverityLevel = 0
Information SeverityLevel = 1
Warning SeverityLevel = 2
Error SeverityLevel = 3
Critical SeverityLevel = 4
)
func (value SeverityLevel) String() string {
switch int(value) {
case 0:
return "Verbose"
case 1:
return "Information"
case 2:
return "Warning"
case 3:
return "Error"
case 4:
return "Critical"
default:
return "<unknown SeverityLevel>"
}
}

52
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/contracts/stackframe.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,52 @@
package contracts
// NOTE: This file was automatically generated.
// Stack frame information.
type StackFrame struct {
// Level in the call stack. For the long stacks SDK may not report every
// function in a call stack.
Level int `json:"level"`
// Method name.
Method string `json:"method"`
// Name of the assembly (dll, jar, etc.) containing this function.
Assembly string `json:"assembly"`
// File name or URL of the method implementation.
FileName string `json:"fileName"`
// Line number of the code implementation.
Line int `json:"line"`
}
// Truncates string fields that exceed their maximum supported sizes for this
// object and all objects it references. Returns a warning for each affected
// field.
func (data *StackFrame) Sanitize() []string {
var warnings []string
if len(data.Method) > 1024 {
data.Method = data.Method[:1024]
warnings = append(warnings, "StackFrame.Method exceeded maximum length of 1024")
}
if len(data.Assembly) > 1024 {
data.Assembly = data.Assembly[:1024]
warnings = append(warnings, "StackFrame.Assembly exceeded maximum length of 1024")
}
if len(data.FileName) > 1024 {
data.FileName = data.FileName[:1024]
warnings = append(warnings, "StackFrame.FileName exceeded maximum length of 1024")
}
return warnings
}
// Creates a new StackFrame instance with default values set by the schema.
func NewStackFrame() *StackFrame {
return &StackFrame{}
}

88
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/diagnostics.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,88 @@
package appinsights
import (
"fmt"
"sync"
)
type diagnosticsMessageWriter struct {
listeners []*diagnosticsMessageListener
lock sync.Mutex
}
// Handler function for receiving diagnostics messages. If this returns an
// error, then the listener will be removed.
type DiagnosticsMessageHandler func(string) error
// Listener type returned by NewDiagnosticsMessageListener.
type DiagnosticsMessageListener interface {
// Stop receiving diagnostics messages from this listener.
Remove()
}
type diagnosticsMessageListener struct {
handler DiagnosticsMessageHandler
writer *diagnosticsMessageWriter
}
func (listener *diagnosticsMessageListener) Remove() {
listener.writer.removeListener(listener)
}
// The one and only diagnostics writer.
var diagnosticsWriter = &diagnosticsMessageWriter{}
// Subscribes the specified handler to diagnostics messages from the SDK. The
// returned interface can be used to unsubscribe.
func NewDiagnosticsMessageListener(handler DiagnosticsMessageHandler) DiagnosticsMessageListener {
listener := &diagnosticsMessageListener{
handler: handler,
writer: diagnosticsWriter,
}
diagnosticsWriter.appendListener(listener)
return listener
}
func (writer *diagnosticsMessageWriter) appendListener(listener *diagnosticsMessageListener) {
writer.lock.Lock()
defer writer.lock.Unlock()
writer.listeners = append(writer.listeners, listener)
}
func (writer *diagnosticsMessageWriter) removeListener(listener *diagnosticsMessageListener) {
writer.lock.Lock()
defer writer.lock.Unlock()
for i := 0; i < len(writer.listeners); i++ {
if writer.listeners[i] == listener {
writer.listeners[i] = writer.listeners[len(writer.listeners)-1]
writer.listeners = writer.listeners[:len(writer.listeners)-1]
return
}
}
}
func (writer *diagnosticsMessageWriter) Write(message string) {
var toRemove []*diagnosticsMessageListener
for _, listener := range writer.listeners {
if err := listener.handler(message); err != nil {
toRemove = append(toRemove, listener)
}
}
for _, listener := range toRemove {
listener.Remove()
}
}
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
}

150
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/exception.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,150 @@
package appinsights
import (
"fmt"
"reflect"
"runtime"
"strings"
"github.com/microsoft/ApplicationInsights-Go/appinsights/contracts"
)
// Exception telemetry items represent a handled or unhandled exceptions that
// occurred during execution of the monitored application.
type ExceptionTelemetry struct {
BaseTelemetry
BaseTelemetryMeasurements
// Panic message: string, error, or Stringer
Error interface{}
// List of stack frames. Use GetCallstack to generate this data.
Frames []*contracts.StackFrame
// Severity level.
SeverityLevel contracts.SeverityLevel
}
// Creates a new exception telemetry item with the specified error and the
// current callstack. This should be used directly from a function that
// handles a recover(), or to report an unexpected error return value from
// a function.
func NewExceptionTelemetry(err interface{}) *ExceptionTelemetry {
return newExceptionTelemetry(err, 1)
}
func newExceptionTelemetry(err interface{}, skip int) *ExceptionTelemetry {
return &ExceptionTelemetry{
Error: err,
Frames: GetCallstack(2 + skip),
SeverityLevel: Error,
BaseTelemetry: BaseTelemetry{
Timestamp: currentClock.Now(),
Tags: make(contracts.ContextTags),
Properties: make(map[string]string),
},
BaseTelemetryMeasurements: BaseTelemetryMeasurements{
Measurements: make(map[string]float64),
},
}
}
func (telem *ExceptionTelemetry) TelemetryData() TelemetryData {
details := contracts.NewExceptionDetails()
details.HasFullStack = len(telem.Frames) > 0
details.ParsedStack = telem.Frames
if err, ok := telem.Error.(error); ok {
details.Message = err.Error()
details.TypeName = reflect.TypeOf(telem.Error).String()
} else if str, ok := telem.Error.(string); ok {
details.Message = str
details.TypeName = "string"
} else if stringer, ok := telem.Error.(fmt.Stringer); ok {
details.Message = stringer.String()
details.TypeName = reflect.TypeOf(telem.Error).String()
} else if stringer, ok := telem.Error.(fmt.GoStringer); ok {
details.Message = stringer.GoString()
details.TypeName = reflect.TypeOf(telem.Error).String()
} else {
details.Message = "<unknown>"
details.TypeName = "<unknown>"
}
data := contracts.NewExceptionData()
data.SeverityLevel = telem.SeverityLevel
data.Exceptions = []*contracts.ExceptionDetails{details}
data.Properties = telem.Properties
data.Measurements = telem.Measurements
return data
}
// Generates a callstack suitable for inclusion in Application Insights
// exception telemetry for the current goroutine, skipping a number of frames
// specified by skip.
func GetCallstack(skip int) []*contracts.StackFrame {
var stackFrames []*contracts.StackFrame
if skip < 0 {
skip = 0
}
stack := make([]uintptr, 64+skip)
depth := runtime.Callers(skip+1, stack)
if depth == 0 {
return stackFrames
}
frames := runtime.CallersFrames(stack[:depth])
level := 0
for {
frame, more := frames.Next()
stackFrame := &contracts.StackFrame{
Level: level,
FileName: frame.File,
Line: frame.Line,
}
if frame.Function != "" {
/* Default */
stackFrame.Method = frame.Function
/* Break up function into assembly/function */
lastSlash := strings.LastIndexByte(frame.Function, '/')
if lastSlash < 0 {
// e.g. "runtime.gopanic"
// The below works with lastSlash=0
lastSlash = 0
}
firstDot := strings.IndexByte(frame.Function[lastSlash:], '.')
if firstDot >= 0 {
stackFrame.Assembly = frame.Function[:lastSlash+firstDot]
stackFrame.Method = frame.Function[lastSlash+firstDot+1:]
}
}
stackFrames = append(stackFrames, stackFrame)
level++
if !more {
break
}
}
return stackFrames
}
// Recovers from any active panics and tracks them to the specified
// TelemetryClient. If rethrow is set to true, then this will panic.
// Should be invoked via defer in functions to monitor.
func TrackPanic(client TelemetryClient, rethrow bool) {
if r := recover(); r != nil {
client.Track(newExceptionTelemetry(r, 1))
if rethrow {
panic(r)
}
}
}

449
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/inmemorychannel.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,449 @@
package appinsights
import (
"sync"
"time"
"code.cloudfoundry.org/clock"
"github.com/microsoft/ApplicationInsights-Go/appinsights/contracts"
)
var (
submit_retries = []time.Duration{time.Duration(10 * time.Second), time.Duration(30 * time.Second), time.Duration(60 * time.Second)}
)
// A telemetry channel that stores events exclusively in memory. Presently
// the only telemetry channel implementation available.
type InMemoryChannel struct {
endpointAddress string
isDeveloperMode bool
collectChan chan *contracts.Envelope
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{}
}
// Creates an InMemoryChannel instance and starts a background submission
// goroutine.
func NewInMemoryChannel(config *TelemetryConfiguration) *InMemoryChannel {
channel := &InMemoryChannel{
endpointAddress: config.EndpointUrl,
collectChan: make(chan *contracts.Envelope),
controlChan: make(chan *inMemoryChannelControl),
batchSize: config.MaxBatchSize,
batchInterval: config.MaxBatchInterval,
throttle: newThrottleManager(),
transmitter: newTransmitter(config.EndpointUrl),
}
go channel.acceptLoop()
return channel
}
// The address of the endpoint to which telemetry is sent
func (channel *InMemoryChannel) EndpointAddress() string {
return channel.endpointAddress
}
// Queues a single telemetry item
func (channel *InMemoryChannel) Send(item *contracts.Envelope) {
if item != nil && channel.collectChan != nil {
channel.collectChan <- item
}
}
// Forces the current queue to be sent
func (channel *InMemoryChannel) Flush() {
if channel.controlChan != nil {
channel.controlChan <- &inMemoryChannelControl{
flush: true,
}
}
}
// 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().
func (channel *InMemoryChannel) Stop() {
if channel.controlChan != nil {
channel.controlChan <- &inMemoryChannelControl{
stop: true,
}
}
}
// Returns true if this channel has been throttled by the data collector.
func (channel *InMemoryChannel) IsThrottled() bool {
return channel.throttle != nil && channel.throttle.IsThrottled()
}
// 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.
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 {
// Initialize timer to stopped -- avoid any chance of a race condition.
timer := currentClock.NewTimer(time.Hour)
timer.Stop()
return &inMemoryChannelState{
channel: channel,
buffer: make(telemetryBufferItems, 0, 16),
stopping: false,
timer: timer,
}
}
// 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 {
if len(state.buffer) >= state.channel.batchSize {
if !state.timer.Stop() {
<-state.timer.C()
}
return state.send()
}
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:
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 {
if !state.timer.Stop() {
<-state.timer.C()
}
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)
}()
}
}

25
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/jsonserializer.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,25 @@
package appinsights
import (
"bytes"
"encoding/json"
"github.com/microsoft/ApplicationInsights-Go/appinsights/contracts"
)
type telemetryBufferItems []*contracts.Envelope
func (items telemetryBufferItems) serialize() []byte {
var result bytes.Buffer
encoder := json.NewEncoder(&result)
for _, item := range items {
end := result.Len()
if err := encoder.Encode(item); err != nil {
diagnosticsWriter.Printf("Telemetry item failed to serialize: %s", err.Error())
result.Truncate(end)
}
}
return result.Bytes()
}

8
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/package.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,8 @@
// Package appinsights provides an interface to submit telemetry to Application Insights.
// See more at https://azure.microsoft.com/en-us/services/application-insights/
package appinsights
const (
sdkName = "go"
Version = "0.4.2"
)

652
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/telemetry.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,652 @@
package appinsights
import (
"fmt"
"math"
"net/url"
"strconv"
"time"
"github.com/microsoft/ApplicationInsights-Go/appinsights/contracts"
)
// Common interface implemented by telemetry data contracts
type TelemetryData interface {
EnvelopeName(string) string
BaseType() string
Sanitize() []string
}
// Common interface implemented by telemetry items that can be passed to
// TelemetryClient.Track
type Telemetry interface {
// Gets the time when this item was measured
Time() time.Time
// Sets the timestamp to the specified time.
SetTime(time.Time)
// Gets context data containing extra, optional tags. Overrides
// values found on client TelemetryContext.
ContextTags() map[string]string
// Gets the data contract as it will be submitted to the data
// collector.
TelemetryData() TelemetryData
// Gets custom properties to submit with the telemetry item.
GetProperties() map[string]string
// Gets custom measurements to submit with the telemetry item.
GetMeasurements() map[string]float64
}
// BaseTelemetry is the common base struct for telemetry items.
type BaseTelemetry struct {
// The time this when this item was measured
Timestamp time.Time
// Custom properties
Properties map[string]string
// Telemetry Context containing extra, optional tags.
Tags contracts.ContextTags
}
// BaseTelemetryMeasurements provides the Measurements field for telemetry
// items that support it.
type BaseTelemetryMeasurements struct {
// Custom measurements
Measurements map[string]float64
}
// BaseTelemetryNoMeasurements provides no Measurements field for telemetry
// items that omit it.
type BaseTelemetryNoMeasurements struct {
}
// Time returns the timestamp when this was measured.
func (item *BaseTelemetry) Time() time.Time {
return item.Timestamp
}
// SetTime sets the timestamp to the specified time.
func (item *BaseTelemetry) SetTime(t time.Time) {
item.Timestamp = t
}
// Gets context data containing extra, optional tags. Overrides values
// found on client TelemetryContext.
func (item *BaseTelemetry) ContextTags() map[string]string {
return item.Tags
}
// Gets custom properties to submit with the telemetry item.
func (item *BaseTelemetry) GetProperties() map[string]string {
return item.Properties
}
// Gets custom measurements to submit with the telemetry item.
func (item *BaseTelemetryMeasurements) GetMeasurements() map[string]float64 {
return item.Measurements
}
// GetMeasurements returns nil for telemetry items that do not support measurements.
func (item *BaseTelemetryNoMeasurements) GetMeasurements() map[string]float64 {
return nil
}
// Trace telemetry items represent printf-like trace statements that can be
// text searched.
type TraceTelemetry struct {
BaseTelemetry
BaseTelemetryNoMeasurements
// Trace message
Message string
// Severity level
SeverityLevel contracts.SeverityLevel
}
// Creates a trace telemetry item with the specified message and severity
// level.
func NewTraceTelemetry(message string, severityLevel contracts.SeverityLevel) *TraceTelemetry {
return &TraceTelemetry{
Message: message,
SeverityLevel: severityLevel,
BaseTelemetry: BaseTelemetry{
Timestamp: currentClock.Now(),
Tags: make(contracts.ContextTags),
Properties: make(map[string]string),
},
}
}
func (trace *TraceTelemetry) TelemetryData() TelemetryData {
data := contracts.NewMessageData()
data.Message = trace.Message
data.Properties = trace.Properties
data.SeverityLevel = trace.SeverityLevel
return data
}
// Event telemetry items represent structured event records.
type EventTelemetry struct {
BaseTelemetry
BaseTelemetryMeasurements
// Event name
Name string
}
// Creates an event telemetry item with the specified name.
func NewEventTelemetry(name string) *EventTelemetry {
return &EventTelemetry{
Name: name,
BaseTelemetry: BaseTelemetry{
Timestamp: currentClock.Now(),
Tags: make(contracts.ContextTags),
Properties: make(map[string]string),
},
BaseTelemetryMeasurements: BaseTelemetryMeasurements{
Measurements: make(map[string]float64),
},
}
}
func (event *EventTelemetry) TelemetryData() TelemetryData {
data := contracts.NewEventData()
data.Name = event.Name
data.Properties = event.Properties
data.Measurements = event.Measurements
return data
}
// Metric telemetry items each represent a single data point.
type MetricTelemetry struct {
BaseTelemetry
BaseTelemetryNoMeasurements
// Metric name
Name string
// Sampled value
Value float64
}
// Creates a metric telemetry sample with the specified name and value.
func NewMetricTelemetry(name string, value float64) *MetricTelemetry {
return &MetricTelemetry{
Name: name,
Value: value,
BaseTelemetry: BaseTelemetry{
Timestamp: currentClock.Now(),
Tags: make(contracts.ContextTags),
Properties: make(map[string]string),
},
}
}
func (metric *MetricTelemetry) TelemetryData() TelemetryData {
dataPoint := contracts.NewDataPoint()
dataPoint.Name = metric.Name
dataPoint.Value = metric.Value
dataPoint.Count = 1
dataPoint.Kind = contracts.Measurement
data := contracts.NewMetricData()
data.Metrics = []*contracts.DataPoint{dataPoint}
data.Properties = metric.Properties
return data
}
// Aggregated metric telemetry items represent an aggregation of data points
// over time. These values can be calculated by the caller or with the AddData
// function.
type AggregateMetricTelemetry struct {
BaseTelemetry
BaseTelemetryNoMeasurements
// Metric name
Name string
// Sum of individual measurements
Value float64
// Minimum value of the aggregated metric
Min float64
// Maximum value of the aggregated metric
Max float64
// Count of measurements in the sample
Count int
// Standard deviation of the aggregated metric
StdDev float64
// Variance of the aggregated metric. As an invariant,
// either this or the StdDev should be zero at any given time.
// If both are non-zero then StdDev takes precedence.
Variance float64
}
// Creates a new aggregated metric telemetry item with the specified name.
// Values should be set on the object returned before submission.
func NewAggregateMetricTelemetry(name string) *AggregateMetricTelemetry {
return &AggregateMetricTelemetry{
Name: name,
Count: 0,
BaseTelemetry: BaseTelemetry{
Timestamp: currentClock.Now(),
Tags: make(contracts.ContextTags),
Properties: make(map[string]string),
},
}
}
// Adds data points to the aggregate totals included in this telemetry item.
// This can be used for all the data at once or incrementally. Calculates
// Min, Max, Sum, Count, and StdDev (by way of Variance).
func (agg *AggregateMetricTelemetry) AddData(values []float64) {
if agg.StdDev != 0.0 {
// If StdDev is non-zero, then square it to produce
// the variance, which is better for incremental calculations,
// and then zero it out.
agg.Variance = agg.StdDev * agg.StdDev
agg.StdDev = 0.0
}
vsum := agg.addData(values, agg.Variance*float64(agg.Count))
if agg.Count > 0 {
agg.Variance = vsum / float64(agg.Count)
}
}
// Adds sampled data points to the aggregate totals included in this telemetry item.
// This can be used for all the data at once or incrementally. Differs from AddData
// in how it calculates standard deviation, and should not be used interchangeably
// with AddData.
func (agg *AggregateMetricTelemetry) AddSampledData(values []float64) {
if agg.StdDev != 0.0 {
// If StdDev is non-zero, then square it to produce
// the variance, which is better for incremental calculations,
// and then zero it out.
agg.Variance = agg.StdDev * agg.StdDev
agg.StdDev = 0.0
}
vsum := agg.addData(values, agg.Variance*float64(agg.Count-1))
if agg.Count > 1 {
// Sampled values should divide by n-1
agg.Variance = vsum / float64(agg.Count-1)
}
}
func (agg *AggregateMetricTelemetry) addData(values []float64, vsum float64) float64 {
if len(values) == 0 {
return vsum
}
// Running tally of the mean is important for incremental variance computation.
var mean float64
if agg.Count == 0 {
agg.Min = values[0]
agg.Max = values[0]
} else {
mean = agg.Value / float64(agg.Count)
}
for _, x := range values {
// Update Min, Max, Count, and Value
agg.Count++
agg.Value += x
if x < agg.Min {
agg.Min = x
}
if x > agg.Max {
agg.Max = x
}
// Welford's algorithm to compute variance. The divide occurs in the caller.
newMean := agg.Value / float64(agg.Count)
vsum += (x - mean) * (x - newMean)
mean = newMean
}
return vsum
}
func (agg *AggregateMetricTelemetry) TelemetryData() TelemetryData {
dataPoint := contracts.NewDataPoint()
dataPoint.Name = agg.Name
dataPoint.Value = agg.Value
dataPoint.Kind = contracts.Aggregation
dataPoint.Min = agg.Min
dataPoint.Max = agg.Max
dataPoint.Count = agg.Count
if agg.StdDev != 0.0 {
dataPoint.StdDev = agg.StdDev
} else if agg.Variance > 0.0 {
dataPoint.StdDev = math.Sqrt(agg.Variance)
}
data := contracts.NewMetricData()
data.Metrics = []*contracts.DataPoint{dataPoint}
data.Properties = agg.Properties
return data
}
// Request telemetry items represents completion of an external request to the
// application and contains a summary of that request execution and results.
type RequestTelemetry struct {
BaseTelemetry
BaseTelemetryMeasurements
// Identifier of a request call instance. Used for correlation between request
// and other telemetry items.
Id string
// Request name. For HTTP requests it represents the HTTP method and URL path template.
Name string
// URL of the request with all query string parameters.
Url string
// Duration to serve the request.
Duration time.Duration
// Results of a request execution. HTTP status code for HTTP requests.
ResponseCode string
// Indication of successful or unsuccessful call.
Success bool
// Source of the request. Examplese are the instrumentation key of the caller
// or the ip address of the caller.
Source string
}
// Creates a new request telemetry item for HTTP requests. The success value will be
// computed from responseCode, and the timestamp will be set to the current time minus
// the duration.
func NewRequestTelemetry(method, uri string, duration time.Duration, responseCode string) *RequestTelemetry {
success := true
code, err := strconv.Atoi(responseCode)
if err == nil {
success = code < 400 || code == 401
}
nameUri := uri
// Sanitize URL for the request name
if parsedUrl, err := url.Parse(uri); err == nil {
// Remove the query
parsedUrl.RawQuery = ""
parsedUrl.ForceQuery = false
// Remove the fragment
parsedUrl.Fragment = ""
// Remove the user info, if any.
parsedUrl.User = nil
// Write back to name
nameUri = parsedUrl.String()
}
return &RequestTelemetry{
Name: fmt.Sprintf("%s %s", method, nameUri),
Url: uri,
Id: newUUID().String(),
Duration: duration,
ResponseCode: responseCode,
Success: success,
BaseTelemetry: BaseTelemetry{
Timestamp: currentClock.Now().Add(-duration),
Tags: make(contracts.ContextTags),
Properties: make(map[string]string),
},
BaseTelemetryMeasurements: BaseTelemetryMeasurements{
Measurements: make(map[string]float64),
},
}
}
// Sets the timestamp and duration of this telemetry item based on the provided
// start and end times.
func (request *RequestTelemetry) MarkTime(startTime, endTime time.Time) {
request.Timestamp = startTime
request.Duration = endTime.Sub(startTime)
}
func (request *RequestTelemetry) TelemetryData() TelemetryData {
data := contracts.NewRequestData()
data.Name = request.Name
data.Duration = formatDuration(request.Duration)
data.ResponseCode = request.ResponseCode
data.Success = request.Success
data.Url = request.Url
data.Source = request.Source
if request.Id == "" {
data.Id = newUUID().String()
} else {
data.Id = request.Id
}
data.Properties = request.Properties
data.Measurements = request.Measurements
return data
}
// Remote dependency telemetry items represent interactions of the monitored
// component with a remote component/service like SQL or an HTTP endpoint.
type RemoteDependencyTelemetry struct {
BaseTelemetry
BaseTelemetryMeasurements
// Name of the command that initiated this dependency call. Low cardinality
// value. Examples are stored procedure name and URL path template.
Name string
// Identifier of a dependency call instance. Used for correlation with the
// request telemetry item corresponding to this dependency call.
Id string
// Result code of a dependency call. Examples are SQL error code and HTTP
// status code.
ResultCode string
// Duration of the remote call.
Duration time.Duration
// Indication of successful or unsuccessful call.
Success bool
// Command initiated by this dependency call. Examples are SQL statement and
// HTTP URL's with all the query parameters.
Data string
// Dependency type name. Very low cardinality. Examples are SQL, Azure table,
// and HTTP.
Type string
// Target site of a dependency call. Examples are server name, host address.
Target string
}
// Builds a new Remote Dependency telemetry item, with the specified name,
// dependency type, target site, and success status.
func NewRemoteDependencyTelemetry(name, dependencyType, target string, success bool) *RemoteDependencyTelemetry {
return &RemoteDependencyTelemetry{
Name: name,
Type: dependencyType,
Target: target,
Success: success,
BaseTelemetry: BaseTelemetry{
Timestamp: currentClock.Now(),
Tags: make(contracts.ContextTags),
Properties: make(map[string]string),
},
BaseTelemetryMeasurements: BaseTelemetryMeasurements{
Measurements: make(map[string]float64),
},
}
}
// Sets the timestamp and duration of this telemetry item based on the provided
// start and end times.
func (telem *RemoteDependencyTelemetry) MarkTime(startTime, endTime time.Time) {
telem.Timestamp = startTime
telem.Duration = endTime.Sub(startTime)
}
func (telem *RemoteDependencyTelemetry) TelemetryData() TelemetryData {
data := contracts.NewRemoteDependencyData()
data.Name = telem.Name
data.Id = telem.Id
data.ResultCode = telem.ResultCode
data.Duration = formatDuration(telem.Duration)
data.Success = telem.Success
data.Data = telem.Data
data.Target = telem.Target
data.Properties = telem.Properties
data.Measurements = telem.Measurements
data.Type = telem.Type
return data
}
// Avaibility telemetry items represent the result of executing an availability
// test.
type AvailabilityTelemetry struct {
BaseTelemetry
BaseTelemetryMeasurements
// Identifier of a test run. Used to correlate steps of test run and
// telemetry generated by the service.
Id string
// Name of the test that this result represents.
Name string
// Duration of the test run.
Duration time.Duration
// Success flag.
Success bool
// Name of the location where the test was run.
RunLocation string
// Diagnostic message for the result.
Message string
}
// Creates a new availability telemetry item with the specified test name,
// duration and success code.
func NewAvailabilityTelemetry(name string, duration time.Duration, success bool) *AvailabilityTelemetry {
return &AvailabilityTelemetry{
Name: name,
Duration: duration,
Success: success,
BaseTelemetry: BaseTelemetry{
Timestamp: currentClock.Now(),
Tags: make(contracts.ContextTags),
Properties: make(map[string]string),
},
BaseTelemetryMeasurements: BaseTelemetryMeasurements{
Measurements: make(map[string]float64),
},
}
}
// Sets the timestamp and duration of this telemetry item based on the provided
// start and end times.
func (telem *AvailabilityTelemetry) MarkTime(startTime, endTime time.Time) {
telem.Timestamp = startTime
telem.Duration = endTime.Sub(startTime)
}
func (telem *AvailabilityTelemetry) TelemetryData() TelemetryData {
data := contracts.NewAvailabilityData()
data.Name = telem.Name
data.Duration = formatDuration(telem.Duration)
data.Success = telem.Success
data.RunLocation = telem.RunLocation
data.Message = telem.Message
data.Properties = telem.Properties
data.Id = telem.Id
data.Measurements = telem.Measurements
return data
}
// Page view telemetry items represent generic actions on a page like a button
// click.
type PageViewTelemetry struct {
BaseTelemetry
BaseTelemetryMeasurements
// Request URL with all query string parameters
Url string
// Request duration.
Duration time.Duration
// Event name.
Name string
}
// Creates a new page view telemetry item with the specified name and url.
func NewPageViewTelemetry(name, url string) *PageViewTelemetry {
return &PageViewTelemetry{
Name: name,
Url: url,
BaseTelemetry: BaseTelemetry{
Timestamp: currentClock.Now(),
Tags: make(contracts.ContextTags),
Properties: make(map[string]string),
},
BaseTelemetryMeasurements: BaseTelemetryMeasurements{
Measurements: make(map[string]float64),
},
}
}
// Sets the timestamp and duration of this telemetry item based on the provided
// start and end times.
func (telem *PageViewTelemetry) MarkTime(startTime, endTime time.Time) {
telem.Timestamp = startTime
telem.Duration = endTime.Sub(startTime)
}
func (telem *PageViewTelemetry) TelemetryData() TelemetryData {
data := contracts.NewPageViewData()
data.Url = telem.Url
data.Duration = formatDuration(telem.Duration)
data.Name = telem.Name
data.Properties = telem.Properties
data.Measurements = telem.Measurements
return data
}
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)
}

50
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/telemetrychannel.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,50 @@
package appinsights
import (
"github.com/microsoft/ApplicationInsights-Go/appinsights/contracts"
"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(*contracts.Envelope)
// 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{}
}

104
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/telemetrycontext.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,104 @@
package appinsights
import (
"strings"
"github.com/microsoft/ApplicationInsights-Go/appinsights/contracts"
)
// Encapsulates contextual data common to all telemetry submitted through a
// TelemetryClient instance such as including instrumentation key, tags, and
// common properties.
type TelemetryContext struct {
// Instrumentation key
iKey string
// Stripped-down instrumentation key used in envelope name
nameIKey string
// Collection of tag data to attach to the telemetry item.
Tags contracts.ContextTags
// Common properties to add to each telemetry item. This only has
// an effect from the TelemetryClient's context instance. This will
// be nil on telemetry items.
CommonProperties map[string]string
}
// Creates a new, empty TelemetryContext
func NewTelemetryContext(ikey string) *TelemetryContext {
return &TelemetryContext{
iKey: ikey,
nameIKey: strings.Replace(ikey, "-", "", -1),
Tags: make(contracts.ContextTags),
CommonProperties: make(map[string]string),
}
}
// Gets the instrumentation key associated with this TelemetryContext. This
// will be an empty string on telemetry items' context instances.
func (context *TelemetryContext) InstrumentationKey() string {
return context.iKey
}
// Wraps a telemetry item in an envelope with the information found in this
// context.
func (context *TelemetryContext) envelop(item Telemetry) *contracts.Envelope {
// Apply common properties
if props := item.GetProperties(); props != nil && context.CommonProperties != nil {
for k, v := range context.CommonProperties {
if _, ok := props[k]; !ok {
props[k] = v
}
}
}
tdata := item.TelemetryData()
data := contracts.NewData()
data.BaseType = tdata.BaseType()
data.BaseData = tdata
envelope := contracts.NewEnvelope()
envelope.Name = tdata.EnvelopeName(context.nameIKey)
envelope.Data = data
envelope.IKey = context.iKey
timestamp := item.Time()
if timestamp.IsZero() {
timestamp = currentClock.Now()
}
envelope.Time = timestamp.UTC().Format("2006-01-02T15:04:05.999999Z")
if contextTags := item.ContextTags(); contextTags != nil {
envelope.Tags = contextTags
// Copy in default tag values.
for tagkey, tagval := range context.Tags {
if _, ok := contextTags[tagkey]; !ok {
contextTags[tagkey] = tagval
}
}
} else {
// Create new tags object
envelope.Tags = make(map[string]string)
for k, v := range context.Tags {
envelope.Tags[k] = v
}
}
// Create operation ID if it does not exist
if _, ok := envelope.Tags[contracts.OperationId]; !ok {
envelope.Tags[contracts.OperationId] = newUUID().String()
}
// Sanitize.
for _, warn := range tdata.Sanitize() {
diagnosticsWriter.Printf("Telemetry data warning: %s", warn)
}
for _, warn := range contracts.SanitizeTags(envelope.Tags) {
diagnosticsWriter.Printf("Telemetry tag warning: %s", warn)
}
return envelope
}

144
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/throttle.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,144 @@
package appinsights
import (
"time"
)
type throttleManager struct {
msgs chan *throttleMessage
}
type throttleMessage struct {
query bool
wait bool
throttle bool
stop bool
timestamp time.Time
result chan bool
}
func newThrottleManager() *throttleManager {
result := &throttleManager{
msgs: make(chan *throttleMessage),
}
go result.run()
return result
}
func (throttle *throttleManager) RetryAfter(t time.Time) {
throttle.msgs <- &throttleMessage{
throttle: true,
timestamp: t,
}
}
func (throttle *throttleManager) IsThrottled() bool {
ch := make(chan bool)
throttle.msgs <- &throttleMessage{
query: true,
result: ch,
}
result := <-ch
close(ch)
return result
}
func (throttle *throttleManager) NotifyWhenReady() chan bool {
result := make(chan bool, 1)
throttle.msgs <- &throttleMessage{
wait: true,
result: result,
}
return result
}
func (throttle *throttleManager) Stop() {
result := make(chan bool)
throttle.msgs <- &throttleMessage{
stop: true,
result: result,
}
<-result
close(result)
}
func (throttle *throttleManager) run() {
for {
throttledUntil, ok := throttle.waitForThrottle()
if !ok {
break
}
if !throttle.waitForReady(throttledUntil) {
break
}
}
close(throttle.msgs)
}
func (throttle *throttleManager) waitForThrottle() (time.Time, bool) {
for {
msg := <-throttle.msgs
if msg.query {
msg.result <- false
} else if msg.wait {
msg.result <- true
} else if msg.stop {
return time.Time{}, false
} else if msg.throttle {
return msg.timestamp, true
}
}
}
func (throttle *throttleManager) waitForReady(throttledUntil time.Time) bool {
duration := throttledUntil.Sub(currentClock.Now())
if duration <= 0 {
return true
}
var notify []chan bool
// --- Throttled and waiting ---
t := currentClock.NewTimer(duration)
for {
select {
case <-t.C():
for _, n := range notify {
n <- true
}
return true
case msg := <-throttle.msgs:
if msg.query {
msg.result <- true
} else if msg.wait {
notify = append(notify, msg.result)
} else if msg.stop {
for _, n := range notify {
n <- false
}
msg.result <- true
return false
} else if msg.throttle {
if msg.timestamp.After(throttledUntil) {
throttledUntil = msg.timestamp
if !t.Stop() {
<-t.C()
}
t.Reset(throttledUntil.Sub(currentClock.Now()))
}
}
}
}
}

237
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/transmitter.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,237 @@
package appinsights
import (
"bytes"
"compress/gzip"
"encoding/json"
"io/ioutil"
"net/http"
"sort"
"time"
)
type transmitter interface {
Transmit(payload []byte, items telemetryBufferItems) (*transmissionResult, error)
}
type httpTransmitter struct {
endpoint string
}
type transmissionResult struct {
statusCode int
retryAfter *time.Time
response *backendResponse
}
// Structures returned by data collector
type backendResponse struct {
ItemsReceived int `json:"itemsReceived"`
ItemsAccepted int `json:"itemsAccepted"`
Errors itemTransmissionResults `json:"errors"`
}
// This needs to be its own type because it implements sort.Interface
type itemTransmissionResults []*itemTransmissionResult
type itemTransmissionResult struct {
Index int `json:"index"`
StatusCode int `json:"statusCode"`
Message string `json:"message"`
}
const (
successResponse = 200
partialSuccessResponse = 206
requestTimeoutResponse = 408
tooManyRequestsResponse = 429
tooManyRequestsOverExtendedTimeResponse = 439
errorResponse = 500
serviceUnavailableResponse = 503
)
func newTransmitter(endpointAddress string) transmitter {
return &httpTransmitter{endpointAddress}
}
func (transmitter *httpTransmitter) Transmit(payload []byte, items telemetryBufferItems) (*transmissionResult, error) {
diagnosticsWriter.Printf("--------- Transmitting %d items ---------", len(items))
startTime := time.Now()
// Compress the payload
var postBody bytes.Buffer
gzipWriter := gzip.NewWriter(&postBody)
if _, err := gzipWriter.Write(payload); err != nil {
diagnosticsWriter.Printf("Failed to compress the payload: %s", err.Error())
gzipWriter.Close()
return nil, err
}
gzipWriter.Close()
req, err := http.NewRequest("POST", transmitter.endpoint, &postBody)
if err != nil {
return nil, err
}
req.Header.Set("Content-Encoding", "gzip")
req.Header.Set("Content-Type", "application/x-json-stream")
req.Header.Set("Accept-Encoding", "gzip, deflate")
client := http.DefaultClient
resp, err := client.Do(req)
if err != nil {
diagnosticsWriter.Printf("Failed to transmit telemetry: %s", err.Error())
return nil, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
diagnosticsWriter.Printf("Failed to read response from server: %s", err.Error())
return nil, err
}
duration := time.Since(startTime)
result := &transmissionResult{statusCode: resp.StatusCode}
// Grab Retry-After header
if retryAfterValue, ok := resp.Header[http.CanonicalHeaderKey("Retry-After")]; ok && len(retryAfterValue) == 1 {
if retryAfterTime, err := time.Parse(time.RFC1123, retryAfterValue[0]); err == nil {
result.retryAfter = &retryAfterTime
}
}
// Parse body, if possible
response := &backendResponse{}
if err := json.Unmarshal(body, &response); err == nil {
result.response = response
}
// Write diagnostics
if diagnosticsWriter.hasListeners() {
diagnosticsWriter.Printf("Telemetry transmitted in %s", duration)
diagnosticsWriter.Printf("Response: %d", result.statusCode)
if result.response != nil {
diagnosticsWriter.Printf("Items accepted/received: %d/%d", result.response.ItemsAccepted, result.response.ItemsReceived)
if len(result.response.Errors) > 0 {
diagnosticsWriter.Printf("Errors:")
for _, err := range result.response.Errors {
if err.Index < len(items) {
diagnosticsWriter.Printf("#%d - %d %s", err.Index, err.StatusCode, err.Message)
diagnosticsWriter.Printf("Telemetry item:\n\t%s", 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
}

71
vendor/github.com/Microsoft/ApplicationInsights-Go/appinsights/uuid.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,71 @@
package appinsights
import (
crand "crypto/rand"
"encoding/binary"
"io"
"math/rand"
"sync"
"time"
"github.com/satori/go.uuid"
)
// uuidGenerator is a wrapper for satori/go.uuid, used for a few reasons:
// - Avoids build failures due to version differences when a project imports us but
// does not respect our vendoring. (satori/go.uuid#77, #71, #66, ...)
// - Avoids error output when creaing new UUID's: if the crypto reader fails,
// this will fallback on the standard library PRNG, since this is never used
// for a sensitive application.
// - Uses io.ReadFull to guarantee fully-populated UUID's (satori/go.uuid#73)
type uuidGenerator struct {
sync.Mutex
fallbackRand *rand.Rand
reader io.Reader
}
var uuidgen *uuidGenerator = newUuidGenerator(crand.Reader)
// newUuidGenerator creates a new uuiGenerator with the specified crypto random reader.
func newUuidGenerator(reader io.Reader) *uuidGenerator {
// Setup seed for fallback random generator
var seed int64
b := make([]byte, 8)
if _, err := io.ReadFull(reader, b); err == nil {
seed = int64(binary.BigEndian.Uint64(b))
} else {
// Otherwise just use the timestamp
seed = time.Now().UTC().UnixNano()
}
return &uuidGenerator{
reader: reader,
fallbackRand: rand.New(rand.NewSource(seed)),
}
}
// newUUID generates a new V4 UUID
func (gen *uuidGenerator) newUUID() uuid.UUID {
u := uuid.UUID{}
if _, err := io.ReadFull(gen.reader, u[:]); err != nil {
gen.fallback(&u)
}
u.SetVersion(uuid.V4)
u.SetVersion(uuid.VariantRFC4122)
return u
}
// fallback populates the specified UUID with the standard library's PRNG
func (gen *uuidGenerator) fallback(u *uuid.UUID) {
gen.Lock()
defer gen.Unlock()
// This does not fail as per documentation
gen.fallbackRand.Read(u[:])
}
// newUUID generates a new V4 UUID
func newUUID() uuid.UUID {
return uuidgen.newUUID()
}

23
vendor/github.com/satori/go.uuid/.travis.yml сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,23 @@
language: go
sudo: false
go:
- 1.2
- 1.3
- 1.4
- 1.5
- 1.6
- 1.7
- 1.8
- 1.9
- tip
matrix:
allow_failures:
- go: tip
fast_finish: true
before_install:
- go get github.com/mattn/goveralls
- go get golang.org/x/tools/cmd/cover
script:
- $HOME/gopath/bin/goveralls -service=travis-ci
notifications:
email: false

20
vendor/github.com/satori/go.uuid/LICENSE сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,20 @@
Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
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.

65
vendor/github.com/satori/go.uuid/README.md сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,65 @@
# UUID package for Go language
[![Build Status](https://travis-ci.org/satori/go.uuid.png?branch=master)](https://travis-ci.org/satori/go.uuid)
[![Coverage Status](https://coveralls.io/repos/github/satori/go.uuid/badge.svg?branch=master)](https://coveralls.io/github/satori/go.uuid)
[![GoDoc](http://godoc.org/github.com/satori/go.uuid?status.png)](http://godoc.org/github.com/satori/go.uuid)
This package provides pure Go implementation of Universally Unique Identifier (UUID). Supported both creation and parsing of UUIDs.
With 100% test coverage and benchmarks out of box.
Supported versions:
* Version 1, based on timestamp and MAC address (RFC 4122)
* Version 2, based on timestamp, MAC address and POSIX UID/GID (DCE 1.1)
* Version 3, based on MD5 hashing (RFC 4122)
* Version 4, based on random numbers (RFC 4122)
* Version 5, based on SHA-1 hashing (RFC 4122)
## Installation
Use the `go` command:
$ go get github.com/satori/go.uuid
## Requirements
UUID package requires Go >= 1.2.
## Example
```go
package main
import (
"fmt"
"github.com/satori/go.uuid"
)
func main() {
// Creating UUID Version 4
u1 := uuid.NewV4()
fmt.Printf("UUIDv4: %s\n", u1)
// Parsing UUID from string input
u2, err := uuid.FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
if err != nil {
fmt.Printf("Something gone wrong: %s", err)
}
fmt.Printf("Successfully parsed: %s", u2)
}
```
## Documentation
[Documentation](http://godoc.org/github.com/satori/go.uuid) is hosted at GoDoc project.
## Links
* [RFC 4122](http://tools.ietf.org/html/rfc4122)
* [DCE 1.1: Authentication and Security Services](http://pubs.opengroup.org/onlinepubs/9696989899/chap5.htm#tagcjh_08_02_01_01)
## Copyright
Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>.
UUID package released under MIT License.
See [LICENSE](https://github.com/satori/go.uuid/blob/master/LICENSE) for details.

206
vendor/github.com/satori/go.uuid/codec.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,206 @@
// Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
//
// 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.
package uuid
import (
"bytes"
"encoding/hex"
"fmt"
)
// FromBytes returns UUID converted from raw byte slice input.
// It will return error if the slice isn't 16 bytes long.
func FromBytes(input []byte) (u UUID, err error) {
err = u.UnmarshalBinary(input)
return
}
// FromBytesOrNil returns UUID converted from raw byte slice input.
// Same behavior as FromBytes, but returns a Nil UUID on error.
func FromBytesOrNil(input []byte) UUID {
uuid, err := FromBytes(input)
if err != nil {
return Nil
}
return uuid
}
// FromString returns UUID parsed from string input.
// Input is expected in a form accepted by UnmarshalText.
func FromString(input string) (u UUID, err error) {
err = u.UnmarshalText([]byte(input))
return
}
// FromStringOrNil returns UUID parsed from string input.
// Same behavior as FromString, but returns a Nil UUID on error.
func FromStringOrNil(input string) UUID {
uuid, err := FromString(input)
if err != nil {
return Nil
}
return uuid
}
// MarshalText implements the encoding.TextMarshaler interface.
// The encoding is the same as returned by String.
func (u UUID) MarshalText() (text []byte, err error) {
text = []byte(u.String())
return
}
// UnmarshalText implements the encoding.TextUnmarshaler interface.
// Following formats are supported:
// "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
// "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}",
// "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8"
// "6ba7b8109dad11d180b400c04fd430c8"
// ABNF for supported UUID text representation follows:
// uuid := canonical | hashlike | braced | urn
// plain := canonical | hashlike
// canonical := 4hexoct '-' 2hexoct '-' 2hexoct '-' 6hexoct
// hashlike := 12hexoct
// braced := '{' plain '}'
// urn := URN ':' UUID-NID ':' plain
// URN := 'urn'
// UUID-NID := 'uuid'
// 12hexoct := 6hexoct 6hexoct
// 6hexoct := 4hexoct 2hexoct
// 4hexoct := 2hexoct 2hexoct
// 2hexoct := hexoct hexoct
// hexoct := hexdig hexdig
// hexdig := '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' |
// 'a' | 'b' | 'c' | 'd' | 'e' | 'f' |
// 'A' | 'B' | 'C' | 'D' | 'E' | 'F'
func (u *UUID) UnmarshalText(text []byte) (err error) {
switch len(text) {
case 32:
return u.decodeHashLike(text)
case 36:
return u.decodeCanonical(text)
case 38:
return u.decodeBraced(text)
case 41:
fallthrough
case 45:
return u.decodeURN(text)
default:
return fmt.Errorf("uuid: incorrect UUID length: %s", text)
}
}
// decodeCanonical decodes UUID string in format
// "6ba7b810-9dad-11d1-80b4-00c04fd430c8".
func (u *UUID) decodeCanonical(t []byte) (err error) {
if t[8] != '-' || t[13] != '-' || t[18] != '-' || t[23] != '-' {
return fmt.Errorf("uuid: incorrect UUID format %s", t)
}
src := t[:]
dst := u[:]
for i, byteGroup := range byteGroups {
if i > 0 {
src = src[1:] // skip dash
}
_, err = hex.Decode(dst[:byteGroup/2], src[:byteGroup])
if err != nil {
return
}
src = src[byteGroup:]
dst = dst[byteGroup/2:]
}
return
}
// decodeHashLike decodes UUID string in format
// "6ba7b8109dad11d180b400c04fd430c8".
func (u *UUID) decodeHashLike(t []byte) (err error) {
src := t[:]
dst := u[:]
if _, err = hex.Decode(dst, src); err != nil {
return err
}
return
}
// decodeBraced decodes UUID string in format
// "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}" or in format
// "{6ba7b8109dad11d180b400c04fd430c8}".
func (u *UUID) decodeBraced(t []byte) (err error) {
l := len(t)
if t[0] != '{' || t[l-1] != '}' {
return fmt.Errorf("uuid: incorrect UUID format %s", t)
}
return u.decodePlain(t[1 : l-1])
}
// decodeURN decodes UUID string in format
// "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8" or in format
// "urn:uuid:6ba7b8109dad11d180b400c04fd430c8".
func (u *UUID) decodeURN(t []byte) (err error) {
total := len(t)
urn_uuid_prefix := t[:9]
if !bytes.Equal(urn_uuid_prefix, urnPrefix) {
return fmt.Errorf("uuid: incorrect UUID format: %s", t)
}
return u.decodePlain(t[9:total])
}
// decodePlain decodes UUID string in canonical format
// "6ba7b810-9dad-11d1-80b4-00c04fd430c8" or in hash-like format
// "6ba7b8109dad11d180b400c04fd430c8".
func (u *UUID) decodePlain(t []byte) (err error) {
switch len(t) {
case 32:
return u.decodeHashLike(t)
case 36:
return u.decodeCanonical(t)
default:
return fmt.Errorf("uuid: incorrrect UUID length: %s", t)
}
}
// MarshalBinary implements the encoding.BinaryMarshaler interface.
func (u UUID) MarshalBinary() (data []byte, err error) {
data = u.Bytes()
return
}
// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
// It will return error if the slice isn't 16 bytes long.
func (u *UUID) UnmarshalBinary(data []byte) (err error) {
if len(data) != Size {
err = fmt.Errorf("uuid: UUID must be exactly 16 bytes long, got %d bytes", len(data))
return
}
copy(u[:], data)
return
}

239
vendor/github.com/satori/go.uuid/generator.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,239 @@
// Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
//
// 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.
package uuid
import (
"crypto/md5"
"crypto/rand"
"crypto/sha1"
"encoding/binary"
"hash"
"net"
"os"
"sync"
"time"
)
// Difference in 100-nanosecond intervals between
// UUID epoch (October 15, 1582) and Unix epoch (January 1, 1970).
const epochStart = 122192928000000000
var (
global = newDefaultGenerator()
epochFunc = unixTimeFunc
posixUID = uint32(os.Getuid())
posixGID = uint32(os.Getgid())
)
// NewV1 returns UUID based on current timestamp and MAC address.
func NewV1() UUID {
return global.NewV1()
}
// NewV2 returns DCE Security UUID based on POSIX UID/GID.
func NewV2(domain byte) UUID {
return global.NewV2(domain)
}
// NewV3 returns UUID based on MD5 hash of namespace UUID and name.
func NewV3(ns UUID, name string) UUID {
return global.NewV3(ns, name)
}
// NewV4 returns random generated UUID.
func NewV4() UUID {
return global.NewV4()
}
// NewV5 returns UUID based on SHA-1 hash of namespace UUID and name.
func NewV5(ns UUID, name string) UUID {
return global.NewV5(ns, name)
}
// Generator provides interface for generating UUIDs.
type Generator interface {
NewV1() UUID
NewV2(domain byte) UUID
NewV3(ns UUID, name string) UUID
NewV4() UUID
NewV5(ns UUID, name string) UUID
}
// Default generator implementation.
type generator struct {
storageOnce sync.Once
storageMutex sync.Mutex
lastTime uint64
clockSequence uint16
hardwareAddr [6]byte
}
func newDefaultGenerator() Generator {
return &generator{}
}
// NewV1 returns UUID based on current timestamp and MAC address.
func (g *generator) NewV1() UUID {
u := UUID{}
timeNow, clockSeq, hardwareAddr := g.getStorage()
binary.BigEndian.PutUint32(u[0:], uint32(timeNow))
binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32))
binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48))
binary.BigEndian.PutUint16(u[8:], clockSeq)
copy(u[10:], hardwareAddr)
u.SetVersion(V1)
u.SetVariant(VariantRFC4122)
return u
}
// NewV2 returns DCE Security UUID based on POSIX UID/GID.
func (g *generator) NewV2(domain byte) UUID {
u := UUID{}
timeNow, clockSeq, hardwareAddr := g.getStorage()
switch domain {
case DomainPerson:
binary.BigEndian.PutUint32(u[0:], posixUID)
case DomainGroup:
binary.BigEndian.PutUint32(u[0:], posixGID)
}
binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32))
binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48))
binary.BigEndian.PutUint16(u[8:], clockSeq)
u[9] = domain
copy(u[10:], hardwareAddr)
u.SetVersion(V2)
u.SetVariant(VariantRFC4122)
return u
}
// NewV3 returns UUID based on MD5 hash of namespace UUID and name.
func (g *generator) NewV3(ns UUID, name string) UUID {
u := newFromHash(md5.New(), ns, name)
u.SetVersion(V3)
u.SetVariant(VariantRFC4122)
return u
}
// NewV4 returns random generated UUID.
func (g *generator) NewV4() UUID {
u := UUID{}
g.safeRandom(u[:])
u.SetVersion(V4)
u.SetVariant(VariantRFC4122)
return u
}
// NewV5 returns UUID based on SHA-1 hash of namespace UUID and name.
func (g *generator) NewV5(ns UUID, name string) UUID {
u := newFromHash(sha1.New(), ns, name)
u.SetVersion(V5)
u.SetVariant(VariantRFC4122)
return u
}
func (g *generator) initStorage() {
g.initClockSequence()
g.initHardwareAddr()
}
func (g *generator) initClockSequence() {
buf := make([]byte, 2)
g.safeRandom(buf)
g.clockSequence = binary.BigEndian.Uint16(buf)
}
func (g *generator) initHardwareAddr() {
interfaces, err := net.Interfaces()
if err == nil {
for _, iface := range interfaces {
if len(iface.HardwareAddr) >= 6 {
copy(g.hardwareAddr[:], iface.HardwareAddr)
return
}
}
}
// Initialize hardwareAddr randomly in case
// of real network interfaces absence
g.safeRandom(g.hardwareAddr[:])
// Set multicast bit as recommended in RFC 4122
g.hardwareAddr[0] |= 0x01
}
func (g *generator) safeRandom(dest []byte) {
if _, err := rand.Read(dest); err != nil {
panic(err)
}
}
// Returns UUID v1/v2 storage state.
// Returns epoch timestamp, clock sequence, and hardware address.
func (g *generator) getStorage() (uint64, uint16, []byte) {
g.storageOnce.Do(g.initStorage)
g.storageMutex.Lock()
defer g.storageMutex.Unlock()
timeNow := epochFunc()
// Clock changed backwards since last UUID generation.
// Should increase clock sequence.
if timeNow <= g.lastTime {
g.clockSequence++
}
g.lastTime = timeNow
return timeNow, g.clockSequence, g.hardwareAddr[:]
}
// Returns difference in 100-nanosecond intervals between
// UUID epoch (October 15, 1582) and current time.
// This is default epoch calculation function.
func unixTimeFunc() uint64 {
return epochStart + uint64(time.Now().UnixNano()/100)
}
// Returns UUID based on hashing of namespace UUID and name.
func newFromHash(h hash.Hash, ns UUID, name string) UUID {
u := UUID{}
h.Write(ns[:])
h.Write([]byte(name))
copy(u[:], h.Sum(nil))
return u
}

78
vendor/github.com/satori/go.uuid/sql.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,78 @@
// Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
//
// 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.
package uuid
import (
"database/sql/driver"
"fmt"
)
// Value implements the driver.Valuer interface.
func (u UUID) Value() (driver.Value, error) {
return u.String(), nil
}
// Scan implements the sql.Scanner interface.
// A 16-byte slice is handled by UnmarshalBinary, while
// a longer byte slice or a string is handled by UnmarshalText.
func (u *UUID) Scan(src interface{}) error {
switch src := src.(type) {
case []byte:
if len(src) == Size {
return u.UnmarshalBinary(src)
}
return u.UnmarshalText(src)
case string:
return u.UnmarshalText([]byte(src))
}
return fmt.Errorf("uuid: cannot convert %T to UUID", src)
}
// NullUUID can be used with the standard sql package to represent a
// UUID value that can be NULL in the database
type NullUUID struct {
UUID UUID
Valid bool
}
// Value implements the driver.Valuer interface.
func (u NullUUID) Value() (driver.Value, error) {
if !u.Valid {
return nil, nil
}
// Delegate to UUID Value function
return u.UUID.Value()
}
// Scan implements the sql.Scanner interface.
func (u *NullUUID) Scan(src interface{}) error {
if src == nil {
u.UUID, u.Valid = Nil, false
return nil
}
// Delegate to UUID Scan function
u.Valid = true
return u.UUID.Scan(src)
}

161
vendor/github.com/satori/go.uuid/uuid.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,161 @@
// Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
//
// 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.
// Package uuid provides implementation of Universally Unique Identifier (UUID).
// Supported versions are 1, 3, 4 and 5 (as specified in RFC 4122) and
// version 2 (as specified in DCE 1.1).
package uuid
import (
"bytes"
"encoding/hex"
)
// Size of a UUID in bytes.
const Size = 16
// UUID representation compliant with specification
// described in RFC 4122.
type UUID [Size]byte
// UUID versions
const (
_ byte = iota
V1
V2
V3
V4
V5
)
// UUID layout variants.
const (
VariantNCS byte = iota
VariantRFC4122
VariantMicrosoft
VariantFuture
)
// UUID DCE domains.
const (
DomainPerson = iota
DomainGroup
DomainOrg
)
// String parse helpers.
var (
urnPrefix = []byte("urn:uuid:")
byteGroups = []int{8, 4, 4, 4, 12}
)
// Nil is special form of UUID that is specified to have all
// 128 bits set to zero.
var Nil = UUID{}
// Predefined namespace UUIDs.
var (
NamespaceDNS = Must(FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8"))
NamespaceURL = Must(FromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8"))
NamespaceOID = Must(FromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8"))
NamespaceX500 = Must(FromString("6ba7b814-9dad-11d1-80b4-00c04fd430c8"))
)
// Equal returns true if u1 and u2 equals, otherwise returns false.
func Equal(u1 UUID, u2 UUID) bool {
return bytes.Equal(u1[:], u2[:])
}
// Version returns algorithm version used to generate UUID.
func (u UUID) Version() byte {
return u[6] >> 4
}
// Variant returns UUID layout variant.
func (u UUID) Variant() byte {
switch {
case (u[8] >> 7) == 0x00:
return VariantNCS
case (u[8] >> 6) == 0x02:
return VariantRFC4122
case (u[8] >> 5) == 0x06:
return VariantMicrosoft
case (u[8] >> 5) == 0x07:
fallthrough
default:
return VariantFuture
}
}
// Bytes returns bytes slice representation of UUID.
func (u UUID) Bytes() []byte {
return u[:]
}
// Returns canonical string representation of UUID:
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
func (u UUID) String() string {
buf := make([]byte, 36)
hex.Encode(buf[0:8], u[0:4])
buf[8] = '-'
hex.Encode(buf[9:13], u[4:6])
buf[13] = '-'
hex.Encode(buf[14:18], u[6:8])
buf[18] = '-'
hex.Encode(buf[19:23], u[8:10])
buf[23] = '-'
hex.Encode(buf[24:], u[10:])
return string(buf)
}
// SetVersion sets version bits.
func (u *UUID) SetVersion(v byte) {
u[6] = (u[6] & 0x0f) | (v << 4)
}
// SetVariant sets variant bits.
func (u *UUID) SetVariant(v byte) {
switch v {
case VariantNCS:
u[8] = (u[8]&(0xff>>1) | (0x00 << 7))
case VariantRFC4122:
u[8] = (u[8]&(0xff>>2) | (0x02 << 6))
case VariantMicrosoft:
u[8] = (u[8]&(0xff>>3) | (0x06 << 5))
case VariantFuture:
fallthrough
default:
u[8] = (u[8]&(0xff>>3) | (0x07 << 5))
}
}
// Must is a helper that wraps a call to a function returning (UUID, error)
// and panics if the error is non-nil. It is intended for use in variable
// initializations such as
// var packageUUID = uuid.Must(uuid.FromString("123e4567-e89b-12d3-a456-426655440000"));
func Must(u UUID, err error) UUID {
if err != nil {
panic(err)
}
return u
}