Skip to content

Commit 330fee3

Browse files
committed
[receiver/receiver_creator] Add support for logs' hints
Signed-off-by: ChrsMark <[email protected]>
1 parent 539042d commit 330fee3

File tree

9 files changed

+731
-21
lines changed

9 files changed

+731
-21
lines changed

.chloggen/f_hints_logs.yaml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Use this changelog template to create an entry for release notes.
2+
3+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
4+
change_type: enhancement
5+
6+
# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
7+
component: receivercreator
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: Add support for starting logs' collection based on provided k8s annotations' hints
11+
12+
# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
13+
issues: [34427]
14+
15+
# (Optional) One or more lines of additional information to render under the primary note.
16+
# These lines will be padded with 2 spaces and then inserted directly into the document.
17+
# Use pipe (|) for multiline entries.
18+
subtext:
19+
20+
# If your change doesn't affect end users or the exported elements of any package,
21+
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
22+
# Optional: The change log or logs in which this entry should be included.
23+
# e.g. '[user]' or '[user, api]'
24+
# Include 'user' if the change is relevant to end users.
25+
# Include 'api' if there is a change to a library API.
26+
# Default: '[user]'
27+
change_logs: [user]

receiver/receivercreator/README.md

Lines changed: 111 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -456,9 +456,12 @@ receiver_creator/metrics:
456456
enabled: true
457457
# Define which receivers should be ignored when provided through annotations
458458
# ignore_receivers: []
459+
# define which paths should be excluded from collection
460+
# exclude_paths: []
459461
```
460462

461-
Find bellow the supported annotations that user can define to automatically enable receivers to start collecting metrics signals from the target Pods/containers.
463+
Find bellow the supported annotations that user can define to automatically enable receivers to start
464+
collecting metrics signals from the target Pods/containers.
462465

463466
### Supported metrics annotations
464467

@@ -511,11 +514,91 @@ The current implementation relies on the implementation of `k8sobserver` extensi
511514
the [pod_endpoint](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/v0.111.0/extension/observer/k8sobserver/pod_endpoint.go).
512515
The hints are evaluated per container by extracting the annotations from each [`Port` endpoint](#Port) that is emitted.
513516

517+
### Supported logs annotations
518+
519+
This feature enables `filelog` receiver along with the `container` parser in order to collect logs from the discovered
520+
Pods.
521+
522+
#### Enable/disable discovery
523+
524+
`io.opentelemetry.discovery.logs/enabled` (example: `"true"`)
525+
526+
By default `"false"`.
527+
528+
In case users want to collect logs from all discovered containers by default, `default_logs_discovery` setting
529+
can be used.
530+
NOTE: it is recommended to exclude Collectors' self logs from default collection. Use `exclude_paths` to exclude them)
531+
532+
The following configuration can be used:
533+
534+
```yaml
535+
receiver_creator/logs:
536+
watch_observers: [ k8s_observer ]
537+
discovery:
538+
enabled: true
539+
# collect logs from all containers unless discovery is explicitly disabled
540+
# for a container using the discovery hint
541+
default_logs_discovery: true
542+
# RECOMMENDED: ensure that Collectors' self logs are excluded to avoid circuiting logs
543+
exclude_paths: [/var/log/pods/*opentelemetry-collector-agent*/opentelemetry-collector/*.log]
544+
```
545+
#### Define configuration
546+
The default configuration for the `filelog` receiver is the following:
547+
548+
```yaml
549+
include:
550+
- /var/log/pods/`pod.namespace`_`pod.name`_`pod.uid`/`container_name`/*.log
551+
include_file_name: false
552+
include_file_path: true
553+
operators:
554+
- id: container-parser
555+
type: container
556+
```
557+
This default can be extended using the respective annotation:
558+
`io.opentelemetry.discovery.logs/config`
559+
560+
**Example:**
561+
562+
```yaml
563+
io.opentelemetry.discovery.logs/config: |
564+
include_file_name: true
565+
max_log_size: "2MiB"
566+
operators:
567+
- type: regex_parser
568+
regex: "^(?P<time>\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}) (?P<sev>[A-Z]*) (?P<msg>.*)$"
569+
```
570+
571+
Note that individual settings are overridden by the configuration provided by the hints while the operators list
572+
is extended keeping first the `container` parser.
573+
574+
575+
#### Support multiple target containers
576+
577+
Users can target the annotation to a specific container by suffixing it with the name of that container:
578+
`io.opentelemetry.discovery.logs.<container_name>/endpoint`.
579+
For example:
580+
```yaml
581+
io.opentelemetry.discovery.logs.busybox/config: |
582+
max_log_size: "3MiB"
583+
operators:
584+
- id: some
585+
type: add
586+
field: attributes.tag
587+
value: hints
588+
```
589+
where `busybox` is the name of the target container.
590+
591+
If a Pod is annotated with both container level hints and pod level hints the container level hints have priority and
592+
the Pod level hints are used as a fallback (see detailed example bellow).
593+
594+
The current implementation relies on the implementation of `k8sobserver` extension and specifically
595+
the [pod_endpoint](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/v0.111.0/extension/observer/k8sobserver/pod_endpoint.go).
596+
The hints are evaluated per container by extracting the annotations from each [`Pod Container` endpoint](#Pod Container) that is emitted.
514597

515598

516599
### Examples
517600

518-
#### Metrics example
601+
#### Metrics and Logs example
519602

520603
Collector's configuration:
521604
```yaml
@@ -525,12 +608,22 @@ receivers:
525608
discovery:
526609
enabled: true
527610
receivers:
611+
612+
receiver_creator/logs:
613+
watch_observers: [ k8s_observer ]
614+
discovery:
615+
enabled: true
616+
receivers:
528617
529618
service:
530619
extensions: [ k8s_observer]
531620
pipelines:
532621
metrics:
533-
receivers: [ receiver_creator ]
622+
receivers: [ receiver_creator/metrics ]
623+
processors: []
624+
exporters: [ debug ]
625+
logs:
626+
receivers: [ receiver_creator/logs ]
534627
processors: []
535628
exporters: [ debug ]
536629
```
@@ -600,6 +693,21 @@ spec:
600693
endpoint: "http://`endpoint`/nginx_status"
601694
collection_interval: "30s"
602695
timeout: "20s"
696+
697+
# redis pod container logs hints
698+
io.opentelemetry.discovery.logs.redis/enabled: "true"
699+
io.opentelemetry.discovery.logs.redis/config: |
700+
max_log_size: "4MiB"
701+
operators:
702+
- id: some
703+
type: add
704+
field: attributes.tag
705+
value: logs_hints
706+
707+
# nginx pod container logs hints
708+
io.opentelemetry.discovery.logs.webserver/enabled: "true"
709+
io.opentelemetry.discovery.logs.webserver/config: |
710+
max_log_size: "3MiB"
603711
spec:
604712
volumes:
605713
- name: nginx-conf

receiver/receivercreator/config.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,10 @@ type Config struct {
9090
}
9191

9292
type DiscoveryConfig struct {
93-
Enabled bool `mapstructure:"enabled"`
94-
IgnoreReceivers []string `mapstructure:"ignore_receivers"`
93+
Enabled bool `mapstructure:"enabled"`
94+
IgnoreReceivers []string `mapstructure:"ignore_receivers"`
95+
DefaultLogsDiscovery bool `mapstructure:"default_logs_discovery"`
96+
ExcludePaths []string `mapstructure:"exclude_paths"`
9597
}
9698

9799
func (cfg *Config) Unmarshal(componentParser *confmap.Conf) error {

receiver/receivercreator/config_test.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,3 +299,40 @@ func (*nopWithoutEndpointFactory) CreateTraces(
299299
cfg: cfg,
300300
}, nil
301301
}
302+
303+
type nopWithFilelogConfig struct {
304+
Include []string `mapstructure:"include"`
305+
IncludeFileName bool `mapstructure:"include_file_name"`
306+
IncludeFilePath bool `mapstructure:"include_file_path"`
307+
Operators []any `mapstructure:"operators"`
308+
}
309+
310+
type nopWithFilelogFactory struct {
311+
rcvr.Factory
312+
}
313+
314+
type nopWithFilelogReceiver struct {
315+
mockComponent
316+
consumer.Logs
317+
consumer.Metrics
318+
consumer.Traces
319+
rcvr.Settings
320+
cfg component.Config
321+
}
322+
323+
func (*nopWithFilelogFactory) CreateDefaultConfig() component.Config {
324+
return &nopWithFilelogConfig{}
325+
}
326+
327+
func (*nopWithFilelogFactory) CreateLogs(
328+
_ context.Context,
329+
rcs rcvr.Settings,
330+
cfg component.Config,
331+
nextConsumer consumer.Logs,
332+
) (rcvr.Logs, error) {
333+
return &nopWithEndpointReceiver{
334+
Logs: nextConsumer,
335+
Settings: rcs,
336+
cfg: cfg,
337+
}, nil
338+
}

0 commit comments

Comments
 (0)