1+ // Copyright © Datalust Pty Ltd
2+ //
3+ // Licensed under the Apache License, Version 2.0 (the "License");
4+ // you may not use this file except in compliance with the License.
5+ // You may obtain a copy of the License at
6+ //
7+ // http://www.apache.org/licenses/LICENSE-2.0
8+ //
9+ // Unless required by applicable law or agreed to in writing, software
10+ // distributed under the License is distributed on an "AS IS" BASIS,
11+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+ // See the License for the specific language governing permissions and
13+ // limitations under the License.
14+
15+ using System ;
16+ using System . Collections . Generic ;
17+ using System . Globalization ;
18+ using System . Linq ;
19+ using System . Threading . Tasks ;
20+ using Seq . Api . Model . Data ;
21+ using SeqCli . Api ;
22+ using SeqCli . Cli . Features ;
23+ using SeqCli . Config ;
24+ using SeqCli . Util ;
25+ using Serilog ;
26+
27+ namespace SeqCli . Cli . Commands . Metrics ;
28+
29+ [ Command ( "metrics" , "search" , "List available metric definitions" ,
30+ Example = "seqcli metrics search -f \" @Resource.service.name = 'proxy'\" -c 512" ) ]
31+ class SearchCommand : Command
32+ {
33+ readonly ConnectionFeature _connection ;
34+ readonly OutputFormatFeature _output ;
35+ readonly DateRangeFeature _range ;
36+ readonly StoragePathFeature _storagePath ;
37+ string ? _filter ;
38+ readonly List < string > _groups = [ ] ;
39+ int _count = 30 ;
40+ bool _trace ;
41+
42+ public SearchCommand ( )
43+ {
44+ Options . Add (
45+ "f=|filter=" ,
46+ "A filter to apply to the search, including metric name/description text in double quotes, for example `\" cpu\" and Host = 'xmpweb-01.example.com'`" ,
47+ v => _filter = v ) ;
48+
49+ Options . Add (
50+ "g=|group=" ,
51+ "Group key for metric definition breakdown; this argument can be used multiple times" ,
52+ c => _groups . Add ( ArgumentString . Normalize ( c ) ?? throw new ArgumentException ( "Group keys require a value." ) ) ) ;
53+
54+ Options . Add (
55+ "c=|count=" ,
56+ $ "The maximum number of metric definitions to retrieve; the default is { _count } ",
57+ v => _count = int . Parse ( v , CultureInfo . InvariantCulture ) ) ;
58+
59+ _range = Enable < DateRangeFeature > ( ) ;
60+ // Native is not supported because accessor expressions appear in the output, and the escaping applied to them
61+ // as native strings does more harm than good.
62+ _output = Enable < OutputFormatFeature > ( ) ;
63+ _storagePath = Enable < StoragePathFeature > ( ) ;
64+
65+ Options . Add ( "trace" , "Enable detailed (server-side) query tracing" , _ => _trace = true ) ;
66+
67+ _connection = Enable < ConnectionFeature > ( ) ;
68+ }
69+
70+ protected override async Task < int > Run ( )
71+ {
72+ try
73+ {
74+ var config = RuntimeConfigurationLoader . Load ( _storagePath ) ;
75+ var output = _output . GetOutputFormat ( config ) ;
76+ var connection = SeqConnectionFactory . Connect ( _connection , config ) ;
77+
78+ string ? filter = null ;
79+ if ( ! string . IsNullOrWhiteSpace ( _filter ) )
80+ filter = ( await connection . Expressions . ToStrictAsync ( _filter ) ) . StrictExpression ;
81+
82+ var result = await connection . Metrics . SearchAsync (
83+ _groups ,
84+ filter ,
85+ _count ,
86+ rangeStartUtc : _range . Start ,
87+ rangeEndUtc : _range . End ,
88+ trace : _trace ) ;
89+
90+ // We convert the metric into a query result to improve formatting consistency. Room for an abstraction of
91+ // some kind here.
92+ var rows = new List < object ? [ ] > ( ) ;
93+ foreach ( var metric in result . Metrics )
94+ {
95+ var row = new List < object ? >
96+ {
97+ metric . Name ?? metric . Accessor ,
98+ metric . Kind ,
99+ metric . Unit ,
100+ metric . Description
101+ } ;
102+
103+ foreach ( var value in metric . GroupKey )
104+ row . Add ( value ) ;
105+
106+ rows . Add ( row . ToArray ( ) ) ;
107+ }
108+ var asRowset = new QueryResultPart
109+ {
110+ Columns = new [ ] { "Name" , "Kind" , "Unit" , "Description" } . Concat ( _groups ) . ToArray ( ) ,
111+ Rows = rows . ToArray ( )
112+ } ;
113+
114+ output . WriteQueryResult ( asRowset ) ;
115+
116+ return 0 ;
117+ }
118+ catch ( Exception ex )
119+ {
120+ Log . Error ( ex , "Could not retrieve metrics: {ErrorMessage}" , ex . Message ) ;
121+ return 1 ;
122+ }
123+ }
124+ }
0 commit comments