Záznam z interního vzdělávacího okénka HAVIT z 11.1.2018 je publikován na našem HAVIT YouTube Channel. Téma prezentoval Pavel Kříž.
Modulární CSS – záznam [Vít Heřman, HAVIT Vzdělávací okénko 4.1.2018]
Záznam z interního vzdělávacího okénka HAVIT z 4.1.2018 je publikován na našem HAVIT YouTube Channel. Téma prezentoval Vít Heřman.
Dotčená témata:
- CSS Zen Garden
- Klasický přístup k CSS vs. Modulární přístup
- OOCSS – Object Oriented CSS
Perly z codereview [Jiří Kanda, HAVIT Vzdělávací okénko 21.12.2017]
Záznam z interního vzdělávacího okénka HAVIT ze 21.12.2017 je publikován na našem HAVIT YouTube Channel. Téma prezentoval Jiří Kandal:
Jak jsme psali jednu stránku dva měsíce, aneb můj výlet do světa Javascriptu – promítání s diapozitivy [Martin Havel, HAVIT Vzdělávací okénko 13.12.2017]
Záznam z interního vzdělávacího okénka HAVIT ze 13.12.2017 je publikován na našem HAVIT YouTube Channel. Téma prezentoval Martin Havel:
Dotčená témata:
- React
- Flow
- ImmutableJS
- Moment
Poznámka: Část prezentace (ukázka výsledku práce) byla z důvodu ochrany zákazníka ze záznamu vystřižena.
SQL Query Store: Porovnání dvou období (počty spuštění dotazů, trvání)
Query Store je užitečnou novinkou v Azure SQL, resp. Microsoft SQL Server 2016+. Ukládá užitečné statistiky o spuštěných dotazech, jejich execution planech a mnoho dalšího. (Umí dokonce vynutit používání konkrétního execution planu a dokonce toto řešit automaticky, pokud detekuje výkonovou regresi. O tom ale někdy jindy.)
Jeden ze scénářů, který vám může být užitečný, je porovnání dvou období co se počtu spuštění jednotlivých dotazů týče, jejich průměrné doby trvání, atp. Hodit se to může při nenadálých poklesech výkonnosti, po nasazení nových verzí aplikací, atp.:
DECLARE @Period1Start datetime, @Period1End datetime, @Period2Start datetime, @Period2End datetime SET @Period1Start = '20171212 00:00' SET @Period1End = '20171213 00:00' SET @Period2Start = '20171214 00:00' SET @Period2End = '20171215 00:00' ;WITH period1 AS ( SELECT query_id, AVG(avg_duration) AS avg_duration, SUM(count_executions) AS count_executions_total FROM sys.query_store_runtime_stats INNER JOIN sys.query_store_runtime_stats_interval ON (query_store_runtime_stats_interval.runtime_stats_interval_id = query_store_runtime_stats.runtime_stats_interval_id) INNER JOIN sys.query_store_plan ON query_store_plan.plan_id = query_store_runtime_stats.plan_id WHERE (sys.query_store_runtime_stats_interval.start_time >= @Period1Start) AND (sys.query_store_runtime_stats_interval.end_time <= @Period1End) GROUP BY query_id ), period2 AS ( SELECT query_id, AVG(avg_duration) AS avg_duration, SUM(count_executions) AS count_executions_total FROM sys.query_store_runtime_stats INNER JOIN sys.query_store_runtime_stats_interval ON (query_store_runtime_stats_interval.runtime_stats_interval_id = query_store_runtime_stats.runtime_stats_interval_id) INNER JOIN sys.query_store_plan ON query_store_plan.plan_id = query_store_runtime_stats.plan_id WHERE (sys.query_store_runtime_stats_interval.start_time >= @Period2Start) AND (sys.query_store_runtime_stats_interval.end_time <= @Period2End) GROUP BY query_id ) SELECT query_store_query.query_id, period1.avg_duration AS period1_avg_duration, period2.avg_duration AS period2_avg_duration, CASE WHEN period1.count_executions_total IS NOT NULL THEN (period2.avg_duration - period1.avg_duration) * 100.0 / period1.avg_duration ELSE NULL END AS avg_duration_increase_percent, period1.count_executions_total AS period1_count_executions_total, period2.count_executions_total AS period2_count_executions_total, CASE WHEN period1.count_executions_total IS NOT NULL THEN (period2.count_executions_total - period1.count_executions_total) * 100.0 / period1.count_executions_total ELSE NULL END AS count_execution_increase_percent, query_sql_text FROM period2 LEFT JOIN period1 ON period1.query_id = period2.query_id LEFT JOIN sys.query_store_query ON query_store_query.query_id = period2.query_id LEFT JOIN sys.query_store_query_text ON query_store_query_text.query_text_id = query_store_query.query_text_id --ORDER BY period2.count_executions_total DESC ORDER BY count_execution_increase_percent DESC --ORDER BY avg_duration_increase_percent DESC
References
Programátorská hádanka: Exceptions
Co bude výstupem?
try
{
try
{
throw new Exception("A");
}
catch
{
throw new Exception("B");
}
finally
{
throw new Exception("C");
}
}
catch (Exception ex)
{
Console.Write(ex.Message);
}
Výsledek: https://dotnetfiddle.net/6SWPqL
Quartz.NET, Castle Windsor – LifeStyle Per Job (Scoped)
Pokud používáte Quartz.NET (známá knihovna pro job-scheduling) s Castle Windsor (IoC/DI container), možná jste narazili na potřebu registrovat komponentu s životním cyklem „per job“ (LifestylePerJob). Na internetu najdete několik možností, které mají jedno společné – nefungují:
- LifestylePerThread – neresetuje thread mezi joby, komponenta se použije pro více jobů
- BoundTo<Job>() – nepodporuje typed factories, pokud si z nich vyžádáte službu v jobu
- BoundTo<object>() – nepodporuje typed factories, pokud si z nich vyžádáte službu v jobu
- Quartz.IJobFactory + LifestyleScoped – nepodporuje typed factories, pokud si z nich vyžádáte službu v jobu (scope odstartovaný v JobFactory se nezpropaguje do jobu!)
Naštěstí existuje „jednoduché“ řešení. Můžete použít LifestyleScoped, ale je potřeba scope začít/ukončit uvnitř jobu.
Pokud použijete samotný job jenom jako plumbing class kde práce samotná je zapouzdřena do samostatné služby (a měli byste to tak mít tak jako tak), pak stačí do jobu nainjectovat factory k takové službě a kernel pro ovládání scope:
public class MyJob : IJob
{
private readonly IServiceFactory<myservice> myServiceFactory;
private readonly IKernel kernel;
public MyJob(IServiceFactory<myservice> myServiceFactory, IKernel kernel)
{
this.myServiceFactory = myServiceFactory;
this.kernel = kernel;
}
public void Execute()
{
using (var scope = kernel.BeginScope())
{
// use your way to work with factories ;-)
using (var myService = myServiceFactory.Create())
{
myService.DoWork();
}
// BTW: we have an extension method
myServiceFactory.ExecuteAction(service =&gt; service.DoWork());
}
}
}
…třída MyService class má všechny dependencies, které potřebuje a při použítí přes factory tím získáte nový pseudo-resolution-root. Svádí to samozřejmě použít rovnou kernel.Resolve+Release, ale nedělejte to… ;-)
References
Tip: Microsoft LogParser [Studio] – rychlé SQL dotazování do textových log-souborů
LogParser (download) je command-line utilita od Microsoftu, kterou můžete použít pro SQL-styl dotazování do libovolného textového log-souboru, resp. i mnoha souborů zároveň. Základní sada podporovaných formátů je úctyhodná: IISW3C, NCSA, IIS, IISODBC, BIN, IISMSID, HTTPERR, URLSCAN, CSV, TSV, W3C, XML, EVT, ETW, NETMON, REG, ADS, TEXTLINE, TEXTWORD, FS a COM.
Já ho používám obvykle pro dotazování IIS Logů a musím říct, že je neuskutečně rychlý. Na mém notebooku Lenovo X1 i7/16GB/SSD je schopen vyřešit následující dotaz do 8.97GB logů za 2min 12sec!
SELECT
Date,
TO_INT(COALESCE(EXTRACT_VALUE(cs-uri-query, 'id'), EXTRACT_VALUE(cs-uri-query, 'SouborSablonyID'))) AS SouborID,
COUNT(*) AS Total
FROM '[LOGFILEPATH]'
WHERE (cs-uri-stem = '/business/sablony/soubor-partner.aspx') OR (cs-uri-stem = '/business/sablony/soubor.aspx')
GROUP BY Date, SouborID
ORDER BY Total DESC
Výstup do databáze
LogParser umí nejenom vyhodnocovat dotazy, ale můžete jeho výsledky nasměrovat i do databáze či mnoha dalších výstupních formátů (CSV, XML, …), např.
C:\Program Files (x86)\Log Parser 2.2>logparser "SELECT * INTO iisLogs FROM c:\temp\logs\*.log" -i:iisw3c -o:SQL -server:localhost -database:MyLogs -username:sa -password:sa -createTable: ON
Poznámka: Pokud chcete čistý import logů do DB (bez filtrování, projekce či agregací) zvažte použití Import Flat File… wizarda z SQL Management Studia, který může být ještě rychlejší. Pokud použijete LogParser, mrkněte na volbu transactionRowCount k seskupení uploadovaných dat do menšího množství transakcí (např. -transactionRowCount:-1 pro jedinou transakci).
Uživatelské rozhraní?
LogParser sám je command-line utilita. Nabízí dále COM API, které můžete volat ze svých aplikací (asi ne). Nicméně právě toto API bylo využito autory několika uživatelských rozhraní, které vám při občasném využití LogParseru usnadní život:
- Microsoft LogParser Studio (download) je přímo od Microsoftu a kromě GUI přináší i mnoho (181) připravených šablon dotazů pro různé typy logů.

- Log Parser Lizard GUI je bezplatná varianta (s placenou Pro edicí) vytvořená mimo Microsoft, která vypadá celkem schopně. Nezkoušel jsem, ale pokud byste to potřebovali dennodenně, asi to může být zajímavé.
Reference
Následující odkazy se mohou při seznamování LogParserem hodit:
- How to analyse IIS logs using LogParser / LogParser Studio [IIS Field Readiness]
- LogParser Functions [logparserplus.com]
- Analyze your IIS Log Files – Favorite Log Parser Queries [CarlosAg]
- Log Parser Rocks! More than 50 Examples! [Mike Lichtenberg]
- LogParser Forums [forums.iis.net]
- LogParser Performance Inserting into SQL Server
Microservices a Docker [Michal Augustýn, HAVIT Vzdělávací okénko 7.12.2017]
Záznam z interního vzdělávacího okénka HAVIT ze 7.12.2017 je publikován na našem HAVIT YouTube Channel. Téma prezentoval Michal Augustýn, Lead Software Developer @ AVAST, MVP Reconnect]:
Dotčená témata:
- Microservices – výhody, nevýhody, výzvy
- Docker Basics – architektura
- container
- image
- Docker Client
- Docker Daemon
- Docker Registry
- interaktivní režim
- mapování portů, filesystemu
- parametrizace
- Dockerfile
- Využití Dockeru
- replikovatelný build
- izolace a replikace testování
- produkce
- Docker Orchestration
- Docker Swarm
- Kubernetes
- Marathon (on Meos)
Bohužel nemáme posledních 5 minut audiozáznamu, kdy Augi mluvil o Dockeru na Windows. Zkusíme to dotočit, ale neslibujeme… ;-)
React a Redux – záznam [Martin Havel, Lukáš Rada, HAVIT Objevitelský den 28.11.2017]
Záznam z úvodního brífingu pro náš HAVIT Objevitelský den (28.11.2017), kdy se snažíme na jeden den odpojit od práce a věnovat ho sebevzdělávání např. formou hrátek s libovolnou technologií. Kdo neměl vybráno téma vlastní, mohl se tentokrát připojit k objevování Reactu a Reduxu.
Záznam je publikován na našem HAVIT YouTube Channel.
React
První část – React – prezentoval Martin Havel:
Redux
Druhou část – Redux – prezentoval Lukáš Rada: