-
Notifications
You must be signed in to change notification settings - Fork 36
feat: Ability to disable log collection at the tracer level #1254
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
a266a71
0ea5243
e48f472
dda37e9
deb9dd8
5ee06c4
8e30ace
5db5d1e
2552001
7564d6b
184a14a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// (c) Copyright IBM Corp. 2025 | ||
|
||
package instana | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Query: In this implementation, do we need a separate file for |
||
|
||
type spanCategory string | ||
|
||
const ( | ||
logging spanCategory = "logging" | ||
unknown spanCategory = "unknown" | ||
) | ||
|
||
func (c spanCategory) String() string { | ||
return string(c) | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggestion: A comment would be nice since it is an exported function. |
||
func (opts *TracerOptions) DisableAllCategories() { | ||
opts.Disable = map[string]bool{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Query: Shouldn't this function be defined in the place where |
||
logging.String(): true, | ||
} | ||
} | ||
|
||
// registeredSpanMap maps span types to their categories | ||
var registeredSpanMap map[RegisteredSpanType]spanCategory = map[RegisteredSpanType]spanCategory{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggestion: Just check whether a function with(switch cases in the future) will be more suiting here. I think we won't be needing a map in that case. |
||
// logging | ||
LogSpanType: logging, | ||
} | ||
|
||
func (r *spanS) getSpanCategory() spanCategory { | ||
// return span category if it is a registered span type | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Query: Shouldn't this function be defined in the place where |
||
if c, ok := registeredSpanMap[RegisteredSpanType(r.Operation)]; ok { | ||
return c | ||
} | ||
|
||
return unknown | ||
} | ||
|
||
func (c spanCategory) Enabled() bool { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Query: Won't Disabled() is more meaningful? |
||
// unrecognized categories are always enabled | ||
if c == unknown { | ||
return true | ||
} | ||
return !sensor.options.Tracer.Disable[c.String()] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe, |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
// (c) Copyright IBM Corp. 2025 | ||
package instana | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestSpanCategoryString(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
category spanCategory | ||
expected string | ||
}{ | ||
{ | ||
name: "Logging category", | ||
category: logging, | ||
expected: "logging", | ||
}, | ||
{ | ||
name: "Unknown category", | ||
category: unknown, | ||
expected: "unknown", | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
result := tt.category.String() | ||
if result != tt.expected { | ||
t.Errorf("Expected %s, got %s", tt.expected, result) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestTracerOptionsDisableAllCategories(t *testing.T) { | ||
opts := &TracerOptions{} | ||
opts.DisableAllCategories() | ||
|
||
expectedCategories := []spanCategory{logging} | ||
|
||
// Check if all categories are disabled | ||
for _, category := range expectedCategories { | ||
if !opts.Disable[category.String()] { | ||
t.Errorf("Category %s should be disabled", category) | ||
} | ||
} | ||
|
||
// Check if the map has the correct size | ||
if len(opts.Disable) != len(expectedCategories) { | ||
t.Errorf("Expected %d disabled categories, got %d", len(expectedCategories), len(opts.Disable)) | ||
} | ||
} | ||
|
||
func TestGetSpanCategory(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
operation string | ||
expectedCat spanCategory | ||
}{ | ||
{ | ||
name: "Log span", | ||
operation: string(LogSpanType), | ||
expectedCat: logging, | ||
}, | ||
{ | ||
name: "Unknown span type", | ||
operation: "unknown-span-type", | ||
expectedCat: unknown, | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
span := &spanS{ | ||
Operation: tt.operation, | ||
} | ||
|
||
result := span.getSpanCategory() | ||
|
||
if result != tt.expectedCat { | ||
t.Errorf("Expected category %s, got %s", tt.expectedCat, result) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestSpanCategoryEnabled(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
category spanCategory | ||
disable map[string]bool | ||
expected bool | ||
}{ | ||
{ | ||
name: "Category enabled when no categories are disabled", | ||
category: logging, | ||
disable: map[string]bool{}, | ||
expected: true, | ||
}, | ||
{ | ||
name: "Category disabled when specifically disabled", | ||
category: logging, | ||
disable: map[string]bool{"logging": true}, | ||
expected: false, | ||
}, | ||
{ | ||
name: "Unknown category always enabled", | ||
category: unknown, | ||
disable: map[string]bool{"logging": true}, | ||
expected: true, | ||
}, | ||
} | ||
|
||
for _, tc := range tests { | ||
t.Run(tc.name, func(t *testing.T) { | ||
InitCollector(&Options{ | ||
Tracer: TracerOptions{ | ||
Disable: tc.disable, | ||
}, | ||
}) | ||
defer ShutdownCollector() | ||
|
||
result := tc.category.Enabled() | ||
|
||
assert.Equal(t, tc.expected, result) | ||
}) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
# Disabling Log Spans | ||
|
||
The Instana Go Tracer allows you to disable log spans to reduce the amount of data being collected and processed. This can be useful in high-volume environments or when you want to focus on specific types of traces. | ||
|
||
## Supported Span Categories | ||
|
||
Currently, only the following span category can be disabled: | ||
|
||
| Category | Description | Affected Instrumentations | | ||
| --------- | ----------- | ------------------------- | | ||
| `logging` | Log spans | `logrus` | | ||
|
||
## Configuration Methods | ||
|
||
There are three ways to disable log spans: | ||
|
||
### 1. Using Code | ||
|
||
You can disable log spans when initializing the tracer: | ||
|
||
```go | ||
col := instana.InitCollector(&instana.Options{ | ||
Service: "My Service", | ||
Tracer: instana.TracerOptions{ | ||
Disable: map[string]bool{ | ||
"logging": true, // Disable log spans | ||
}, | ||
}, | ||
}) | ||
``` | ||
|
||
### 2. Using Environment Variables | ||
|
||
You can disable log spans using the `INSTANA_TRACING_DISABLE` environment variable: | ||
|
||
```bash | ||
# Disable log spans | ||
export INSTANA_TRACING_DISABLE="logging" | ||
|
||
# Disable all tracing | ||
export INSTANA_TRACING_DISABLE=true | ||
``` | ||
|
||
### 3. Using Configuration File | ||
|
||
You can create a YAML configuration file and specify its path using the `INSTANA_CONFIG_PATH` environment variable: | ||
|
||
```yaml | ||
# config.yaml | ||
tracing: | ||
disable: | ||
- logging | ||
``` | ||
|
||
```bash | ||
export INSTANA_CONFIG_PATH=/path/to/config.yaml | ||
``` | ||
|
||
## Priority Order | ||
|
||
When multiple configuration methods are used, they are applied in the following order of precedence: | ||
|
||
1. Configuration file (`INSTANA_CONFIG_PATH`) | ||
2. Environment variable (`INSTANA_TRACING_DISABLE`) | ||
3. Code-level configuration | ||
|
||
## Example | ||
|
||
### Disable Log Spans | ||
|
||
```go | ||
col := instana.InitCollector(&instana.Options{ | ||
Service: "My Service", | ||
Tracer: instana.TracerOptions{ | ||
Disable: map[string]bool{ | ||
"logging": true, | ||
}, | ||
}, | ||
}) | ||
``` | ||
|
||
## Use Cases | ||
|
||
- **Performance Optimization**: In high-throughput applications, disabling log spans can reduce the overhead of tracing. | ||
- **Cost Management**: Reduce the volume of trace data sent to Instana to manage costs. | ||
- **Focus on Specific Areas**: Disable log spans to focus on the parts of your application that need attention. | ||
- **Testing**: Temporarily disable log spans during testing or development. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -66,7 +66,13 @@ IncludeProfilerFrames is whether to include profiler calls into the profile or n | |
|
||
**Type:** [TracerOptions](https://pkg.go.dev/github.com/instana/go-sensor#TracerOptions) | ||
|
||
Tracer contains tracer-specific configuration used by all tracers | ||
Tracer contains tracer-specific configuration used by all tracers. Key options include: | ||
|
||
- **Disable**: A map of span categories to disable. Currently, only the "logging" category is supported. See [Disabling Log Spans](disabling_spans.md) for details. | ||
- **DropAllLogs**: Turns log events on all spans into no-ops when set to true. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Query: How can the user set this, |
||
- **MaxLogsPerSpan**: Maximum number of log records that can be attached to a span. | ||
- **Secrets**: A secrets matcher used to filter out sensitive data from HTTP requests, database connection strings, etc. | ||
- **CollectableHTTPHeaders**: A list of HTTP headers to be collected from requests. | ||
|
||
#### AgentClient | ||
|
||
|
@@ -97,3 +103,4 @@ Go Tracer only captures log spans with severity `warn` or higher. | |
[Tracing SQL Driver Databases](sql.md) | | ||
[Tracing Other Go Packages](other_packages.md) | | ||
[Instrumenting Code Manually](manual_instrumentation.md) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should name the file for the component present, not for a feature.