@@ -12,39 +12,61 @@ import (
1212)
1313
1414const (
15- exportMetrics = maps .Bits (1 << iota )
16- exportTraces
15+ // if the corresponding bit is set to 1, this means that this signal
16+ // is not going to be emitted
17+ blockMetrics = maps .Bits (1 << iota )
18+ blockTraces
1719)
1820
1921var modeForText = map [string ]maps.Bits {
20- "metrics" : exportMetrics ,
21- "traces" : exportTraces ,
22+ "metrics" : blockMetrics ,
23+ "traces" : blockTraces ,
2224}
2325
24- type ExportModes struct {
25- items maps.Bits
26- }
26+ const (
27+ // the zero-value of ExportModes (blockSignal == 0) means that the value is unset.
28+ // This is, all the signals are allowed.
29+ // In the corresponding YAML is a null or undefined value
30+ unset = maps .Bits (0 )
31+ // the -1 (all bits to one) value of ExportModes means that the value is set to
32+ // an empty set: all the signals are blocked.
33+ // In the corresponding YAML it's an empty sequence []
34+ blockAll = maps .Bits (^ uint (0 ))
35+ )
2736
28- func (modes * ExportModes ) canExport (mode maps.Bits ) bool {
29- if modes == nil {
30- return true
31- }
32- return modes .items .Has (mode )
37+ // ExportModeUnset corresponds to an undefined export mode in the configuration YAML
38+ // (null or undefined value). This means that all the signals (traces, metrics) are
39+ // going to be exported
40+ var ExportModeUnset = ExportModes {blockSignal : unset }
41+
42+ // ExportModes specifies which signals are going to be exported for a given service,
43+ // via the public methods CanExportTraces and CanExportMetrics.
44+ // Internally, it has three modes of operation depending on how it is defined in the YAML:
45+ // - When it is undefined or null in the YAML, it will allow exporting all the signals
46+ // (as no blocking signals are defined)
47+ // - When it is defined as an empty list in the YAML, it will block all the signals. No
48+ // metrics nor traces are exported.
49+ // - When it is defined as a non-empty list, it will only allow the explicitly specified signals.
50+ type ExportModes struct {
51+ blockSignal maps.Bits
3352}
3453
3554// CanExportTraces reports whether traces can be exported.
3655// It's provided as a convenience function.
37- func (modes * ExportModes ) CanExportTraces () bool {
38- return modes .canExport ( exportTraces )
56+ func (modes ExportModes ) CanExportTraces () bool {
57+ return ! modes .blockSignal . Has ( blockTraces )
3958}
4059
4160// CanExportMetrics reports whether metrics can be exported.
4261// It's provided as a convenience function.
43- func (modes * ExportModes ) CanExportMetrics () bool {
44- return modes .canExport ( exportMetrics )
62+ func (modes ExportModes ) CanExportMetrics () bool {
63+ return ! modes .blockSignal . Has ( blockMetrics )
4564}
4665
4766func (modes * ExportModes ) UnmarshalYAML (value * yaml.Node ) error {
67+ // by default, everything is blocked, and we will unblock each signal
68+ // as long as we parse them in the YAML
69+ modes .blockSignal = blockAll
4870 if value .Kind != yaml .SequenceNode {
4971 return fmt .Errorf ("ExportModes: unexpected YAML node kind %d" , value .Kind )
5072 }
@@ -55,33 +77,27 @@ func (modes *ExportModes) UnmarshalYAML(value *yaml.Node) error {
5577 if mode , ok := modeForText [inner .Value ]; ! ok {
5678 return fmt .Errorf ("ExportModes[%d]: unknown export mode %q" , i , inner .Value )
5779 } else {
58- modes .items |= mode
80+ // a given signal is defined. Remove it from the blocking list
81+ modes .blockSignal ^= mode
5982 }
6083 }
61- return modes .UnmarshalText ([]byte (value .Value ))
62- }
63-
64- func (modes * ExportModes ) UnmarshalText (text []byte ) error {
65- var options []string
66- if err := yaml .Unmarshal (text , & options ); err != nil {
67- return fmt .Errorf ("invalid export_modes: %w" , err )
68- }
69- if options == nil {
70- return nil
71- }
72- modes .items = maps .MappedBits (options , modeForText )
7384 return nil
7485}
7586
76- func (modes * ExportModes ) MarshalYAML () (any , error ) {
77- if modes == nil {
87+ func (modes ExportModes ) MarshalYAML () (any , error ) {
88+ if modes . blockSignal == unset {
7889 return nil , nil
7990 }
8091 node := yaml.Node {
8192 Kind : yaml .SequenceNode ,
8293 }
94+ // return an empty sequence, in opposition of "null" in the unset case
95+ if modes .blockSignal == blockAll {
96+ return node , nil
97+ }
8398 for text , mode := range modeForText {
84- if modes .items .Has (mode ) {
99+ // the given signal is not explicitly blocked, so we can list it as allowed
100+ if ! modes .blockSignal .Has (mode ) {
85101 node .Content = append (node .Content , & yaml.Node {
86102 Kind : yaml .ScalarNode ,
87103 Value : text ,
@@ -90,16 +106,3 @@ func (modes *ExportModes) MarshalYAML() (any, error) {
90106 }
91107 return node , nil
92108}
93-
94- func (modes * ExportModes ) MarshalText () ([]byte , error ) {
95- var options []string
96- if modes != nil {
97- options = make ([]string , 0 , len (modeForText ))
98- for text , mode := range modeForText {
99- if modes .items .Has (mode ) {
100- options = append (options , text )
101- }
102- }
103- }
104- return yaml .Marshal (options )
105- }
0 commit comments