ThreadStatic et tâche asynchrones

Par défaut

Si vous utilisez l’attribut ThreadStatic pour obtenir des variables contextualisées à un thread, cette solution ne marche pas si vous êtes dans un contexte de tâches asynchrone, par exemple en utilisant async/await.

Par exemple le code suivant, lors de son exécution ne produit pas le résultat auquel on pourrait s’attendre

public class Program
{
  [ThreadStatic]
  private static string Test;

  public static void Main(string[] args)
  {

      var task = Task.Run(async () =>
      {
         Test = "a";
         
         await Run();

         Console.WriteLine(Test);
      });

      task.Wait();

      Console.ReadLine();
  }

  private static async Task Run()
  {
      await Task.Delay(100);
  }
}

En effet à la fin de l’exécution la valeur affichée dans la console est …. vide.

Cela s’explique par le fait que les tâches sont, en générale, exécutées sur des threads différents du thread déclencheur et que l’exécution du code après un « await » est faite sur le thread de retour de la tâche.

Pour obtenir le même comportement avec les tâches asynchrone il faut utiliser la classe AsyncLocal<T>:

public class Program
{
  private static AsyncLocal<string> Test2 = new AsyncLocal<string>();

  public static void Main(string[] args)
  {

      var task = Task.Run(async () =>
      {
         Test2.Value = "b";
         
         await Run();

         Console.WriteLine(Test2.Value);
      });

      task.Wait();

      Console.ReadLine();
  }

  private static async Task Run()
  {
      await Task.Delay(100);
  }
}

Dans ce cas l’exécution affiche bien « b » dans la console.

Installer Sentry sur un cluster docker swarm

Par défaut

Sentry est un outil de remonté et de mise en évidence des erreurs dans vos applications. Il supporte un très large panel de technos allant du javascript aux applications iOS en passant par les applications .NET.
Le support des technos n’est pas toujours au même niveau mais globalement avec un peu d’intégration il est possible de mettre en place une solution complète de rapport d’erreurs.

Par défaut Sentry propose 2 types d’installation, la première directement sur un serveur, la deuxième sur Docker.
Toutefois si vous avez un cluster docker en mode swarm les choses ne sont pas aussi simple. En effet le guide d’installation docker utilise les liens et un container en mode interactif, ce qui est problématique dans le cadre d’un cluster swarm.

Pour palier tout voici la marche à suivre pour déployer Sentry sur un cluster docker swarm:

1°) Créer un réseau dédié à Sentry.
La création d’un réseau dédié à Sentry permet de faire communiquer facile les différents composants entre eux grâce au serveur DNS fournit par docker. Le réseau est créé en mode overlay afin d’être accessible depuis l’ensemble des noeuds du cluster docker

docker network create \
--driver overlay \
sentry

2°) Création d’un volume pour stoker les données Postgres
Par défaut les volumes dockers sont locaux, toutefois il existe des plugins permettant des volumes distribués sur l’ensemble du cluster. Pour plus de simplicité nous utilisons un volume local.

Attention il faut donc jouer cette commande sur le noeud du cluster sur lequel le container postgres sera déployé (Nous utiliserons les contraintes pour forcer le déploiement du container sur un noeud en particulier)

docker volume create -d local --name pgsdata

3°) Déploiement d’un container redis
le déploiement du container redis ne pose pas de problème particulier:

docker service create \
--replicas 1 \
--network sentry \
--name sentry-redis \
redis:3.2-alpine

4°) Déploiement d’un container postgres
La aussi le déploiement du container postgres n’est pas compliqué, la seule subtilité consiste à ne pas oublier de monter le volume précédement créé:

docker service create \
--replicas 1 \
--network sentry \
--name sentry-postgres \
--env POSTGRES_PASSWORD=P@ss0rd \
--env POSTGRES_USER=sentry \
--mount type=volume,source=pgsdata,destination=/var/lib/postgresql/data \
--constraint "node.hostname==docker-node-01" \
postgres:9.6

5°) Création de la configuration de sentry
C’est la ou les problèmes commencent. La configuration de sentry se fait à partir d’un container en mode interactif, le problème étant que docker swarm ne supporte pas les containers interactifs. de plus notre installation utilisant un réseau dédié, il n’est pas possible de lancer un container en mode « standalone » en utilisant le réseau créé sur le swarm.
Toute l’astuce consiste à lancer un container dans le service avec un sleep et ensuite de se connecter dessus avec la commande exec

docker service create \
--network sentry \
--name sentry-upgrade \
--with-registry-auth \
--env SENTRY_SECRET_KEY="{{ma clef sentry}}" \
--env SENTRY_POSTGRES_HOST=sentry-postgres \
--env SENTRY_REDIS_HOST=sentry-redis \
--env SENTRY_DB_USER=sentry \
--env SENTRY_DB_PASSWORD=P@ss0rd \
myregistry.mydomain.com/sentry:latest \
sleep 3000

Il faut ensuite localiser ou l’instance du container a été démarrée:

docker service ps sentry-upgrade

et se connecter en ssh sur l’hote pour ensuite s’attacher au container:

docker exec -it {{nom de la tache}}.{{id du container}} /bin/bash

ou {{nom de la tache}} est le nom généré par docker (par exemple sentry-upgrade.1 et {{id du container}} l’id du container renvoyé par la commande docker service ps sentry-upgrade.
Une fois dans le container, il ne reste plus qu’à jouer la commande upgrade de sentry :
/entrypoint.sh upgrade

6°) Déploiement du front-end de sentry
A ce point nous avons un cache redis, un serveur postgre et la configuration initiale injectée dans postgres. Il nous reste donc à démarrer un front-end, toutefois étant dans un swarm nous ne pouvons pas utiliser l’option --link de docker, il nous faut donc utiliser les variables d’environnement définies dans Sentry pour surcharger les informations récupérées par sentry automatiquement:

docker service create \
--replicas 1 \
--limit-memory 256m \
--network sentry \
--env SENTRY_SECRET_KEY="{{ma clef sentry}}" \
--env SENTRY_POSTGRES_HOST=sentry-postgres \
--env SENTRY_REDIS_HOST=sentry-redis \
--env SENTRY_DB_USER=sentry \
--env SENTRY_DB_PASSWORD=P@ss0rd \
--name sentry-web-01 \
--publish 9000:9000 \
myregistry.mydomain.com/sentry \
run web

et voilà ! un beau front-end sentry qui tourne sur un docker swarm.

il ne reste plus qu’à déployer un worker et un cron:
7°) Déploiement d’un worker sentry

docker service create \
--replicas 1 \
--network sentry \
--env SENTRY_SECRET_KEY="{{ma clef sentry}}" \
--env SENTRY_POSTGRES_HOST=sentry-postgres \
--env SENTRY_REDIS_HOST=sentry-redis \
--env SENTRY_DB_USER=sentry \
--env SENTRY_DB_PASSWORD=P@ss0rd \
--name sentry-worker-01 \
myregistry.mydomain.com/sentry \
run worker

8°) Déploiement d’un cron sentry

docker service create \
--replicas 1 \
--network sentry \
--env SENTRY_SECRET_KEY="{{ma clef sentry}}" \
--env SENTRY_POSTGRES_HOST=sentry-postgres \
--env SENTRY_REDIS_HOST=sentry-redis \
--env SENTRY_DB_USER=sentry \
--env SENTRY_DB_PASSWORD=P@ss0rd \
--name sentry-cron \
myregistry.mydomain.com/sentry \
run cron

Nouvelle mise à jour de Visual Studio 2017 RC

Par défaut

Microsoft vient de mettre à jour Visual Studio 2017 RC avec un ensemble de corrections et d’améliorations et en particulier sur le tooling de .NET Core qui devient, disons le franchement, enfin utilisable.

Le détails des améliorations de cette version est disponible ici: https://blogs.msdn.microsoft.com/dotnet/2016/12/12/updating-visual-studio-2017-rc-net-core-tooling-improvements/

la suite…

Changement de modèle de licensing dans VSTS et TFS 2017 pour les builds et release

Par défaut

Dans les prochaines semaines, Microsoft va déployer un nouveau modèle de licensing pour les builds et les releases basés non pas sur le nombre d’agents déployés mais sur le nombre de pipeline (workflow de build ou de release) exécuté en parallèle.

Concrètement cela veut dire que vous pourrez déployer autant d’agents de build ou de release que vous le souhaitez mais que seul un nombre déterminé de pipeline (build ou release) pourront s’exécuter en parallèle.

L’énorme avantage de ce changement c’est la possibilité, pour le même coût qu’actuellement, d’installer des agents de builds/release sur windows, linux et mac et permettre ainsi de builder virtuellement n’importe quel type de projets sans surcout.

L’offre de base de VSTS contient toujours 4 heures d’exécution d’un pipeline hébergé gratuites ainsi qu’un pipeline privé.

Coté TFS, c’est complétement open-bar pour les builds mais seule 1 pipeline de release est fournit de base. Tout les abonnements VS Entreprise que vous avez ajoute 1 pipeline de release gratuitement.

Work item search: Comment chercher dans vos work items depuis VSTS

Par défaut

Visual Studio Team Service est un outil complet qui permet de gérer bien des choses dont vos éléments de travail.
Malheureusement jusqu’à maintenant il n’était pas possible de faire de recherche simplement sur ces fameux work items.
La nouvelle extension Work item search permet (enfin) de combler ce manque et de rapprocher VSTS d’un Jira pour le coté gestion des éléments de travail.

Le principe de la recherche est le même que pour les éléments de code: Une recherche globale est possible ou vous pouvez spécifier le type d’information que vous recherchez. A ce jour les champs des work item sur lesquels la recherche est possible sont:

  • Assigné à
  • Créé par
  • Etat
  • Type d’élément de travail

Pour plus d’information vous pouvez consulter le post de l’annonce:
https://blogs.msdn.microsoft.com/visualstudioalm/2016/11/16/announcing-public-preview-for-work-item-search/

Visual Studio 2017 RC est disponible

Par défaut

Suite à la conférence connect(); , la pré-version de VS 2017 est disponible.
Cette release apporte pas mal de changements et surtout le support .NET Core avec le système de projets basé sur MSBuild.

Attention donc si vous avez des solutions avec des projets .NET, ils seront upgradé automatiquement vers des projets .csproj en lieu et place des projets .xproj. D’ailleurs le process de migration n’est pas forcément sans problème, plusieurs de mes projets n’étaient pas fonctionnels après migration (Une obscure histoire de runtime non défini).

Pour télécharger VS 2017 RC c’est par ici: https://www.visualstudio.com/vs/visual-studio-2017-rc/

Demain c’est l’évènement connect(); de MS !

Par défaut

Demain commence l’évènement Microsoft connect(); 2016.
Au programme une keynote, une journée de conf techniques et une journée spéciale app mobile et web

Au niveau des attentes, il est très fort probable que VS 2017 RC et Visual Studio For Mac soit officiellement annoncés.

Pour suivre l’évènement c’est par ici: https://connectevent.microsoft.com

Azure container service apporte le support de kubernetes en preview

Par défaut

L’équipe Azure vient d’annoncer le support en preview de la dernière version de Kubernetes (1.4) directement dans Azure Container Service (ACS).
Cela permet de maintenant de déployer un cluster Kubernetes dans azure depuis ACS avec une configuration automatique et l’intégration, par exemple, du load balancer Azure.

Une bonne nouvelle pour tout ceux qui se penchent sur les conteneurs !

Sources :

Utilisation de NLog avec DNX/ASP.NET 5

Par défaut

Si vous utilisez NLog dans vos projets et que vous souhaitez passer à ASP.NET (beta 8 à l’heure ou ces lignes sont écrites), il vous faut savoir quelques petites choses:

  • NLog ne supporte pas (encore) le framework Core,
  • La structure des projets ayant changé et le format des fichiers de configuration également, la config de NLog doit être externalisé du web.config

Sur ce dernier point les méthodes habituelles permettant à NLog de facilement localiser le fichier de configuration (CF la doc de NLog) ne fonctionnent pas car l’application n’est plus hébergée directement par IIS mais est gérée par DNX.

Pour permettre la configuration correcte de NLog il faut lui indiquer « manuellement » ou trouver le fichier de configuration à utiliser.

Par exemple:

// Configure is called after ConfigureServices is called.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationEnvironment appEnv, ILoggerFactory loggerFactory)
{
     NLog.LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(Path.Combine(appEnv.ApplicationBasePath, "NLog.config"));
}

Et voila ! Ce n’est pas bien compliqué mais en même temps si on ne le sait pas … 😉

La CTP 6 de VS 2015 est disponible

Par défaut

La CTP 6 de VS 2015 est disponible depuis hier soir au téléchargement pour l’ensemble des personnes intéressées par le test cette version préliminaire.

Pour le téléchargement c’est par ici

Au niveau des améliorations disponibles nous avons:

  • NuGet: Amélioration des performances (ce qui n’est pas du luxe au vue de l’inutilisabilité de la précédente version ^^)
  • Single Sign-In entre les services VS Online et Azure
  • ASP.NET 5.0: Amélioration du support d’ASP.NET 5.0
  • Intégration de Xamarin dans l’installeur et dans VS
  • CodeLens pour Git local
  • CodeMaps: Amélioration des performances
  • .NET Debugging: Amélioration des performances lors du démarrage de débug
  • XAML UI Debugging