-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
config.go
604 lines (492 loc) · 21.7 KB
/
config.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2016-present Datadog, Inc.
package config
import (
"crypto/tls"
"errors"
"net"
"net/http"
"net/url"
"os"
"regexp"
"time"
"github.com/DataDog/opentelemetry-mapping-go/pkg/otlp/attributes"
"github.com/DataDog/datadog-agent/pkg/obfuscate"
"github.com/DataDog/datadog-agent/pkg/remoteconfig/state"
"github.com/DataDog/datadog-agent/pkg/trace/log"
"github.com/DataDog/datadog-agent/pkg/trace/traceutil"
)
// ServiceName specifies the service name used in the operating system.
const ServiceName = "datadog-trace-agent"
// ErrMissingAPIKey is returned when the config could not be validated due to missing API key.
var ErrMissingAPIKey = errors.New("you must specify an API Key, either via a configuration file or the DD_API_KEY env var")
// Endpoint specifies an endpoint that the trace agent will write data (traces, stats & services) to.
type Endpoint struct {
APIKey string `json:"-"` // never marshal this
Host string
// NoProxy will be set to true when the proxy setting for the trace API endpoint
// needs to be ignored (e.g. it is part of the "no_proxy" list in the yaml settings).
NoProxy bool
}
// TelemetryEndpointPrefix specifies the prefix of the telemetry endpoint URL.
const TelemetryEndpointPrefix = "https://instrumentation-telemetry-intake."
// OTLP holds the configuration for the OpenTelemetry receiver.
type OTLP struct {
// BindHost specifies the host to bind the receiver to.
BindHost string `mapstructure:"-"`
// GRPCPort specifies the port to use for the plain HTTP receiver.
// If unset (or 0), the receiver will be off.
GRPCPort int `mapstructure:"grpc_port"`
// SpanNameRemappings is the map of datadog span names and preferred name to map to. This can be used to
// automatically map Datadog Span Operation Names to an updated value. All entries should be key/value pairs.
SpanNameRemappings map[string]string `mapstructure:"span_name_remappings"`
// SpanNameAsResourceName specifies whether the OpenTelemetry span's name should be
// used as the Datadog span's operation name. By default (when this is false), the
// operation name is deduced from a combination between the instrumentation scope
// name and the span kind.
//
// For context, the OpenTelemetry 'Span Name' is equivalent to the Datadog 'resource name'.
// The Datadog Span's Operation Name equivalent in OpenTelemetry does not exist, but the span's
// kind comes close.
SpanNameAsResourceName bool `mapstructure:"span_name_as_resource_name"`
// MaxRequestBytes specifies the maximum number of bytes that will be read
// from an incoming HTTP request.
MaxRequestBytes int64 `mapstructure:"-"`
// ProbabilisticSampling specifies the percentage of traces to ingest. Exceptions are made for errors
// and rare traces (outliers) if "RareSamplerEnabled" is true. Invalid values are equivalent to 100.
// If spans have the "sampling.priority" attribute set, probabilistic sampling is skipped and the user's
// decision is followed.
ProbabilisticSampling float64
// AttributesTranslator specifies an OTLP to Datadog attributes translator.
AttributesTranslator *attributes.Translator `mapstructure:"-"`
}
// ObfuscationConfig holds the configuration for obfuscating sensitive data
// for various span types.
type ObfuscationConfig struct {
// ES holds the obfuscation configuration for ElasticSearch bodies.
ES obfuscate.JSONConfig `mapstructure:"elasticsearch"`
// Mongo holds the obfuscation configuration for MongoDB queries.
Mongo obfuscate.JSONConfig `mapstructure:"mongodb"`
// SQLExecPlan holds the obfuscation configuration for SQL Exec Plans. This is strictly for safety related obfuscation,
// not normalization. Normalization of exec plans is configured in SQLExecPlanNormalize.
SQLExecPlan obfuscate.JSONConfig `mapstructure:"sql_exec_plan"`
// SQLExecPlanNormalize holds the normalization configuration for SQL Exec Plans.
SQLExecPlanNormalize obfuscate.JSONConfig `mapstructure:"sql_exec_plan_normalize"`
// HTTP holds the obfuscation settings for HTTP URLs.
HTTP obfuscate.HTTPConfig `mapstructure:"http"`
// RemoveStackTraces specifies whether stack traces should be removed.
// More specifically "error.stack" tag values will be cleared.
RemoveStackTraces bool `mapstructure:"remove_stack_traces"`
// Redis holds the configuration for obfuscating the "redis.raw_command" tag
// for spans of type "redis".
Redis obfuscate.RedisConfig `mapstructure:"redis"`
// Memcached holds the configuration for obfuscating the "memcached.command" tag
// for spans of type "memcached".
Memcached obfuscate.MemcachedConfig `mapstructure:"memcached"`
// CreditCards holds the configuration for obfuscating credit cards.
CreditCards CreditCardsConfig `mapstructure:"credit_cards"`
}
// Export returns an obfuscate.Config matching o.
func (o *ObfuscationConfig) Export(conf *AgentConfig) obfuscate.Config {
return obfuscate.Config{
SQL: obfuscate.SQLConfig{
TableNames: conf.HasFeature("table_names"),
ReplaceDigits: conf.HasFeature("quantize_sql_tables") || conf.HasFeature("replace_sql_digits"),
KeepSQLAlias: conf.HasFeature("keep_sql_alias"),
DollarQuotedFunc: conf.HasFeature("dollar_quoted_func"),
Cache: conf.HasFeature("sql_cache"),
},
ES: o.ES,
Mongo: o.Mongo,
SQLExecPlan: o.SQLExecPlan,
SQLExecPlanNormalize: o.SQLExecPlanNormalize,
HTTP: o.HTTP,
Redis: o.Redis,
Memcached: o.Memcached,
Logger: new(debugLogger),
}
}
type debugLogger struct{}
func (debugLogger) Debugf(format string, params ...interface{}) {
log.Debugf(format, params...)
}
// CreditCardsConfig holds the configuration for credit card obfuscation in
// (Meta) tags.
type CreditCardsConfig struct {
// Enabled specifies whether this feature should be enabled.
Enabled bool `mapstructure:"enabled"`
// Luhn specifies whether Luhn checksum validation should be enabled.
// https://dev.to/shiraazm/goluhn-a-simple-library-for-generating-calculating-and-verifying-luhn-numbers-588j
// It reduces false positives, but increases the CPU time X3.
Luhn bool `mapstructure:"luhn"`
}
// Enablable can represent any option that has an "enabled" boolean sub-field.
type Enablable struct {
Enabled bool `mapstructure:"enabled"`
}
// TelemetryConfig holds Instrumentation telemetry Endpoints information
type TelemetryConfig struct {
Enabled bool `mapstructure:"enabled"`
Endpoints []*Endpoint
}
// ReplaceRule specifies a replace rule.
type ReplaceRule struct {
// Name specifies the name of the tag that the replace rule addresses. However,
// some exceptions apply such as:
// • "resource.name" will target the resource
// • "*" will target all tags and the resource
Name string `mapstructure:"name"`
// Pattern specifies the regexp pattern to be used when replacing. It must compile.
Pattern string `mapstructure:"pattern"`
// Re holds the compiled Pattern and is only used internally.
Re *regexp.Regexp `mapstructure:"-"`
// Repl specifies the replacement string to be used when Pattern matches.
Repl string `mapstructure:"repl"`
}
// WriterConfig specifies configuration for an API writer.
type WriterConfig struct {
// ConnectionLimit specifies the maximum number of concurrent outgoing
// connections allowed for the sender.
ConnectionLimit int `mapstructure:"connection_limit"`
// QueueSize specifies the maximum number or payloads allowed to be queued
// in the sender.
QueueSize int `mapstructure:"queue_size"`
// FlushPeriodSeconds specifies the frequency at which the writer's buffer
// will be flushed to the sender, in seconds. Fractions are permitted.
FlushPeriodSeconds float64 `mapstructure:"flush_period_seconds"`
}
// FargateOrchestratorName is a Fargate orchestrator name.
type FargateOrchestratorName string
const (
// OrchestratorECS represents AWS ECS
OrchestratorECS FargateOrchestratorName = "ECS"
// OrchestratorEKS represents AWS EKS
OrchestratorEKS FargateOrchestratorName = "EKS"
// OrchestratorUnknown is used when we cannot retrieve the orchestrator
OrchestratorUnknown FargateOrchestratorName = "Unknown"
)
// ProfilingProxyConfig ...
type ProfilingProxyConfig struct {
// DDURL ...
DDURL string
// AdditionalEndpoints ...
AdditionalEndpoints map[string][]string
}
// EVPProxy contains the settings for the EVPProxy proxy.
type EVPProxy struct {
// Enabled reports whether EVPProxy is enabled (true by default).
Enabled bool
// DDURL is the Datadog site to forward payloads to (defaults to the Site setting if not set).
DDURL string
// APIKey is the main API Key (defaults to the main API key).
APIKey string `json:"-"` // Never marshal this field
// ApplicationKey to be used for requests with the X-Datadog-NeedsAppKey set (defaults to the top-level Application Key).
ApplicationKey string `json:"-"` // Never marshal this field
// AdditionalEndpoints is a map of additional Datadog sites to API keys.
AdditionalEndpoints map[string][]string
// MaxPayloadSize indicates the size at which payloads will be rejected, in bytes.
MaxPayloadSize int64
}
// InstallSignatureConfig contains the information on how the agent was installed
// and a unique identifier that distinguishes this agent from others.
type InstallSignatureConfig struct {
Found bool `json:"-"`
InstallID string `json:"install_id"`
InstallType string `json:"install_type"`
InstallTime int64 `json:"install_time"`
}
// DebuggerProxyConfig ...
type DebuggerProxyConfig struct {
// DDURL ...
DDURL string
// APIKey ...
APIKey string `json:"-"` // Never marshal this field
// AdditionalEndpoints is a map of additional Datadog sites to API keys.
AdditionalEndpoints map[string][]string `json:"-"` // Never marshal this field
}
// SymDBProxyConfig ...
type SymDBProxyConfig struct {
// DDURL ...
DDURL string
// APIKey ...
APIKey string `json:"-"` // Never marshal this field
// AdditionalEndpoints is a map of additional Datadog endpoints to API keys.
AdditionalEndpoints map[string][]string `json:"-"` // Never marshal this field
}
// AgentConfig handles the interpretation of the configuration (with default
// behaviors) in one place. It is also a simple structure to share across all
// the Agent components, with 100% safe and reliable values.
// It is exposed with expvar, so make sure to exclude any sensible field
// from JSON encoding. Use New() to create an instance.
type AgentConfig struct {
Features map[string]struct{}
Enabled bool
AgentVersion string
GitCommit string
Site string // the intake site to use (e.g. "datadoghq.com")
// FargateOrchestrator specifies the name of the Fargate orchestrator. e.g. "ECS", "EKS", "Unknown"
FargateOrchestrator FargateOrchestratorName
// Global
Hostname string
DefaultEnv string // the traces will default to this environment
ConfigPath string // the source of this config, if any
// Endpoints specifies the set of hosts and API keys where traces and stats
// will be uploaded to. The first endpoint is the main configuration endpoint;
// any following ones are read from the 'additional_endpoints' parts of the
// configuration file, if present.
Endpoints []*Endpoint
// Concentrator
BucketInterval time.Duration // the size of our pre-aggregation per bucket
ExtraAggregators []string // DEPRECATED
PeerServiceAggregation bool // TO BE DEPRECATED - enables/disables stats aggregation for peer.service, used by Concentrator and ClientStatsAggregator
PeerTagsAggregation bool // enables/disables stats aggregation for peer entity tags, used by Concentrator and ClientStatsAggregator
ComputeStatsBySpanKind bool // enables/disables the computing of stats based on a span's `span.kind` field
PeerTags []string // additional tags to use for peer entity stats aggregation
// Sampler configuration
ExtraSampleRate float64
TargetTPS float64
ErrorTPS float64
MaxEPS float64
MaxRemoteTPS float64
// Rare Sampler configuration
RareSamplerEnabled bool
RareSamplerTPS int
RareSamplerCooldownPeriod time.Duration
RareSamplerCardinality int
// Receiver
ReceiverHost string
ReceiverPort int
ReceiverSocket string // if not empty, UDS will be enabled on unix://<receiver_socket>
ConnectionLimit int // for rate-limiting, how many unique connections to allow in a lease period (30s)
ReceiverTimeout int
MaxRequestBytes int64 // specifies the maximum allowed request size for incoming trace payloads
TraceBuffer int // specifies the number of traces to buffer before blocking.
Decoders int // specifies the number of traces that can be concurrently decoded.
MaxConnections int // specifies the maximum number of concurrent incoming connections allowed.
DecoderTimeout int // specifies the maximum time in milliseconds that the decoders will wait for a turn to accept a payload before returning 429
WindowsPipeName string
PipeBufferSize int
PipeSecurityDescriptor string
GUIPort string // the port of the Datadog Agent GUI (for control access)
// Writers
SynchronousFlushing bool // Mode where traces are only submitted when FlushAsync is called, used for Serverless Extension
StatsWriter *WriterConfig
TraceWriter *WriterConfig
ConnectionResetInterval time.Duration // frequency at which outgoing connections are reset. 0 means no reset is performed
// MaxSenderRetries is the maximum number of retries that a sender will perform
// before giving up. Note that the sender may not perform all MaxSenderRetries if
// the agent is under load and the outgoing payload queue is full. In that
// case, the sender will drop failed payloads when it is unable to enqueue
// them for another retry.
MaxSenderRetries int
// internal telemetry
StatsdEnabled bool
StatsdHost string
StatsdPort int
StatsdPipeName string // for Windows Pipes
StatsdSocket string // for UDS Sockets
// logging
LogFilePath string
LogThrottling bool
// watchdog
MaxMemory float64 // MaxMemory is the threshold (bytes allocated) above which program panics and exits, to be restarted
MaxCPU float64 // MaxCPU is the max UserAvg CPU the program should consume
WatchdogInterval time.Duration // WatchdogInterval is the delay between 2 watchdog checks
// http/s proxying
ProxyURL *url.URL
SkipSSLValidation bool
// filtering
Ignore map[string][]string
// ReplaceTags is used to filter out sensitive information from tag values.
// It maps tag keys to a set of replacements. Only supported in A6.
ReplaceTags []*ReplaceRule
// GlobalTags list metadata that will be added to all spans
GlobalTags map[string]string
// transaction analytics
AnalyzedRateByServiceLegacy map[string]float64
AnalyzedSpansByService map[string]map[string]float64
// infrastructure agent binary
DDAgentBin string
// Obfuscation holds sensitive data obufscator's configuration.
Obfuscation *ObfuscationConfig
// MaxResourceLen the maximum length the resource can have
MaxResourceLen int
// RequireTags specifies a list of tags which must be present on the root span in order for a trace to be accepted.
RequireTags []*Tag
// RejectTags specifies a list of tags which must be absent on the root span in order for a trace to be accepted.
RejectTags []*Tag
// RequireTagsRegex specifies a list of regexp for tags which must be present on the root span in order for a trace to be accepted.
RequireTagsRegex []*TagRegex
// RejectTagsRegex specifies a list of regexp for tags which must be absent on the root span in order for a trace to be accepted.
RejectTagsRegex []*TagRegex
// OTLPReceiver holds the configuration for OpenTelemetry receiver.
OTLPReceiver *OTLP
// ProfilingProxy specifies settings for the profiling proxy.
ProfilingProxy ProfilingProxyConfig
// Telemetry settings
TelemetryConfig *TelemetryConfig
// EVPProxy contains the settings for the EVPProxy proxy.
EVPProxy EVPProxy
// DebuggerProxy contains the settings for the Live Debugger proxy.
DebuggerProxy DebuggerProxyConfig
// DebuggerDiagnosticsProxy contains the settings for the Live Debugger diagnostics proxy.
DebuggerDiagnosticsProxy DebuggerProxyConfig
// SymDBProxy contains the settings for the Symbol Database proxy.
SymDBProxy SymDBProxyConfig
// Proxy specifies a function to return a proxy for a given Request.
// See (net/http.Transport).Proxy for more details.
Proxy func(*http.Request) (*url.URL, error) `json:"-"`
// MaxCatalogEntries specifies the maximum number of services to be added to the priority sampler's
// catalog. If not set (0) it will default to 5000.
MaxCatalogEntries int
// RemoteConfigClient retrieves sampling updates from the remote config backend
RemoteConfigClient RemoteClient `json:"-"`
// ContainerTags ...
ContainerTags func(cid string) ([]string, error) `json:"-"`
// ContainerProcRoot is the root dir for `proc` info
ContainerProcRoot string
// DebugServerPort defines the port used by the debug server
DebugServerPort int
// Install Signature
InstallSignature InstallSignatureConfig
// Lambda function name
LambdaFunctionName string
}
// RemoteClient client is used to APM Sampling Updates from a remote source.
// This is an interface around the client provided by pkg/config/remote to allow for easier testing.
type RemoteClient interface {
Close()
Start()
Subscribe(string, func(update map[string]state.RawConfig, applyStateCallback func(string, state.ApplyStatus)))
UpdateApplyStatus(cfgPath string, status state.ApplyStatus)
}
// Tag represents a key/value pair.
type Tag struct {
K, V string
}
// TagRegex represents a key/value regex pattern pair.
type TagRegex struct {
K string
V *regexp.Regexp
}
// New returns a configuration with the default values.
func New() *AgentConfig {
return &AgentConfig{
Enabled: true,
DefaultEnv: "none",
Endpoints: []*Endpoint{{Host: "https://trace.agent.datadoghq.com"}},
FargateOrchestrator: OrchestratorUnknown,
Site: "datadoghq.com",
MaxCatalogEntries: 5000,
BucketInterval: time.Duration(10) * time.Second,
ExtraSampleRate: 1.0,
TargetTPS: 10,
ErrorTPS: 10,
MaxEPS: 200,
MaxRemoteTPS: 100,
RareSamplerEnabled: false,
RareSamplerTPS: 5,
RareSamplerCooldownPeriod: 5 * time.Minute,
RareSamplerCardinality: 200,
ReceiverHost: "localhost",
ReceiverPort: 8126,
MaxRequestBytes: 25 * 1024 * 1024, // 25MB
PipeBufferSize: 1_000_000,
PipeSecurityDescriptor: "D:AI(A;;GA;;;WD)",
GUIPort: "5002",
StatsWriter: new(WriterConfig),
TraceWriter: new(WriterConfig),
ConnectionResetInterval: 0, // disabled
StatsdHost: "localhost",
StatsdPort: 8125,
StatsdEnabled: true,
LogThrottling: true,
LambdaFunctionName: os.Getenv("AWS_LAMBDA_FUNCTION_NAME"),
MaxMemory: 5e8, // 500 Mb, should rarely go above 50 Mb
MaxCPU: 0.5, // 50%, well behaving agents keep below 5%
WatchdogInterval: 10 * time.Second,
Ignore: make(map[string][]string),
AnalyzedRateByServiceLegacy: make(map[string]float64),
AnalyzedSpansByService: make(map[string]map[string]float64),
Obfuscation: &ObfuscationConfig{},
MaxResourceLen: 5000,
GlobalTags: computeGlobalTags(),
Proxy: http.ProxyFromEnvironment,
OTLPReceiver: &OTLP{},
ContainerTags: noopContainerTagsFunc,
TelemetryConfig: &TelemetryConfig{
Endpoints: []*Endpoint{{Host: TelemetryEndpointPrefix + "datadoghq.com"}},
},
EVPProxy: EVPProxy{
Enabled: true,
MaxPayloadSize: 5 * 1024 * 1024,
},
Features: make(map[string]struct{}),
}
}
func computeGlobalTags() map[string]string {
if inAzureAppServices() {
return traceutil.GetAppServicesTags()
}
return make(map[string]string)
}
func noopContainerTagsFunc(_ string) ([]string, error) {
return nil, errors.New("ContainerTags function not defined")
}
// APIKey returns the first (main) endpoint's API key.
func (c *AgentConfig) APIKey() string {
if len(c.Endpoints) == 0 {
return ""
}
return c.Endpoints[0].APIKey
}
// NewHTTPClient returns a new http.Client to be used for outgoing connections to the
// Datadog API.
func (c *AgentConfig) NewHTTPClient() *ResetClient {
return NewResetClient(c.ConnectionResetInterval, func() *http.Client {
return &http.Client{
Timeout: 10 * time.Second,
Transport: c.NewHTTPTransport(),
}
})
}
// NewHTTPTransport returns a new http.Transport to be used for outgoing connections to
// the Datadog API.
func (c *AgentConfig) NewHTTPTransport() *http.Transport {
transport := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: c.SkipSSLValidation},
// below field values are from http.DefaultTransport (go1.12)
Proxy: c.Proxy,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
DualStack: true,
}).DialContext,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
}
return transport
}
//nolint:revive // TODO(APM) Fix revive linter
func (c *AgentConfig) HasFeature(feat string) bool {
_, ok := c.Features[feat]
return ok
}
//nolint:revive // TODO(APM) Fix revive linter
func (c *AgentConfig) AllFeatures() []string {
feats := []string{}
for feat := range c.Features {
feats = append(feats, feat)
}
return feats
}
//nolint:revive // TODO(APM) Fix revive linter
func inAzureAppServices() bool {
_, existsLinux := os.LookupEnv("APPSVC_RUN_ZIP")
_, existsWin := os.LookupEnv("WEBSITE_APPSERVICEAPPLOGS_TRACE_ENABLED")
return existsLinux || existsWin
}