2525using Sharphound . Client ;
2626using SharpHoundCommonLib ;
2727using SharpHoundCommonLib . Enums ;
28+ using SharpHoundCommonLib . Models ;
29+ using SharpHoundCommonLib . Services ;
30+ using SharpHoundCommonLib . Static ;
2831
2932namespace Sharphound
3033{
@@ -36,6 +39,8 @@ namespace Sharphound
3639 #region Console Entrypoint
3740
3841 public class Program {
42+ private static MetricsFlushTimer _flushTimer ;
43+
3944 public static async Task Main ( string [ ] args ) {
4045 var logger = new BasicLogger ( ( int ) LogLevel . Information ) ;
4146 logger . LogInformation ( "This version of SharpHound is compatible with the 5.0.0 Release of BloodHound" ) ;
@@ -88,7 +93,8 @@ await options.WithParsedAsync(async options =>
8893 SearchForest = options . SearchForest ,
8994 RecurseDomains = options . RecurseDomains ,
9095 DoLocalAdminSessionEnum = options . DoLocalAdminSessionEnum ,
91- ParititonLdapQueries = options . PartitionLdapQueries
96+ ParititonLdapQueries = options . PartitionLdapQueries ,
97+ Metrics = options . Metrics ,
9298 } ;
9399
94100 var ldapOptions = new LdapConfig
@@ -149,10 +155,44 @@ await options.WithParsedAsync(async options =>
149155 }
150156 }
151157
158+ if ( flags . Metrics ) {
159+ var metricsRegistry = new MetricRegistry ( ) ;
160+ metricsRegistry . RegisterDefaultMetrics ( ) ;
161+ metricsRegistry . Seal ( ) ;
162+
163+ var fileSinkOptions = new FileMetricSinkOptions {
164+ FlushInterval = TimeSpan . FromSeconds ( 5 ) ,
165+ } ;
166+
167+ var metricsWriter = new MetricWriter ( ) ;
168+
169+ var metricsFileName = string . IsNullOrEmpty ( options . OutputPrefix ) ? "metrics.log" : $ "{ options . OutputPrefix } _metrics.log";
170+ var metricsFilePath = System . IO . Path . Combine ( options . OutputDirectory , metricsFileName ) ;
171+
172+ var fileSink = new FileMetricSink (
173+ metricsRegistry . Definitions ,
174+ filePath : metricsFilePath ,
175+ metricsWriter ,
176+ fileSinkOptions ) ;
177+
178+ var metricsRouter = new MetricRouter (
179+ metricsRegistry . Definitions ,
180+ [ fileSink ] ,
181+ new DefaultLabelValuesCache ( ) ) ;
182+
183+ Metrics . Factory = new MetricFactory ( metricsRouter ) ;
184+
185+ _flushTimer = new MetricsFlushTimer (
186+ flush : metricsRouter . Flush ,
187+ interval : fileSinkOptions . FlushInterval ) ;
188+
189+ }
190+
152191 await StartCollection ( options , logger , resolved , flags , ldapOptions ) ;
153192 } ) ;
154193 } catch ( Exception ex ) {
155194 logger . LogError ( $ "Error running SharpHound: { ex . Message } \n { ex . StackTrace } ") ;
195+ _flushTimer ? . Dispose ( ) ;
156196 }
157197 }
158198
@@ -214,6 +254,7 @@ private static async Task StartCollection(Options options, BasicLogger logger, C
214254 context = await links . AwaitLoopCompletion ( context ) ;
215255 context = links . SaveCacheFile ( context ) ;
216256 links . Finish ( context ) ;
257+ _flushTimer ? . Dispose ( ) ;
217258 }
218259
219260 // Accessor function for the PS1 to work, do not change or remove
0 commit comments