Skip to content
This repository was archived by the owner on Jan 3, 2023. It is now read-only.

Commit 24422d9

Browse files
committed
adding debug flag for logging and catching more errors.
1 parent 4f15277 commit 24422d9

File tree

3 files changed

+152
-78
lines changed

3 files changed

+152
-78
lines changed

CacheInitializer.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
55
<TargetFramework>netcoreapp3.1</TargetFramework>
6+
<Copyright>EA Americas</Copyright>
7+
<Description>This tool pre-loads Qlik Sense applications in a QSEoW environment.</Description>
8+
<Version>1.0.0</Version>
69
</PropertyGroup>
710

811
<ItemGroup>

ParamHandler.cs

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,39 +8,33 @@ namespace CacheInitializer
88
// Define a class to receive parsed values
99
class Options
1010
{
11+
[Option('s', "server", Required = true, HelpText = "URL to the server.")]
12+
public string Server { get; set; }
1113

12-
[Option('s', "server", Required = true,
13-
HelpText = "URL to the server.")]
14-
public string server { get; set; }
14+
[Option('a', "appname", Required = false, HelpText = "App to load (using app name)")]
15+
public string AppName { get; set; }
1516

16-
[Option('a', "appname", Required = false,
17-
HelpText = "App to load (using app name)")]
18-
public string appname { get; set; }
17+
[Option('i', "appid", Required = false, HelpText = "App to load (using app ID)")]
18+
public string AppID { get; set; }
1919

20-
[Option('i', "appid", Required = false,
21-
HelpText = "App to load (using app ID)")]
22-
public string appid { get; set; }
20+
[Option('p', "proxy", Required = false, HelpText = "Virtual Proxy to use")]
21+
public string VirtualProxy { get; set; }
2322

24-
[Option('p', "proxy", Required = false,
25-
HelpText = "Virtual Proxy to use")]
26-
public string virtualProxy { get; set; }
23+
[Option('o', "objects", Required = false, Default = false, HelpText = "cycle through all sheets and objects")]
24+
public bool FetchObjects { get; set; }
2725

28-
[Option('o', "objects", Required = false, Default = false,
29-
HelpText = "cycle through all sheets and objects")]
30-
public bool fetchobjects { get; set; }
26+
[Option('f', "field", Required = false, HelpText = "field to make selections in e.g Region")]
27+
public string SelectionField { get; set; }
3128

32-
[Option('f', "field", Required = false,
33-
HelpText = "field to make selections in e.g Region")]
34-
public string selectionfield { get; set; }
29+
[Option('v', "values", Required = false, HelpText = "values to select e.g \"France\",\"Germany\",\"Spain\"")]
30+
public string SelectionValues { get; set; }
3531

36-
[Option('v', "values", Required = false,
37-
HelpText = "values to select e.g \"France\",\"Germany\",\"Spain\"")]
38-
public string selectionvalues { get; set; }
32+
[Option('d', "debug", Required = false, HelpText = "Run with logging set to debug.")]
33+
public bool Debug { get; set; }
3934

4035
static void DisplayHelp<T>(ParserResult<T> result, IEnumerable<Error> errs)
4136
{
42-
var helpText = HelpText.AutoBuild(result,
43-
(current) => HelpText.DefaultParsingErrorsHandler(result, current));
37+
var helpText = HelpText.AutoBuild(result, (current) => HelpText.DefaultParsingErrorsHandler(result, current));
4438
Console.WriteLine(helpText);
4539
}
4640
}

Program.cs

Lines changed: 132 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,21 @@
2424

2525
namespace CacheInitializer
2626
{
27+
internal enum LogLevel
28+
{
29+
Info,
30+
Debug
31+
}
32+
33+
internal class QlikSelection
34+
{
35+
public string fieldname { get; set; }
36+
public string[] fieldvalues { get; set; }
37+
}
38+
2739
class Program
2840
{
41+
private static bool DEBUG_MODE = false;
2942

3043
static void Main(string[] args)
3144
{
@@ -55,28 +68,40 @@ private static void DoWork(Options options)
5568
string virtualProxy;
5669
QlikSelection mySelection = null;
5770

71+
ILocation remoteQlikSenseLocation = null;
5872

5973
try
6074
{
61-
serverURL = new Uri(options.server);
62-
appname = options.appname;
63-
appid = options.appid;
64-
virtualProxy = !string.IsNullOrEmpty(options.virtualProxy) ? options.virtualProxy : "";
65-
openSheets = options.fetchobjects;
66-
if (options.selectionfield != null)
75+
if (options.Debug)
76+
{
77+
DEBUG_MODE = true;
78+
Print(LogLevel.Debug, "Debug logging enabled.");
79+
80+
}
81+
Print(LogLevel.Debug, "setting parameter values in main");
82+
serverURL = new Uri(options.Server);
83+
appname = options.AppName;
84+
appid = options.AppID;
85+
virtualProxy = !string.IsNullOrEmpty(options.VirtualProxy) ? options.VirtualProxy : "";
86+
openSheets = options.FetchObjects;
87+
if (options.SelectionField != null)
6788
{
6889
mySelection = new QlikSelection();
69-
mySelection.fieldname = options.selectionfield;
70-
mySelection.fieldvalues = options.selectionvalues.Split(',');
90+
mySelection.fieldname = options.SelectionField;
91+
mySelection.fieldvalues = options.SelectionValues.Split(',');
7192
}
7293
//TODO need to validate the params ideally
7394

95+
Print(LogLevel.Debug, "setting remoteQlikSenseLocation"); ;
96+
7497
////connect to the server (using windows credentials
7598
QlikConnection.Timeout = Int32.MaxValue;
7699
var d = DateTime.Now;
77100

78-
ILocation remoteQlikSenseLocation = Qlik.Engine.Location.FromUri(serverURL);
101+
remoteQlikSenseLocation = Qlik.Engine.Location.FromUri(serverURL);
79102

103+
104+
Print(LogLevel.Debug, "validating http(s) and virtual proxy"); ;
80105
if (virtualProxy.Length > 0)
81106
{
82107
remoteQlikSenseLocation.VirtualProxyPath = virtualProxy;
@@ -88,14 +113,17 @@ private static void DoWork(Options options)
88113
}
89114
remoteQlikSenseLocation.AsNtlmUserViaProxy(isHTTPs, null, false);
90115

116+
Print(LogLevel.Debug, "starting to cache applications");
91117
////Start to cache the apps
92118
IAppIdentifier appIdentifier = null;
93119

94120
if (appid != null)
95121
{
96122
//Open up and cache one app, based on app ID
97123
appIdentifier = remoteQlikSenseLocation.AppWithId(appid);
124+
Print(LogLevel.Debug, "got app identifier by ID");
98125
LoadCache(remoteQlikSenseLocation, appIdentifier, openSheets, mySelection);
126+
Print(LogLevel.Debug, "finished caching by ID");
99127

100128
}
101129
else
@@ -104,87 +132,134 @@ private static void DoWork(Options options)
104132
{
105133
//Open up and cache one app
106134
appIdentifier = remoteQlikSenseLocation.AppWithNameOrDefault(appname);
135+
Print(LogLevel.Debug, "got app identifier by name");
107136
LoadCache(remoteQlikSenseLocation, appIdentifier, openSheets, mySelection);
137+
Print(LogLevel.Debug, "finished caching by name");
108138
}
109139
else
110140
{
111141
//Get all apps, open them up and cache them
112142
remoteQlikSenseLocation.GetAppIdentifiers().ToList().ForEach(id => LoadCache(remoteQlikSenseLocation, id, openSheets, null));
143+
Print(LogLevel.Debug, "finished caching all applications");
113144
}
114145
}
115146

116147

117148
////Wrap it up
118149
var dt = DateTime.Now - d;
119-
Print("Cache initialization complete. Total time: {0}", dt.ToString());
150+
Print(LogLevel.Info, "Cache initialization complete. Total time: {0}", dt.ToString());
120151
remoteQlikSenseLocation.Dispose();
152+
Print(LogLevel.Debug, "done");
153+
121154
return;
122155
}
123156
catch (UriFormatException)
124157
{
125-
Print("Invalid server paramater format. Format must be http[s]://host.domain.tld.");
158+
Print(LogLevel.Info, "Invalid server paramater format. Format must be http[s]://host.domain.tld.");
159+
return;
126160
}
127161
catch (WebSocketException webEx)
128162
{
129-
Print("Unable to connect to establish WebSocket connection with: " + options.server);
130-
Print("Error: " + webEx.Message);
163+
if (remoteQlikSenseLocation != null)
164+
{
165+
Print(LogLevel.Info, "Disposing remoteQlikSenseLocation");
166+
remoteQlikSenseLocation.Dispose();
167+
}
168+
169+
Print(LogLevel.Info, "Unable to connect to establish WebSocket connection with: " + options.Server);
170+
Print(LogLevel.Info, "Error: " + webEx.Message);
171+
172+
return;
173+
}
174+
catch (TimeoutException timeoutEx)
175+
{
176+
Print(LogLevel.Info, "Timeout Exception - Unable to connect to: " + options.Server);
177+
Print(LogLevel.Info, "Error: " + timeoutEx.Message);
178+
179+
return;
180+
}
181+
catch (Exception ex)
182+
{
183+
if (ex.Message.Trim() == "Websocket closed unexpectedly (EndpointUnavailable):")
184+
{
185+
Print(LogLevel.Info, "Error: licenses exhausted.");
186+
return;
187+
}
188+
else
189+
{
190+
Print(LogLevel.Info, "Unexpected error.");
191+
Print(LogLevel.Info, "Message: " + ex.Message);
131192

193+
return;
194+
}
132195
}
133196
}
134197

135198
static void LoadCache(ILocation location, IAppIdentifier id, bool opensheets, QlikSelection Selections)
136199
{
137-
//open up the app
138-
Print("{0}: Opening app", id.AppName);
139-
IApp app = location.App(id);
140-
Print("{0}: App open", id.AppName);
141-
142-
//see if we are going to open the sheets too
143-
if (opensheets)
200+
IApp app = null;
201+
try
144202
{
145-
//see of we are going to make some selections too
146-
if (Selections != null)
203+
//open up the app
204+
Print(LogLevel.Info, "{0}: Opening app", id.AppName);
205+
app = location.App(id);
206+
Print(LogLevel.Info, "{0}: App open", id.AppName);
207+
208+
//see if we are going to open the sheets too
209+
if (opensheets)
147210
{
148-
for (int i = 0; i < Selections.fieldvalues.Length; i++)
211+
//see of we are going to make some selections too
212+
if (Selections != null)
149213
{
150-
//clear any existing selections
151-
Print("{0}: Clearing Selections", id.AppName);
214+
for (int i = 0; i < Selections.fieldvalues.Length; i++)
215+
{
216+
//clear any existing selections
217+
Print(LogLevel.Info, "{0}: Clearing Selections", id.AppName);
218+
app.ClearAll(true);
219+
//apply the new selections
220+
Print(LogLevel.Info, "{0}: Applying Selection: {1} = {2}", id.AppName, Selections.fieldname, Selections.fieldvalues[i]);
221+
app.GetField(Selections.fieldname).Select(Selections.fieldvalues[i]);
222+
//cache the results
223+
cacheObjects(app, location, id);
224+
}
225+
226+
}
227+
else
228+
{
229+
//clear any selections
230+
Print(LogLevel.Info, "{0}: Clearing Selections", id.AppName);
152231
app.ClearAll(true);
153-
//apply the new selections
154-
Print("{0}: Applying Selection: {1} = {2}", id.AppName, Selections.fieldname, Selections.fieldvalues[i]);
155-
app.GetField(Selections.fieldname).Select(Selections.fieldvalues[i]);
156232
//cache the results
157233
cacheObjects(app, location, id);
158234
}
159-
160235
}
161-
else
236+
237+
Print(LogLevel.Info, "{0}: App cache completed", id.AppName);
238+
app.Dispose();
239+
}
240+
catch (Exception ex)
241+
{
242+
if (app != null)
162243
{
163-
//clear any selections
164-
Print("{0}: Clearing Selections", id.AppName);
165-
app.ClearAll(true);
166-
//cache the results
167-
cacheObjects(app, location, id);
244+
app.Dispose();
168245
}
246+
throw ex;
169247
}
170-
171-
Print("{0}: App cache completed", id.AppName);
172-
app.Dispose();
173248
}
174249

175250
static void cacheObjects(IApp app, ILocation location, IAppIdentifier id)
176251
{
177252
//get a list of the sheets in the app
178-
Print("{0}: Getting sheets", id.AppName);
253+
Print(LogLevel.Info, "{0}: Getting sheets", id.AppName);
179254
var sheets = app.GetSheets().ToArray();
180255
//get a list of the objects in the app
181-
Print("{0}: Number of sheets - {1}, getting children", id.AppName, sheets.Count());
256+
Print(LogLevel.Info, "{0}: Number of sheets - {1}, getting children", id.AppName, sheets.Count());
182257
IGenericObject[] allObjects = sheets.Concat(sheets.SelectMany(sheet => GetAllChildren(app, sheet))).ToArray();
183258
//draw the layout of all objects so the server calculates the data for them
184-
Print("{0}: Number of objects - {1}, caching all objects", id.AppName, allObjects.Count());
259+
Print(LogLevel.Info, "{0}: Number of objects - {1}, caching all objects", id.AppName, allObjects.Count());
185260
var allLayoutTasks = allObjects.Select(o => o.GetLayoutAsync()).ToArray();
186261
Task.WaitAll(allLayoutTasks);
187-
Print("{0}: Objects cached", id.AppName);
262+
Print(LogLevel.Info, "{0}: Objects cached", id.AppName);
188263
}
189264

190265
private static IEnumerable<IGenericObject> GetAllChildren(IApp app, IGenericObject obj)
@@ -193,23 +268,25 @@ private static IEnumerable<IGenericObject> GetAllChildren(IApp app, IGenericObje
193268
return children.Concat(children.SelectMany(child => GetAllChildren(app, child)));
194269
}
195270

196-
private static void Print(string txt)
271+
private static void Print(LogLevel level, string txt)
197272
{
198-
Console.WriteLine("{0} - {1}", DateTime.Now.ToString("hh:mm:ss"), txt);
273+
if (level == LogLevel.Info)
274+
{
275+
Console.WriteLine("{0} - {1}", DateTime.Now.ToString("hh:mm:ss"), txt);
276+
}
277+
else if (level == LogLevel.Debug && DEBUG_MODE)
278+
{
279+
Console.WriteLine("DEBUG\t{0} - {1}", DateTime.Now.ToString("hh:mm:ss"), txt);
280+
}
281+
else
282+
{
283+
throw new ArgumentException("Invalid LogLevel specified.");
284+
}
199285
}
200286

201-
private static void Print(string txt, params object[] os)
287+
private static void Print(LogLevel level, string txt, params object[] os)
202288
{
203-
Print(String.Format(txt, os));
289+
Print(level, String.Format(txt, os));
204290
}
205-
206-
207291
}
208-
209-
class QlikSelection
210-
{
211-
public string fieldname { get; set; }
212-
public string[] fieldvalues { get; set; }
213-
}
214-
215292
}

0 commit comments

Comments
 (0)