2014年9月29日 星期一

TeamCity 發行 Octopus 部署套件

先到Octopus建立一個專案

選擇發行套件

就可以找到剛建置出來的套件

回到TeamCity新增一個部署設定

在Trigger中新增一個建置完成觸發事件,指定到對應的專案

在關聯性設定中,也把這個專案指定進來

在版號的地方才能用%dep開頭的設定,取得這個專案目前的版號

建置步驟選擇OctopusDeploy: Create release

輸入Octopus URL和API Key
再輸入專案名稱和要連立版本的版號
如果要順便部署環境的話,就在Deploy To中輸入環境名稱
再把Wait for deployment to complete勾起來就行了

建置成功

自動新增一個部署版本了

TeamCity 打包 Octopus 部署套件

首先新建一個建置設定


設定SVN路徑


SVN的細部設定


取用trunk為根目錄

設定版號

第一個建置步驟是NuGet Installer,選擇方案檔即可
如果有自訂的NuGet來源,要記得輸入


接下來可以建置專案了,勾選方案檔即可
在Run OctoPack這邊也勾選起來,輸入建置版號即可

建置成功就會得到打包好的套件

利用OctoPack套件打包Web專案

首先開一個簡單的Web專案


透過NuGet安裝OctoPack套件


簡單寫一個批次檔來測試
@echo off
set MSBUILD="C:\Program Files (x86)\MSBuild\12.0\bin\amd64\msbuild.exe"
if not exist %MSBUILD% (
 echo MSBuild not found
 exit
) 

%MSBUILD% WebApplication1.sln /p:Configuration=Release /p:RunOctoPack=true /m
pause

編譯成功

bin資料夾下就會多了一個打包好的套件


TeamCity 安裝 Octopus Deploy Integration 套件

首先到官網下載TeamCity Plugin
http://octopusdeploy.com/downloads



把下載的zip檔,丟到TeamCity的Plugins資料夾下面


重新啟動TeamCity後,就可以在Plugin列表中看到Octopus Deploy Integration套件


在TeamCity的建置步驟中,會多出三個Runner
Create release是新增發行版本,也可以順便部署的指定的環境
Deploy release是部署指定版本
Promote是把現有的版本從指定的環境部署到其他環境


在VS建置Runner中,也會多出一個OctoPack的設定項目
勾選後會在建置參數中加入/p:RunOctoPack=true


參考資料
官網的說明和影片
http://docs.octopusdeploy.com/display/OD/TeamCity

2014年9月18日 星期四

NLog.Elmah

NLog.Elmah套件,是用來擴充NLog的Target,可以寫到Elmah去
Elmah的用法可以參考之前的筆記
在設定好Elmah之後,開始來安裝NLog.Elmah
首先透過NuGet來安裝套件


再來設定NLog來套用Elmah
主要是透過extensions來引用NLog.Elmah這個Assembly
就可以透過Elmah這個Target,把Log寫到Elmah去
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

    <extensions>
        <add assembly="NLog.Elmah"/>
    </extensions>
    
    <targets>
        <target xsi:type="Elmah" name="elmah"
                layout="${longdate} ${uppercase:${level}} ${message}"/>
    </targets>

    <rules>
        <logger name="*" minlevel="Trace" writeTo="elmah" />
    </rules>
</nlog>


就可以在elmah中看到寫出的記錄,只是沒有Type,HttpStatusCode也都是0


如果加上LogLevelAsType="true"這個屬性
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" autoReload="true">

    <extensions>
        <add assembly="NLog.Elmah"/>
    </extensions>
    
    <targets>
        <target xsi:type="Elmah" name="elmah" LogLevelAsType="true"
                layout="${longdate} ${uppercase:${level}} ${message}"/>
    </targets>

    <rules>
        <logger name="*" minlevel="Trace" writeTo="elmah" />
    </rules>
</nlog>


elmah的Type中,就會顯示Log的Level


NLog Database Target

NLog要把Log存到資料庫的話,可以透過Database這個taget

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" autoReload="true">
    <targets>
        <target xsi:type="Database" name="db"
                connectionString="data source=(localdb)\v11.0;database=LogDB; trusted_connection=true;"
                commandText="INSERT INTO NLog_Error(ThreadId, MachineName, LogName, LogLevel, LogMessage, CallSite, Exception, Stacktrace) VALUES (@ThreadId, @MachineName, @LogName, @LogLevel, @LogMessage, @CallSite, @Exception, @Stacktrace);">
            <parameter name="@ThreadId" layout="${threadid}"/>
            <parameter name="@MachineName" layout="${machinename}"/>
            <parameter name="@LogName" layout="${logger}"/>
            <parameter name="@LogLevel" layout="${level}"/>
            <parameter name="@LogMessage" layout="${message}"/>
            <parameter name="@CallSite" layout="${callsite:filename=true}"/>
            <parameter name="@Exception" layout="${exception}"/>
            <parameter name="@stacktrace" layout="${stacktrace}"/>
        </target>
    </targets>
    <rules>
        <logger name="*" minlevel="Trace" writeTo="db" />
    </rules>
</nlog>


資料庫的Table Schema

USE LogDB
GO

IF OBJECT_ID('NLog_Error') IS NOT NULL
DROP TABLE NLog_Error
GO

CREATE TABLE NLog_Error
(
 LogId   INT    NOT NULL IDENTITY(1,1) PRIMARY KEY,
 ThreadId  INT    NOT NULL,
 MachineName  VARCHAR(255) NOT NULL,
 LogName   VARCHAR(255) NOT NULL,
 LogLevel  VARCHAR(5)  NOT NULL,
 LogMessage  VARCHAR(MAX) NOT NULL,
 CallSite  VARCHAR(1024) NOT NULL,
 Exception  VARCHAR(1024) NOT NULL,
 Stacktrace  VARCHAR(1024) NOT NULL,
 CreateDateTime DATETIME NOT NULL DEFAULT(GETDATE())
)
GO

2014年9月16日 星期二

Elmah (Error Logging Modules and Handlers)

Elmah - Error Logging Modules and Handlers
是一個將未處理的Error記錄起來的模組,和包含一個顯示Log的處理常式
先開一個簡單的Web專案

透過NuGet安裝Elmah套件

從設定檔上可以看到包含四個模組
<configSections>
    <sectionGroup name="elmah">
        <section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah" />
        <section name="errorLog" requirePermission="false" type="Elmah.ErrorLogSectionHandler, Elmah" />
        <section name="errorMail" requirePermission="false" type="Elmah.ErrorMailSectionHandler, Elmah" />
        <section name="errorFilter" requirePermission="false" type="Elmah.ErrorFilterSectionHandler, Elmah" />
    </sectionGroup>
</configSections>

security,用來設定是否允許遠端讀取elmah.axd,
errorLog,用來設定Log要存在什麼地方,例如XML或DB,預設是Memory
errorMail,用來把Log送出EMail通知
errorFilter,用來過濾Log

elmah.axd是用來顯示Log的處理常式,如果允許遠端存取的時後,在安全性上要特別注意


如果要把記錄存在資料庫的話,以下用SQL Server為例子
首先到官網取得資料表結構
或是透過NuGet安裝Elmah.SqlServer套件

就可以在App_Readme資料夾下找到SQL檔案

不過最好把NTEXT形態,改成NVARCHAR(MAX)比較好

準備好資料庫,包含ELMAH_Error資料表和三隻預儲程序
透過errorLog設定Log寫到SQL Server
<elmah>
    <security allowRemoteAccess="false" />
    <errorLog type="Elmah.SqlErrorLog, Elmah" connectionString="data source=(localdb)\v11.0; database=ElmahDB; trusted_connection=true" />
</elmah>

隨便丟個錯誤出來
namespace WebApplication1
{
    public partial class WebForm1 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            throw new Exception("test");
        }
    }
}

資料庫就有記錄了