Skip to content

Commit 8177bcd

Browse files
authored
Implementation of internal logging context to better be able to log the hierarchy of pipelines and nodes. (#202)
* Implementation of internal logging context to better be able to show the hierarchy of pipelines and nodes. * Added logging context where applicable.
1 parent 46af0b4 commit 8177bcd

27 files changed

Lines changed: 422 additions & 184 deletions
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+

2+
using CodeCasa.AutomationPipelines.Lights.ReactiveNode;
3+
using CodeCasa.Lights;
4+
5+
namespace CodeCasa.AutomationPipelines.Lights.Extensions
6+
{
7+
internal static class ActionExtensions
8+
{
9+
public static Action<T> SetLoggingContext<T>(
10+
this Action<T> configure, string parentName, bool enableLogging)
11+
{
12+
return c =>
13+
{
14+
if (c is IInternalLoggingContext loggingContext)
15+
{
16+
loggingContext.SetParentName(parentName);
17+
if (enableLogging)
18+
{
19+
loggingContext.EnableLoggingInternal();
20+
}
21+
}
22+
configure(c);
23+
};
24+
}
25+
26+
public static Action<T> SetLoggingContext<T, TLight>(
27+
this Action<T> configure, ILightTransitionReactiveNodeConfigurator<TLight> lightTransitionReactiveNodeConfigurator) where TLight : ILight
28+
{
29+
// Note: This method is used for convenience. As we use this internally only, we can assume that all implementations of ILightTransitionReactiveNodeConfigurator also implement IInternalLoggingContext.
30+
var loggingContext = (IInternalLoggingContext)lightTransitionReactiveNodeConfigurator;
31+
return configure.SetLoggingContext(loggingContext.LogName, loggingContext.LoggingEnabled ?? false);
32+
}
33+
}
34+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+

2+
namespace CodeCasa.AutomationPipelines.Lights.Extensions
3+
{
4+
internal static class ObjectExtensions
5+
{
6+
public static T SetLoggingContext<T>(this T obj, string parentName, string name, bool enableLogging)
7+
{
8+
if (obj is IInternalLoggingContext loggingContext)
9+
{
10+
loggingContext.SetParentName(parentName);
11+
loggingContext.SetName(name);
12+
if (enableLogging)
13+
{
14+
loggingContext.EnableLoggingInternal();
15+
}
16+
}
17+
return obj;
18+
}
19+
}
20+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+

2+
namespace CodeCasa.AutomationPipelines.Lights;
3+
4+
internal interface IInternalLoggingContext
5+
{
6+
void EnableLoggingInternal();
7+
void SetName(string name);
8+
void SetParentName(string parentName);
9+
string LogName { get; }
10+
bool? LoggingEnabled { get; }
11+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using CodeCasa.AutomationPipelines.Lights.Extensions;
2+
3+
namespace CodeCasa.AutomationPipelines.Lights.Pipeline;
4+
5+
internal partial class CompositeLightTransitionPipelineConfigurator<TLight> : IInternalLoggingContext
6+
{
7+
private string? _parentName;
8+
private string? _name;
9+
10+
public string LogName => _parentName == null ? _name ?? "Pipeline" : $"{_parentName}->{_name ?? "Pipeline"}";
11+
public bool? LoggingEnabled { get; private set; }
12+
13+
public void EnableLoggingInternal()
14+
{
15+
LoggingEnabled = true;
16+
NodeContainers.Values.ForEach(b => b.EnableLoggingInternal());
17+
}
18+
19+
public void SetParentName(string parentName)
20+
{
21+
_parentName = parentName;
22+
NodeContainers.Values.ForEach(b => b.SetParentName(parentName));
23+
}
24+
25+
public void SetName(string name)
26+
{
27+
_name = name;
28+
NodeContainers.Values.ForEach(b => b.SetName(name));
29+
}
30+
31+
/// <inheritdoc/>
32+
public ILightTransitionPipelineConfigurator<TLight> EnableLogging(string? pipelineName = null)
33+
{
34+
_name = pipelineName;
35+
LoggingEnabled = true;
36+
NodeContainers.Values.ForEach(b => b.EnableLogging(pipelineName));
37+
return this;
38+
}
39+
40+
/// <inheritdoc/>
41+
public ILightTransitionPipelineConfigurator<TLight> DisableLogging()
42+
{
43+
LoggingEnabled = false;
44+
NodeContainers.Values.ForEach(b => b.DisableLogging());
45+
return this;
46+
}
47+
}
Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using CodeCasa.AutomationPipelines.Lights.Cycle;
2+
using CodeCasa.AutomationPipelines.Lights.Extensions;
23
using CodeCasa.Lights;
34

45
namespace CodeCasa.AutomationPipelines.Lights.Pipeline;
@@ -7,28 +8,38 @@ internal partial class CompositeLightTransitionPipelineConfigurator<TLight>
78
{
89
public ILightTransitionPipelineConfigurator<TLight> AddCycle<T>(IObservable<T> triggerObservable, IEnumerable<LightParameters> lightParameters)
910
{
10-
return AddReactiveNode(c => c.AddCycle(triggerObservable, lightParameters));
11+
return AddReactiveNode(c => c
12+
.SetLoggingContext(LogName, "Cycle", LoggingEnabled ?? false)
13+
.AddCycle(triggerObservable, lightParameters));
1114
}
1215

1316
public ILightTransitionPipelineConfigurator<TLight> AddCycle<T>(IObservable<T> triggerObservable,
1417
params LightParameters[] lightParameters)
1518
{
16-
return AddReactiveNode(c => c.AddCycle(triggerObservable, lightParameters));
19+
return AddReactiveNode(c => c
20+
.SetLoggingContext(LogName, "Cycle", LoggingEnabled ?? false)
21+
.AddCycle(triggerObservable, lightParameters));
1722
}
1823

1924
public ILightTransitionPipelineConfigurator<TLight> AddCycle<T>(IObservable<T> triggerObservable, IEnumerable<LightTransition> lightTransitions)
2025
{
21-
return AddReactiveNode(c => c.AddCycle(triggerObservable, lightTransitions));
26+
return AddReactiveNode(c => c
27+
.SetLoggingContext(LogName, "Cycle", LoggingEnabled ?? false)
28+
.AddCycle(triggerObservable, lightTransitions));
2229
}
2330

2431
public ILightTransitionPipelineConfigurator<TLight> AddCycle<T>(IObservable<T> triggerObservable,
2532
params LightTransition[] lightTransitions)
2633
{
27-
return AddReactiveNode(c => c.AddCycle(triggerObservable, lightTransitions));
34+
return AddReactiveNode(c => c
35+
.SetLoggingContext(LogName, "Cycle", LoggingEnabled ?? false)
36+
.AddCycle(triggerObservable, lightTransitions));
2837
}
2938

3039
public ILightTransitionPipelineConfigurator<TLight> AddCycle<T>(IObservable<T> triggerObservable, Action<ILightTransitionCycleConfigurator<TLight>> configure)
3140
{
32-
return AddReactiveNode(c => c.AddCycle(triggerObservable, configure));
41+
return AddReactiveNode(c => c
42+
.SetLoggingContext(LogName, "Cycle", LoggingEnabled ?? false)
43+
.AddCycle(triggerObservable, configure));
3344
}
3445
}
Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using CodeCasa.AutomationPipelines.Lights.Extensions;
12
using CodeCasa.AutomationPipelines.Lights.Toggle;
23
using CodeCasa.Lights;
34

@@ -9,48 +10,62 @@ internal partial class CompositeLightTransitionPipelineConfigurator<TLight>
910
public ILightTransitionPipelineConfigurator<TLight> AddToggle<T>(IObservable<T> triggerObservable,
1011
IEnumerable<LightParameters> lightParameters)
1112
{
12-
return AddReactiveNode(c => c.AddToggle(triggerObservable, lightParameters));
13+
return AddReactiveNode(c => c
14+
.SetLoggingContext(LogName, "Toggle", LoggingEnabled ?? false)
15+
.AddToggle(triggerObservable, lightParameters));
1316
}
1417

1518
/// <inheritdoc/>
1619
public ILightTransitionPipelineConfigurator<TLight> AddToggle<T>(IObservable<T> triggerObservable,
1720
params LightParameters[] lightParameters)
1821
{
19-
return AddReactiveNode(c => c.AddToggle(triggerObservable, lightParameters));
22+
return AddReactiveNode(c => c
23+
.SetLoggingContext(LogName, "Toggle", LoggingEnabled ?? false)
24+
.AddToggle(triggerObservable, lightParameters));
2025
}
2126

2227
/// <inheritdoc/>
2328
public ILightTransitionPipelineConfigurator<TLight> AddToggle<T>(IObservable<T> triggerObservable,
2429
IEnumerable<LightTransition> lightTransitions)
2530
{
26-
return AddReactiveNode(c => c.AddToggle(triggerObservable, lightTransitions));
31+
return AddReactiveNode(c => c
32+
.SetLoggingContext(LogName, "Toggle", LoggingEnabled ?? false)
33+
.AddToggle(triggerObservable, lightTransitions));
2734
}
2835

2936
/// <inheritdoc/>
3037
public ILightTransitionPipelineConfigurator<TLight> AddToggle<T>(IObservable<T> triggerObservable,
3138
params LightTransition[] lightTransitions)
3239
{
33-
return AddReactiveNode(c => c.AddToggle(triggerObservable, lightTransitions));
40+
return AddReactiveNode(c => c
41+
.SetLoggingContext(LogName, "Toggle", LoggingEnabled ?? false)
42+
.AddToggle(triggerObservable, lightTransitions));
3443
}
3544

3645
/// <inheritdoc/>
3746
public ILightTransitionPipelineConfigurator<TLight> AddToggle<T>(IObservable<T> triggerObservable,
3847
IEnumerable<Func<IServiceProvider, IPipelineNode<LightTransition>>> nodeFactories)
3948
{
40-
return AddReactiveNode(c => c.AddToggle(triggerObservable, nodeFactories));
49+
return AddReactiveNode(c => c
50+
.SetLoggingContext(LogName, "Toggle", LoggingEnabled ?? false)
51+
.AddToggle(triggerObservable, nodeFactories));
4152
}
4253

4354
/// <inheritdoc/>
4455
public ILightTransitionPipelineConfigurator<TLight> AddToggle<T>(IObservable<T> triggerObservable,
4556
params Func<IServiceProvider, IPipelineNode<LightTransition>>[] nodeFactories)
4657
{
47-
return AddReactiveNode(c => c.AddToggle(triggerObservable, nodeFactories));
58+
return AddReactiveNode(c => c
59+
.SetLoggingContext(LogName, "Toggle", LoggingEnabled ?? false)
60+
.AddToggle(triggerObservable, nodeFactories));
4861
}
4962

5063
/// <inheritdoc/>
5164
public ILightTransitionPipelineConfigurator<TLight> AddToggle<T>(IObservable<T> triggerObservable,
5265
Action<ILightTransitionToggleConfigurator<TLight>> configure)
5366
{
54-
return AddReactiveNode(c => c.AddToggle(triggerObservable, configure));
67+
return AddReactiveNode(c => c
68+
.SetLoggingContext(LogName, "Toggle", LoggingEnabled ?? false)
69+
.AddToggle(triggerObservable, configure));
5570
}
5671
}

src/CodeCasa.AutomationPipelines.Lights/Pipeline/CompositeLightTransitionPipelineConfigurator.Switch.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ public ILightTransitionPipelineConfigurator<TLight> AddReactiveNodeSwitch(IObser
119119
Action<ILightTransitionReactiveNodeConfigurator<TLight>> falseConfigure, InstantiationScope instantiationScope = InstantiationScope.Shared)
120120
{
121121
return AddReactiveNode(c => c
122+
.SetLoggingContext(LogName, "Toggle", LoggingEnabled ?? false)
122123
.On(observable.Where(x => x), trueConfigure, instantiationScope)
123124
.On(observable.Where(x => !x), falseConfigure, instantiationScope));
124125
}
@@ -140,8 +141,9 @@ public ILightTransitionPipelineConfigurator<TLight> AddPipelineSwitch(IObservabl
140141
Action<ILightTransitionPipelineConfigurator<TLight>> falseConfigure, InstantiationScope instantiationScope = InstantiationScope.Shared)
141142
{
142143
return AddReactiveNode(c => c
143-
.On(observable.Where(x => x), trueConfigure, instantiationScope)
144-
.On(observable.Where(x => !x), falseConfigure, instantiationScope));
144+
.SetLoggingContext(LogName, "Switch", LoggingEnabled ?? false)
145+
.On(observable.Where(x => x), trueConfigure.SetLoggingContext(c), instantiationScope)
146+
.On(observable.Where(x => !x), falseConfigure.SetLoggingContext(c), instantiationScope));
145147
}
146148

147149
/// <inheritdoc/>

src/CodeCasa.AutomationPipelines.Lights/Pipeline/CompositeLightTransitionPipelineConfigurator.When.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,8 @@ public ILightTransitionPipelineConfigurator<TLight> AddReactiveNodeWhen<TObserva
117117
public ILightTransitionPipelineConfigurator<TLight> AddReactiveNodeWhen(IObservable<bool> observable, Action<ILightTransitionReactiveNodeConfigurator<TLight>> configure, InstantiationScope instantiationScope = InstantiationScope.Shared)
118118
{
119119
return AddReactiveNode(c => c
120-
.On(observable.Where(x => x), configure, instantiationScope)
120+
.SetLoggingContext(LogName, "Conditional", LoggingEnabled ?? false)
121+
.On(observable.Where(x => x), configure.SetLoggingContext(c), instantiationScope)
121122
.PassThroughOn(observable.Where(x => !x)));
122123
}
123124

@@ -132,7 +133,8 @@ public ILightTransitionPipelineConfigurator<TLight> AddPipelineWhen<TObservable>
132133
public ILightTransitionPipelineConfigurator<TLight> AddPipelineWhen(IObservable<bool> observable, Action<ILightTransitionPipelineConfigurator<TLight>> configure, InstantiationScope instantiationScope = InstantiationScope.Shared)
133134
{
134135
return AddReactiveNode(c => c
135-
.On(observable.Where(x => x), configure, instantiationScope)
136+
.SetLoggingContext(LogName, "Conditional", LoggingEnabled ?? false)
137+
.On(observable.Where(x => x), configure.SetLoggingContext(c), instantiationScope)
136138
.PassThroughOn(observable.Where(x => !x)));
137139
}
138140

src/CodeCasa.AutomationPipelines.Lights/Pipeline/CompositeLightTransitionPipelineConfigurator.cs

Lines changed: 6 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,6 @@ internal partial class CompositeLightTransitionPipelineConfigurator<TLight>(
1818
{
1919
public Dictionary<string, LightTransitionPipelineConfigurator<TLight>> NodeContainers { get; } = nodeContainers;
2020

21-
/// <inheritdoc/>
22-
public ILightTransitionPipelineConfigurator<TLight> EnableLogging(string? pipelineName = null)
23-
{
24-
NodeContainers.Values.ForEach(b => b.EnableLogging(pipelineName));
25-
return this;
26-
}
27-
28-
/// <inheritdoc/>
29-
public ILightTransitionPipelineConfigurator<TLight> DisableLogging()
30-
{
31-
NodeContainers.Values.ForEach(b => b.DisableLogging());
32-
return this;
33-
}
34-
3521
/// <inheritdoc/>
3622
public ILightTransitionPipelineConfigurator<TLight> AddNode<TNode>() where TNode : IPipelineNode<LightTransition>
3723
{
@@ -51,25 +37,15 @@ public ILightTransitionPipelineConfigurator<TLight> AddReactiveNode(
5137
Action<ILightTransitionReactiveNodeConfigurator<TLight>> configure)
5238
{
5339
var nodes = reactiveNodeFactory.CreateReactiveNodes(NodeContainers.Select(nc => nc.Value.Light),
54-
c =>
55-
{
56-
var firstContainer = NodeContainers.Values.First();
57-
if (firstContainer.Log ?? false)
58-
{
59-
// If logging is enabled, enable it on the reactive node configurator by default.
60-
c.EnableLogging($"Reactive Node in {firstContainer.Name ?? "light group"}");
61-
}
62-
configure(c);
63-
});
40+
configure.SetLoggingContext(LogName, LoggingEnabled ?? false));
6441
NodeContainers.ForEach(kvp => kvp.Value.AddNode(nodes[kvp.Key]));
6542
return this;
6643
}
6744

6845
/// <inheritdoc/>
69-
public ILightTransitionPipelineConfigurator<TLight> AddPipeline(Action<ILightTransitionPipelineConfigurator<TLight>> pipelineNodeOptions)
46+
public ILightTransitionPipelineConfigurator<TLight> AddPipeline(Action<ILightTransitionPipelineConfigurator<TLight>> configure)
7047
{
71-
var pipelines = lightPipelineFactory.CreateLightPipelines(NodeContainers.Select(c => c.Value.Light),
72-
pipelineNodeOptions);
48+
var pipelines = lightPipelineFactory.CreateLightPipelines(NodeContainers.Select(c => c.Value.Light), configure.SetLoggingContext(LogName, LoggingEnabled ?? false));
7349
NodeContainers.ForEach(kvp => kvp.Value.AddNode(pipelines[kvp.Key]));
7450
return this;
7551
}
@@ -83,10 +59,9 @@ public ILightTransitionPipelineConfigurator<TLight> AddDimmer(IDimmer dimmer)
8359
/// <inheritdoc/>
8460
public ILightTransitionPipelineConfigurator<TLight> AddDimmer(IDimmer dimmer, Action<DimmerOptions> dimOptions)
8561
{
86-
return AddReactiveNode(c =>
87-
{
88-
c.AddUncoupledDimmer(dimmer, dimOptions);
89-
});
62+
return AddReactiveNode(c => c
63+
.SetLoggingContext(LogName, "Dimmer", LoggingEnabled ?? false)
64+
.AddUncoupledDimmer(dimmer, dimOptions));
9065
}
9166

9267
/// <inheritdoc/>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
namespace CodeCasa.AutomationPipelines.Lights.Pipeline;
2+
3+
public partial interface ILightTransitionPipelineConfigurator<TLight>
4+
{
5+
/// <summary>
6+
/// Enables logging for the pipeline configuration.
7+
/// </summary>
8+
/// <param name="pipelineName">The optional name of the pipeline to include in logs.</param>
9+
/// <returns>The configurator instance for method chaining.</returns>
10+
ILightTransitionPipelineConfigurator<TLight> EnableLogging(string? pipelineName = null);
11+
12+
/// <summary>
13+
/// Disables logging for the pipeline configuration.
14+
/// </summary>
15+
/// <returns>The configurator instance for method chaining.</returns>
16+
ILightTransitionPipelineConfigurator<TLight> DisableLogging();
17+
}

0 commit comments

Comments
 (0)