Compare commits
10 Commits
ff7a20da80
...
fd2463e981
| Author | SHA1 | Date |
|---|---|---|
|
|
fd2463e981 | |
|
|
c31d402b72 | |
|
|
f5404aee67 | |
|
|
187a1931e5 | |
|
|
9465e7182a | |
|
|
fd1964bfd7 | |
|
|
5a29809eea | |
|
|
ed56d640f2 | |
|
|
d252bc83d3 | |
|
|
7cd6c00647 |
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
#  Telegraf
|
||||
|
||||
[](https://godoc.org/github.com/influxdata/telegraf)
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ the general steps to set it up.
|
|||
quotes:
|
||||
|
||||
```shell
|
||||
> "C:Program Files\Telegraf\telegraf.exe" service install
|
||||
> "C:\Program Files\Telegraf\telegraf.exe" service install
|
||||
```
|
||||
|
||||
5. Edit the configuration file to meet your needs
|
||||
|
|
|
|||
12
go.mod
12
go.mod
|
|
@ -48,7 +48,7 @@ require (
|
|||
github.com/aristanetworks/goarista v0.0.0-20190325233358-a123909ec740
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
|
||||
github.com/awnumar/memguard v0.22.5
|
||||
github.com/aws/aws-msk-iam-sasl-signer-go v1.0.1
|
||||
github.com/aws/aws-msk-iam-sasl-signer-go v1.0.3
|
||||
github.com/aws/aws-sdk-go-v2 v1.36.3
|
||||
github.com/aws/aws-sdk-go-v2/config v1.29.14
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.67
|
||||
|
|
@ -57,7 +57,7 @@ require (
|
|||
github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.48.0
|
||||
github.com/aws/aws-sdk-go-v2/service/dynamodb v1.43.1
|
||||
github.com/aws/aws-sdk-go-v2/service/ec2 v1.215.0
|
||||
github.com/aws/aws-sdk-go-v2/service/kinesis v1.33.3
|
||||
github.com/aws/aws-sdk-go-v2/service/kinesis v1.35.0
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.33.19
|
||||
github.com/aws/aws-sdk-go-v2/service/timestreamwrite v1.30.2
|
||||
github.com/aws/smithy-go v1.22.3
|
||||
|
|
@ -114,7 +114,7 @@ require (
|
|||
github.com/gosnmp/gosnmp v1.40.0
|
||||
github.com/grid-x/modbus v0.0.0-20240503115206-582f2ab60a18
|
||||
github.com/gwos/tcg/sdk v0.0.0-20240830123415-f8a34bba6358
|
||||
github.com/hashicorp/consul/api v1.32.0
|
||||
github.com/hashicorp/consul/api v1.32.1
|
||||
github.com/hashicorp/go-uuid v1.0.3
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7
|
||||
github.com/influxdata/influxdb-observability/common v0.5.12
|
||||
|
|
@ -151,7 +151,7 @@ require (
|
|||
github.com/moby/ipvs v1.1.0
|
||||
github.com/multiplay/go-ts3 v1.2.0
|
||||
github.com/nats-io/nats-server/v2 v2.11.3
|
||||
github.com/nats-io/nats.go v1.41.2
|
||||
github.com/nats-io/nats.go v1.42.0
|
||||
github.com/netsampler/goflow2/v2 v2.2.2
|
||||
github.com/newrelic/newrelic-telemetry-sdk-go v0.8.1
|
||||
github.com/nsqio/go-nsq v1.1.0
|
||||
|
|
@ -176,7 +176,7 @@ require (
|
|||
github.com/prometheus/procfs v0.16.1
|
||||
github.com/prometheus/prometheus v0.54.1
|
||||
github.com/rabbitmq/amqp091-go v1.10.0
|
||||
github.com/rclone/rclone v1.69.1
|
||||
github.com/rclone/rclone v1.69.2
|
||||
github.com/redis/go-redis/v9 v9.8.0
|
||||
github.com/riemann/riemann-go-client v0.5.1-0.20211206220514-f58f10cdce16
|
||||
github.com/robbiet480/go.nut v0.0.0-20220219091450-bd8f121e1fa1
|
||||
|
|
@ -223,7 +223,7 @@ require (
|
|||
go.step.sm/crypto v0.63.0
|
||||
golang.org/x/crypto v0.38.0
|
||||
golang.org/x/mod v0.24.0
|
||||
golang.org/x/net v0.39.0
|
||||
golang.org/x/net v0.40.0
|
||||
golang.org/x/oauth2 v0.30.0
|
||||
golang.org/x/sync v0.14.0
|
||||
golang.org/x/sys v0.33.0
|
||||
|
|
|
|||
24
go.sum
24
go.sum
|
|
@ -878,8 +878,8 @@ github.com/awnumar/memcall v0.3.0 h1:8b/3Sptrtgejj2kLgL6M5F2r4OzTf19CTllO+gIXUg8
|
|||
github.com/awnumar/memcall v0.3.0/go.mod h1:8xOx1YbfyuCg3Fy6TO8DK0kZUua3V42/goA5Ru47E8w=
|
||||
github.com/awnumar/memguard v0.22.5 h1:PH7sbUVERS5DdXh3+mLo8FDcl1eIeVjJVYMnyuYpvuI=
|
||||
github.com/awnumar/memguard v0.22.5/go.mod h1:+APmZGThMBWjnMlKiSM1X7MVpbIVewen2MTkqWkA/zE=
|
||||
github.com/aws/aws-msk-iam-sasl-signer-go v1.0.1 h1:nMp7diZObd4XEVUR0pEvn7/E13JIgManMX79Q6quV6E=
|
||||
github.com/aws/aws-msk-iam-sasl-signer-go v1.0.1/go.mod h1:MVYeeOhILFFemC/XlYTClvBjYZrg/EPd3ts885KrNTI=
|
||||
github.com/aws/aws-msk-iam-sasl-signer-go v1.0.3 h1:9vETuCJAV00CpMT8ONil8xvFuZrEgjTHWavXBd/DiPQ=
|
||||
github.com/aws/aws-msk-iam-sasl-signer-go v1.0.3/go.mod h1:MVYeeOhILFFemC/XlYTClvBjYZrg/EPd3ts885KrNTI=
|
||||
github.com/aws/aws-sdk-go v1.29.11/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTgahTma5Xg=
|
||||
github.com/aws/aws-sdk-go v1.44.263/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
|
||||
github.com/aws/aws-sdk-go-v2 v1.18.0/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw=
|
||||
|
|
@ -928,8 +928,8 @@ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 h1:dM9/92u2
|
|||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15/go.mod h1:SwFBy2vjtA0vZbjjaFtfN045boopadnoVPhu4Fv66vY=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.6 h1:BbGDtTi0T1DYlmjBiCr/le3wzhA37O8QTC5/Ab8+EXk=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.6/go.mod h1:hLMJt7Q8ePgViKupeymbqI0la+t9/iYFBjxQCFwuAwI=
|
||||
github.com/aws/aws-sdk-go-v2/service/kinesis v1.33.3 h1:brQCC27V/e3wGeJ0JFh5InpH28saxe73Xpf0GXojn8M=
|
||||
github.com/aws/aws-sdk-go-v2/service/kinesis v1.33.3/go.mod h1:dJngkoVMrq0K7QvRkdRZYM4NUp6cdWa2GBdpm8zoY8U=
|
||||
github.com/aws/aws-sdk-go-v2/service/kinesis v1.35.0 h1:Y8ONhfuFKHfx+gvgKbrsN8lOgNCHcnyHRLldRmhaI/M=
|
||||
github.com/aws/aws-sdk-go-v2/service/kinesis v1.35.0/go.mod h1:dJngkoVMrq0K7QvRkdRZYM4NUp6cdWa2GBdpm8zoY8U=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.71.0 h1:nyuzXooUNJexRT0Oy0UQY6AhOzxPxhtt4DcBIHyCnmw=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.71.0/go.mod h1:sT/iQz8JK3u/5gZkT+Hmr7GzVZehUMkRZpOaAwYXeGY=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.12.10/go.mod h1:ouy2P4z6sJN70fR3ka3wD3Ro3KezSxU6eKGQI2+2fjI=
|
||||
|
|
@ -1519,8 +1519,8 @@ github.com/gwos/tcg/sdk v0.0.0-20240830123415-f8a34bba6358/go.mod h1:h40FJV0HuUL
|
|||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8=
|
||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
|
||||
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
||||
github.com/hashicorp/consul/api v1.32.0 h1:5wp5u780Gri7c4OedGEPzmlUEzi0g2KyiPphSr6zjVg=
|
||||
github.com/hashicorp/consul/api v1.32.0/go.mod h1:Z8YgY0eVPukT/17ejW+l+C7zJmKwgPHtjU1q16v/Y40=
|
||||
github.com/hashicorp/consul/api v1.32.1 h1:0+osr/3t/aZNAdJX558crU3PEjVrG4x6715aZHRgceE=
|
||||
github.com/hashicorp/consul/api v1.32.1/go.mod h1:mXUWLnxftwTmDv4W3lzxYCPD199iNLLUyLfLGFJbtl4=
|
||||
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
github.com/hashicorp/consul/sdk v0.16.1 h1:V8TxTnImoPD5cj0U9Spl0TUxcytjcbbJeADFF07KdHg=
|
||||
github.com/hashicorp/consul/sdk v0.16.1/go.mod h1:fSXvwxB2hmh1FMZCNl6PwX0Q/1wdWtHJcZ7Ea5tns0s=
|
||||
|
|
@ -1964,8 +1964,8 @@ github.com/nats-io/jwt/v2 v2.7.4 h1:jXFuDDxs/GQjGDZGhNgH4tXzSUK6WQi2rsj4xmsNOtI=
|
|||
github.com/nats-io/jwt/v2 v2.7.4/go.mod h1:me11pOkwObtcBNR8AiMrUbtVOUGkqYjMQZ6jnSdVUIA=
|
||||
github.com/nats-io/nats-server/v2 v2.11.3 h1:AbGtXxuwjo0gBroLGGr/dE0vf24kTKdRnBq/3z/Fdoc=
|
||||
github.com/nats-io/nats-server/v2 v2.11.3/go.mod h1:6Z6Fd+JgckqzKig7DYwhgrE7bJ6fypPHnGPND+DqgMY=
|
||||
github.com/nats-io/nats.go v1.41.2 h1:5UkfLAtu/036s99AhFRlyNDI1Ieylb36qbGjJzHixos=
|
||||
github.com/nats-io/nats.go v1.41.2/go.mod h1:iRWIPokVIFbVijxuMQq4y9ttaBTMe0SFdlZfMDd+33g=
|
||||
github.com/nats-io/nats.go v1.42.0 h1:ynIMupIOvf/ZWH/b2qda6WGKGNSjwOUutTpWRvAmhaM=
|
||||
github.com/nats-io/nats.go v1.42.0/go.mod h1:iRWIPokVIFbVijxuMQq4y9ttaBTMe0SFdlZfMDd+33g=
|
||||
github.com/nats-io/nkeys v0.4.11 h1:q44qGV008kYd9W1b1nEBkNzvnWxtRSQ7A8BoqRrcfa0=
|
||||
github.com/nats-io/nkeys v0.4.11/go.mod h1:szDimtgmfOi9n25JpfIdGw12tZFYXqhGxjhVxsatHVE=
|
||||
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
||||
|
|
@ -2150,8 +2150,8 @@ github.com/putdotio/go-putio/putio v0.0.0-20200123120452-16d982cac2b8 h1:Y258uzX
|
|||
github.com/putdotio/go-putio/putio v0.0.0-20200123120452-16d982cac2b8/go.mod h1:bSJjRokAHHOhA+XFxplld8w2R/dXLH7Z3BZ532vhFwU=
|
||||
github.com/rabbitmq/amqp091-go v1.10.0 h1:STpn5XsHlHGcecLmMFCtg7mqq0RnD+zFr4uzukfVhBw=
|
||||
github.com/rabbitmq/amqp091-go v1.10.0/go.mod h1:Hy4jKW5kQART1u+JkDTF9YYOQUHXqMuhrgxOEeS7G4o=
|
||||
github.com/rclone/rclone v1.69.1 h1:pjkfJlZjUk2DGj7vofG9baD+LKADm7zvoHFGQM1tPIA=
|
||||
github.com/rclone/rclone v1.69.1/go.mod h1:VtzXeF46F7f6CtdCrxbZJdtsVVPBVYLGYyNG+KoTxIc=
|
||||
github.com/rclone/rclone v1.69.2 h1:6uhFI7tiOrR5fy7Q88s49EqXc222mmwvZd7G9ne4lOE=
|
||||
github.com/rclone/rclone v1.69.2/go.mod h1:fJPDOXUUPwN3KsbC3CGoVUuA5XU16IQvvMtrRqXYpvs=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/redis/go-redis/v9 v9.8.0 h1:q3nRvjrlge/6UD7eTu/DSg2uYiU2mCL0G/uzBWqhicI=
|
||||
|
|
@ -2720,8 +2720,8 @@ golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
|||
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
|
||||
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
|
||||
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
|
|
|
|||
|
|
@ -167,6 +167,11 @@ to use them.
|
|||
## A list of queries to explicitly ignore.
|
||||
exclude_query = ["SQLServerAvailabilityReplicaStates", "SQLServerDatabaseReplicaStates"]
|
||||
|
||||
## Force using the deprecated ADAL authentication method instead of the recommended
|
||||
## MSAL method. Setting this option is not recommended and only exists for backward
|
||||
## compatibility.
|
||||
# use_deprecated_adal_authentication = false
|
||||
|
||||
## Queries enabled by default for database_type = "SQLServer" are -
|
||||
## SQLServerPerformanceCounters, SQLServerWaitStatsCategorized, SQLServerDatabaseIO, SQLServerProperties, SQLServerMemoryClerks,
|
||||
## SQLServerSchedulers, SQLServerRequests, SQLServerVolumeSpace, SQLServerCpu, SQLServerAvailabilityReplicaStates, SQLServerDatabaseReplicaStates,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
package sqlserver
|
||||
|
||||
import "time"
|
||||
|
||||
// New token structure for Azure Identity SDK
|
||||
type azureToken struct {
|
||||
token string
|
||||
expiresOn time.Time
|
||||
}
|
||||
|
||||
// IsExpired helper method for Azure token expiry
|
||||
func (t *azureToken) IsExpired() bool {
|
||||
if t == nil {
|
||||
return true
|
||||
}
|
||||
return time.Now().After(t.expiresOn)
|
||||
}
|
||||
|
|
@ -35,6 +35,11 @@
|
|||
## A list of queries to explicitly ignore.
|
||||
exclude_query = ["SQLServerAvailabilityReplicaStates", "SQLServerDatabaseReplicaStates"]
|
||||
|
||||
## Force using the deprecated ADAL authentication method instead of the recommended
|
||||
## MSAL method. Setting this option is not recommended and only exists for backward
|
||||
## compatibility.
|
||||
# use_deprecated_adal_authentication = false
|
||||
|
||||
## Queries enabled by default for database_type = "SQLServer" are -
|
||||
## SQLServerPerformanceCounters, SQLServerWaitStatsCategorized, SQLServerDatabaseIO, SQLServerProperties, SQLServerMemoryClerks,
|
||||
## SQLServerSchedulers, SQLServerRequests, SQLServerVolumeSpace, SQLServerCpu, SQLServerAvailabilityReplicaStates, SQLServerDatabaseReplicaStates,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
|
||||
// Legacy ADAL package - kept for backward compatibility
|
||||
"github.com/Azure/go-autorest/autorest/adal"
|
||||
mssql "github.com/microsoft/go-mssqldb"
|
||||
|
||||
|
|
@ -55,9 +58,18 @@ type SQLServer struct {
|
|||
HealthMetric bool `toml:"health_metric"`
|
||||
Log telegraf.Logger `toml:"-"`
|
||||
|
||||
pools []*sql.DB
|
||||
queries mapQuery
|
||||
adalToken *adal.Token
|
||||
pools []*sql.DB
|
||||
queries mapQuery
|
||||
|
||||
// Legacy token - kept for backward compatibility
|
||||
adalToken *adal.Token
|
||||
// New token using Azure Identity SDK
|
||||
azToken *azureToken
|
||||
// Config option to use legacy ADAL authentication instead of the newer Azure Identity SDK
|
||||
// When true, the deprecated ADAL library will be used
|
||||
// When false (default), the new Azure Identity SDK will be used
|
||||
UseAdalToken bool `toml:"use_deprecated_adal_authentication" deprecated:"1.40.0;migrate to MSAL authentication"`
|
||||
|
||||
muCacheLock sync.RWMutex
|
||||
}
|
||||
|
||||
|
|
@ -70,7 +82,7 @@ type query struct {
|
|||
|
||||
type mapQuery map[string]query
|
||||
|
||||
// healthMetric struct tracking the number of attempted vs successful connections for each connection string
|
||||
// healthMetric struct tracking the number of attempted vs. successful connections for each connection string
|
||||
type healthMetric struct {
|
||||
attemptedQueries int
|
||||
successfulQueries int
|
||||
|
|
@ -466,54 +478,124 @@ func (s *SQLServer) getDatabaseTypeToLog() string {
|
|||
return logname
|
||||
}
|
||||
|
||||
// Get Token Provider by loading cached token or refreshed token
|
||||
// ------------------------------------------------------------------------------
|
||||
// Token Provider Implementation
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
// getTokenProvider returns a function that provides authentication tokens for SQL Server.
|
||||
//
|
||||
// DEPRECATION NOTICE:
|
||||
// The ADAL authentication library is deprecated and will be removed in a future version.
|
||||
// It is strongly recommended to migrate to the Azure Identity SDK.
|
||||
// See the migration documentation at: https://learn.microsoft.com/en-us/azure/active-directory/develop/msal-migration
|
||||
//
|
||||
// This implementation supports both authentication methods:
|
||||
// 1. Azure Identity SDK (default, recommended)
|
||||
// 2. Legacy ADAL library (deprecated, maintained for backward compatibility)
|
||||
//
|
||||
// To control which authentication library is used, set the use_deprecated_adal_authentication config option:
|
||||
// - use_deprecated_adal_authentication = true : Use legacy ADAL authentication (deprecated)
|
||||
// - use_deprecated_adal_authentication = false : Use Azure Identity SDK (recommended)
|
||||
// - Not set : Use Azure Identity SDK (recommended)
|
||||
func (s *SQLServer) getTokenProvider() (func() (string, error), error) {
|
||||
var tokenString string
|
||||
|
||||
// load token
|
||||
s.muCacheLock.RLock()
|
||||
token, err := s.loadToken()
|
||||
s.muCacheLock.RUnlock()
|
||||
|
||||
// if there's error while loading token or found an expired token, refresh token and save it
|
||||
if err != nil || token.IsExpired() {
|
||||
// refresh token within a write-lock
|
||||
s.muCacheLock.Lock()
|
||||
defer s.muCacheLock.Unlock()
|
||||
|
||||
// load token again, in case it's been refreshed by another thread
|
||||
token, err = s.loadToken()
|
||||
|
||||
// check loaded token's error/validity, then refresh/save token
|
||||
if err != nil || token.IsExpired() {
|
||||
// get new token
|
||||
spt, err := s.refreshToken()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// use the refreshed token
|
||||
tokenString = spt.OAuthToken()
|
||||
} else {
|
||||
// use locally cached token
|
||||
tokenString = token.OAuthToken()
|
||||
}
|
||||
// Check if use_deprecated_adal_authentication config option is set to determine which auth method to use
|
||||
// Default to using Azure Identity SDK if the config is not set
|
||||
useAzureIdentity := !s.UseAdalToken
|
||||
if useAzureIdentity {
|
||||
s.Log.Debugf("Using Azure Identity SDK for authentication (recommended)")
|
||||
} else {
|
||||
// use locally cached token
|
||||
tokenString = token.OAuthToken()
|
||||
s.Log.Debugf("Using legacy ADAL for authentication (deprecated, will be removed in 1.40.0)")
|
||||
}
|
||||
|
||||
// return acquired token
|
||||
var tokenString string
|
||||
|
||||
if useAzureIdentity {
|
||||
// Use Azure Identity SDK
|
||||
s.muCacheLock.RLock()
|
||||
token, err := s.loadAzureToken()
|
||||
s.muCacheLock.RUnlock()
|
||||
|
||||
// If the token is nil, expired, or there was an error loading it, refresh the token
|
||||
if err != nil || token == nil || token.IsExpired() {
|
||||
// Refresh token within a write-lock
|
||||
s.muCacheLock.Lock()
|
||||
defer s.muCacheLock.Unlock()
|
||||
|
||||
// Load token again, in case it's been refreshed by another thread
|
||||
token, err = s.loadAzureToken()
|
||||
|
||||
// Check loaded token's error/validity, then refresh/save token
|
||||
if err != nil || token == nil || token.IsExpired() {
|
||||
// Get new token
|
||||
newToken, err := s.refreshAzureToken()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Use the refreshed token
|
||||
tokenString = newToken.token
|
||||
} else {
|
||||
// Use locally cached token
|
||||
tokenString = token.token
|
||||
}
|
||||
} else {
|
||||
// Use locally cached token
|
||||
tokenString = token.token
|
||||
}
|
||||
} else {
|
||||
// Use legacy ADAL approach for backward compatibility
|
||||
s.muCacheLock.RLock()
|
||||
token, err := s.loadToken()
|
||||
s.muCacheLock.RUnlock()
|
||||
|
||||
// If there's an error while loading token or found an expired token, refresh token and save it
|
||||
if err != nil || token.IsExpired() {
|
||||
// Refresh token within a write-lock
|
||||
s.muCacheLock.Lock()
|
||||
defer s.muCacheLock.Unlock()
|
||||
|
||||
// Load token again, in case it's been refreshed by another thread
|
||||
token, err = s.loadToken()
|
||||
|
||||
// Check loaded token's error/validity, then refresh/save token
|
||||
if err != nil || token.IsExpired() {
|
||||
// Get new token
|
||||
spt, err := s.refreshToken()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Use the refreshed token
|
||||
tokenString = spt.OAuthToken()
|
||||
} else {
|
||||
// Use locally cached token
|
||||
tokenString = token.OAuthToken()
|
||||
}
|
||||
} else {
|
||||
// Use locally cached token
|
||||
tokenString = token.OAuthToken()
|
||||
}
|
||||
}
|
||||
|
||||
// Return acquired token
|
||||
//nolint:unparam // token provider function always returns nil error in this scenario
|
||||
return func() (string, error) {
|
||||
return tokenString, nil
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Load token from in-mem cache
|
||||
// ------------------------------------------------------------------------------
|
||||
// Legacy ADAL Token Methods - Kept for backward compatibility
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
// loadToken loads a token from in-memory cache using the legacy ADAL method.
|
||||
//
|
||||
// Deprecated: This method uses the deprecated ADAL library and will be removed in a future version.
|
||||
// Use the Azure Identity SDK instead of setting use_deprecated_adal_authentication = false or omitting it.
|
||||
// See migration documentation: https://learn.microsoft.com/en-us/azure/active-directory/develop/msal-migration
|
||||
func (s *SQLServer) loadToken() (*adal.Token, error) {
|
||||
// This method currently does a simplistic task of reading a from variable (in-mem cache),
|
||||
// however it's been structured here to allow extending the cache mechanism to a different approach in future
|
||||
// This method currently does a simplistic task of reading from a variable (in-mem cache);
|
||||
// however, it's been structured here to allow extending the cache mechanism to a different approach in future
|
||||
|
||||
if s.adalToken == nil {
|
||||
return nil, errors.New("token is nil or failed to load existing token")
|
||||
|
|
@ -522,31 +604,39 @@ func (s *SQLServer) loadToken() (*adal.Token, error) {
|
|||
return s.adalToken, nil
|
||||
}
|
||||
|
||||
// Refresh token for the resource, and save to in-mem cache
|
||||
// refreshToken refreshes the token using the legacy ADAL method.
|
||||
//
|
||||
// Deprecated: This method uses the deprecated ADAL library and will be removed in a future version.
|
||||
// Use the Azure Identity SDK instead of setting use_deprecated_adal_authentication = false or omitting it.
|
||||
// See migration documentation: https://learn.microsoft.com/en-us/azure/active-directory/develop/msal-migration
|
||||
func (s *SQLServer) refreshToken() (*adal.Token, error) {
|
||||
// get MSI endpoint to get a token
|
||||
msiEndpoint, err := adal.GetMSIVMEndpoint()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("failed to get MSI endpoint: %w", err)
|
||||
}
|
||||
|
||||
// get new token for the resource id
|
||||
// get a new token for the resource id
|
||||
var spt *adal.ServicePrincipalToken
|
||||
if s.ClientID == "" {
|
||||
// Using system-assigned managed identity
|
||||
s.Log.Debugf("Using system-assigned managed identity with ADAL")
|
||||
spt, err = adal.NewServicePrincipalTokenFromMSI(msiEndpoint, sqlAzureResourceID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("failed to create service principal token from MSI: %w", err)
|
||||
}
|
||||
} else {
|
||||
// Using user-assigned managed identity
|
||||
s.Log.Debugf("Using user-assigned managed identity with ClientID: %s with ADAL", s.ClientID)
|
||||
spt, err = adal.NewServicePrincipalTokenFromMSIWithUserAssignedID(msiEndpoint, sqlAzureResourceID, s.ClientID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("failed to create service principal token from MSI with user-assigned ID: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// ensure token is fresh
|
||||
// ensure the token is fresh
|
||||
if err := spt.EnsureFresh(); err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("failed to ensure token freshness: %w", err)
|
||||
}
|
||||
|
||||
// save token to local in-mem cache
|
||||
|
|
@ -563,6 +653,64 @@ func (s *SQLServer) refreshToken() (*adal.Token, error) {
|
|||
return s.adalToken, nil
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// New Azure Identity SDK Token Methods
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
// loadAzureToken loads a token from in-memory cache using the Azure Identity SDK.
|
||||
//
|
||||
// This is the recommended authentication method for Azure SQL resources.
|
||||
func (s *SQLServer) loadAzureToken() (*azureToken, error) {
|
||||
// This method reads from variable (in-mem cache) but can be extended
|
||||
// for different cache mechanisms in the future
|
||||
|
||||
if s.azToken == nil {
|
||||
return nil, errors.New("token is nil or failed to load existing token")
|
||||
}
|
||||
|
||||
return s.azToken, nil
|
||||
}
|
||||
|
||||
// refreshAzureToken refreshes the token using the Azure Identity SDK.
|
||||
//
|
||||
// This is the recommended authentication method for Azure SQL resources.
|
||||
func (s *SQLServer) refreshAzureToken() (*azureToken, error) {
|
||||
var options *azidentity.ManagedIdentityCredentialOptions
|
||||
|
||||
if s.ClientID != "" {
|
||||
options = &azidentity.ManagedIdentityCredentialOptions{
|
||||
ID: azidentity.ResourceID(s.ClientID),
|
||||
}
|
||||
}
|
||||
cred, err := azidentity.NewManagedIdentityCredential(options)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create managed identity credential: %w", err)
|
||||
}
|
||||
|
||||
// Get token from Azure AD
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
accessToken, err := cred.GetToken(ctx, policy.TokenRequestOptions{
|
||||
Scopes: []string{sqlAzureResourceID + "/.default"},
|
||||
})
|
||||
if err != nil {
|
||||
credType := "system-assigned"
|
||||
if s.ClientID != "" {
|
||||
credType = fmt.Sprintf("user-assigned (ClientID: %s)", s.ClientID)
|
||||
}
|
||||
return nil, fmt.Errorf("failed to get token using %s managed identity: %w", credType, err)
|
||||
}
|
||||
|
||||
// Save token to cache
|
||||
s.azToken = &azureToken{
|
||||
token: accessToken.Token,
|
||||
expiresOn: accessToken.ExpiresOn,
|
||||
}
|
||||
|
||||
return s.azToken, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
inputs.Add("sqlserver", func() telegraf.Input {
|
||||
return &SQLServer{
|
||||
|
|
|
|||
|
|
@ -151,6 +151,8 @@ func (p *Parser) parseCriticalPath(input []byte) ([]telegraf.Metric, error) {
|
|||
}
|
||||
|
||||
var metrics []telegraf.Metric
|
||||
// timestamp defaults to current time
|
||||
now := time.Now()
|
||||
|
||||
for _, c := range p.Configs {
|
||||
// Measurement name can either be hardcoded, or parsed from the JSON using a GJSON path expression
|
||||
|
|
@ -162,8 +164,8 @@ func (p *Parser) parseCriticalPath(input []byte) ([]telegraf.Metric, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// timestamp defaults to current time, or can be parsed from the JSON using a GJSON path expression
|
||||
timestamp := time.Now()
|
||||
// timestamp can be parsed from the JSON using a GJSON path expression
|
||||
timestamp := now
|
||||
if c.TimestampPath != "" {
|
||||
result := gjson.GetBytes(input, c.TimestampPath)
|
||||
|
||||
|
|
@ -200,13 +202,15 @@ func (p *Parser) parseCriticalPath(input []byte) ([]telegraf.Metric, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
metrics = append(metrics, cartesianProduct(tags, fields)...)
|
||||
cmetrics := cartesianProduct(tags, fields)
|
||||
|
||||
if len(objects) != 0 && len(metrics) != 0 {
|
||||
metrics = cartesianProduct(objects, metrics)
|
||||
if len(objects) != 0 && len(cmetrics) != 0 {
|
||||
cmetrics = cartesianProduct(objects, cmetrics)
|
||||
} else {
|
||||
metrics = append(metrics, objects...)
|
||||
cmetrics = append(cmetrics, objects...)
|
||||
}
|
||||
|
||||
metrics = append(metrics, cmetrics...)
|
||||
}
|
||||
|
||||
for k, v := range p.DefaultTags {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
api_http_status_codes 200=11586,201=16,202=14,204=8,404=43,500=0,503=0 1741532840501119000
|
||||
api_requests requests=11668 1741532840501225000
|
||||
api_responses responses=11667 1741532840501263000
|
||||
api_av sessions_added=0,sessions_removed=0 1741544068286646000
|
||||
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"api": {
|
||||
"http_status_codes": {
|
||||
"200": 11586,
|
||||
"201": 16,
|
||||
"202": 14,
|
||||
"204": 8,
|
||||
"404": 43,
|
||||
"500": 0,
|
||||
"503": 0
|
||||
},
|
||||
"requests": 11668,
|
||||
"responses": 11667,
|
||||
"av": {
|
||||
"sessions": {
|
||||
"added": 0,
|
||||
"removed": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
[[inputs.file]]
|
||||
files = ["./testdata/object_multiple/input.json"]
|
||||
data_format = "json_v2"
|
||||
|
||||
[[inputs.file.json_v2]]
|
||||
measurement_name = "api_http_status_codes"
|
||||
[[inputs.file.json_v2.object]]
|
||||
path = "api.http_status_codes"
|
||||
|
||||
[[inputs.file.json_v2]]
|
||||
measurement_name = "api_requests"
|
||||
[[inputs.file.json_v2.field]]
|
||||
path = "api.requests"
|
||||
|
||||
[[inputs.file.json_v2]]
|
||||
measurement_name = "api_responses"
|
||||
[[inputs.file.json_v2.field]]
|
||||
path = "api.responses"
|
||||
|
||||
[[inputs.file.json_v2]]
|
||||
measurement_name = "api_av"
|
||||
[[inputs.file.json_v2.object]]
|
||||
path = "api.av"
|
||||
Loading…
Reference in New Issue