Photon 카운터
Photon은 서버의 성능과 통계를 추적 하기 위해 커스텀 In-Memory 카운터는 물론 Windows 성능 카운터를 이용합니다. 예, CPU 부하량, 메모리 사용량, 현재 연결 개수, 오퍼레이션 실행 시간 등.
이러한 카운터를 표시하기 위해서 Windows 성능 모니터 또는 외부 시계열 데이터 베이스시스템을 사용할 수 있습니다.
Photon 은 카운터 값을 UDP ,TCP,PGM 또는 HTTP 를 통하여 게재 할 수 있습니다.
근본적으로 지원되는 어플리케이션 레벨 프로토콜은 다음과 같습니다:
Photon 성능 카운터는 쉽게 확정될 수 있고 디스플레이 옵션을 완전히 커스터마이징 할 수 있습니다.
시작하기
Photon 카운터 사용 시작 하기
"PhotonControl"로 Windows 카운터 정의를 인스톨 하거나 다음의 명령어를 이용합니다:"PhotonSocketServer.exe /installCounters".
Windows 성능 모니터를 사용하여 살펴 봅니다.
선택한 Photon 어플리케이션의 카운터 발행이 사용하는 것으로 되어 있는지 확인 합니다. 환경설정 파일은 반드시 다음 라인이 포함되어 있어야 합니다:
XML
<configSections>
<section name="Photon" type="Photon.SocketServer.Diagnostics.Configuration.PhotonSettings, Photon.SocketServer" />
</configSections>
<Photon>
<CounterPublisher enabled="True" />
</Photon>
Photon.SocketServer.Diagnostics.Configuration.PhotonSettings
의 alias 로 <Photon>
을 유지하는 것이 중요한데 어플리케이션 퍼블리셔 인스턴스의 디폴터 환경설정을 위한 예약된 내부 이름 이기 때문 입니다.
기본적으로 퍼블리싱은 매 10초 마다 구식의 브로드캐스트 종말점 udp://255.255.255.255:40001
(프로토콜의 이름은 "PhotonBinary" 입니다)에 Photon 바이너리 프로토콜 UDP 패킷으로 전송되도록 설정되어 있습니다.
프로덕션으로 사용할 때는 명시적으로 유니캐스트(Unicast) endpoint와 senderId 를 지정하는 것이 더 좋습니다.
성능 카운터
In-Memory 카운터
Photon의 어플리케이션들은 in-memory 성능 카운터를 사용하여 어플리케이션의 특정 통계를 추적합니다. 예, 현재 게임 개수.
이러한 카운터는 Windows 성능 모니터에는 표시되지 않습니다.
Windows 성능 카운터
성능 데이터를 추적하기 위해서 Photon 은 원조 Windows 성능 카운터 에 의존 하고 있습니다.
EnablePerformanceCounters
를 True
로 설정 하시면 됩니다:
XML
<configuration>
<applicationSettings>
<Photon.LoadBalancing.Common.CommonSettings>
<setting name="EnablePerformanceCounters" serializeAs="String">
<value>True</value>
</setting>
</Photon.LoadBalancing.Common.CommonSettings>
</applicationSettings>
</configuration>
이러한 카운터를 사용하고 싶으면 Photon 을 시작하기전에 인스톨 해야 합니다. Photon 컨트롤에서 다음처럼 수행 합니다:
Windows 성능 모니터의 설치된 카운터들에 있는지 확인 하세요:
Photon 이 시작되면 자동적으로 이러한 카운터에게 데이터를 기록 하게 됩니다.
사용방법
개요
Photon 서버는 통계를 발행하기 위해서 Windows 성능 카운터 와 In-Memory Photon 카운터를 사용합니다.
Photon 원조 코어는 통계정보를 Windows 성능 카운터에만 작성합니다. CounterPublisher
.NET 어플리케이션에 의해서 다른 모든 엔드 포인트로 읽고 발행 될 수 있습니다.
일반적으로 Photon Server 는 출시 할 때 몇개의 .NET 어플리케이션이 들어 있습니다.
모든 Photon .NET 어플리케이션은 Photon.SocketServer.ApplicationBase
을 구현하는 기본 카운터의 집합이 들어 있으며
설정 가능한 Photon.SocketServer.Diagnostics.CounterPublisher
싱글톤을 통해 게시 될 수 있습니다.
.NET 응용 프로그램 통계 게시는 어플리케이션에 대한 설정 파일 (일반적으로 "어플리케이션 이름"+ ". config")을 통해 활성화 할 수 있습니다.
게시 속도, 사용된 프로토콜, 수신 엔드 포인트와 추가적인 옵션은 가동 상태에서 설정 될 수 있습니다.
디폴트 퍼블리셔는 다양한 종류의 프로토콜을 지원 합니다.
퍼블리셔는 플러그인에 의해서 확장 될 수 있습니다. 퍼블리셔에 의해 만들어진 카운터 샘플들을 추가적인 카운터 스키마를 환경설정에 지정하여 확장하는 것도 가능 합니다.
아키텍쳐
Photon 원조 코어는 Windows 성능 카운터에 통계를 작성 합니다.
모든 Photon .NET 어플리케이션은 Photon.SocketServer.ApplicationBase
을 구현 합니다.
후자는 Photon.SocketServer.Diagnostics.CounterPublisher 싱글톤을 이용하여 통계를 샘플링하고 세계에 게시합니다.
퍼블리셔는 Photon.SocketServer.Diagnostics.Configuration.PhotonSettings
, Photon.SocketServer
타입인 어플리케이션 환경설정<Photon>
섹션에서 설정 할 수 있습니다.
통계 게시를 시작 하기 위해서 <CounterPublisher>
는 반드시 어플리케이션의 환경설정에서 사용하는 것으로 설정되어 있어야 합니다. "AddDefaultAppCounter" 옵션은 퍼블리셔에게 디폴트 어플리케이션 카운트를 포함할지를 제어 하는데 기본값은 "true"로 설정 되어 있습니다.
퍼블리셔는 "Sampler" 와 "Sender" 로 구성 되어 있습니다.
샘플러는 퍼블리셔에 등록된 모든 카운터를 단순히 읽고(ExitGames.Diagnostics.Counter.ICounter
인터페이스에 의해 추상화된 모든 소스로 부터) 읽은 값을 큐에 들어가있는 시간에 통합 합니다.
일반적으로 카운터는 분리된 카운터 클래스에 의해 노출되며 특정 속성의 정적 멤버로 정의되며 네임스페이스 정의를 포함하고 실제 카운터 이름을 가지고 있는 스키마 클래스를 도와 구현과 의미있는 제공자들(Windows 원조 또는 In-memory)에 지정되어 등록됩니다.
전송자는 ExitGames.Diagnostics.Monitoring.Protocol.ICounterSampleWriter
인터페이스의 구현을 사용하여 설정된 엔드 포인트에게 통합된 데이터를 실제로 전송합니다.
전송자는 퍼블리셔로부터 전송과 프로토콜 레벨을 추상화 합니다.
개발자들이 새로운 플러그인 생성에 도움을 주기 위한 ICounterSampleWriter
의 디폴트 추상 구현이 있습니다:PhotonBinaryWriterBase
기본적으로 샘플러는 최초 10초의 지연 후에 10초 간격으로 카운터를 읽으며 모든 통합된 데이터는 전송자에 의해 10초마다 게시됩니다.
전송 프로토콜
기본적으로 사용할 수 있는 몇 개의 전송 프로토콜이 있습니다:
- UDP
- HTTP (또는 HTTPS)
- PGM
- 제3자 클라이언트에 의해서 제공되는 모든 커스텀 전송
전송 프로토콜은 ExitGames.Diagnostics.Configuration.CounterSampleSenderSettings
의 endpoint 프로퍼티를 통하여 설정 할 수 있습니다.
개별 TCP는 아직 지원 하지 않습니다.
이러한 전송 타입들은 ExitGames.Diagnostics.Configuration.TransportType
에 정의 됩니다.
"Endpoint" 프로퍼티 포맷은 System.Uri
타입의 디폴트 생성자 사양에 의해 정의 됩니다.
사용방법 예제:
XML
<Photon>
<CounterPublisher enabled="True">
<Sender endpoint="udp://255.255.255.255:40001" />
</CounterPublisher>
</Photon>
또는
XML
<Photon>
<CounterPublisher enabled="True">
<Sender endpoint="https://localhost:4000" />
</CounterPublisher>
</Photon>
"CounterPublisher/App.config" 에 더 많은 예제가 있습니다.
어플리케이션 프로토콜
Photon "CounterPublisher" 는 다양한 시계열 데이터베이스로 기록 될 수 있습니다.
실제 데이터 게시는 ExitGames.Diagnostics.Monitoring.Protocol.ICounterSampleWriter
의 구현을 통해 이루어 집니다.
일반적으로 모든 지정된 기록자(writer)에 대해서 ExitGames.Diagnostics.Configuration
네임스페이스내에 상응하는 설정 클래스가 있습니다.
전송자 디폴트 설정은 ExitGames.Diagnostics.Configuration.CounterSampleSenderSettings
를 통해서 구현 됩니다.
"ExitGamesLibs" 는 다음 사항들을 구현이 포함됩니다:
- 구식의 Photon 바이너리 프로토콜
- Graphite
- InfluxDB 0.9.0 / Graphite UDP with tags
- StatsD
"CounterPublisher" 는 ICounterSampleWriter
의 모든 외부 구현을 이용 할 수 있습니다.
따라서 커스텀 기록자 구현 기능을 통해 어떤 데이터베이스로든 기록 할 수 가 있습니다.
또한 다음 사항을 가능하게 지원하는 ICounterSampleWriter
의 독립적인 커스텀 구현 2 종류가 있습니다:
- Amazon AWS CloudWatch
(CounterPublisher.AWS.CloudWatch
플러그인) - NewRelic
Platform
(CounterPublisher.NewRelic
플러그인)
이러한 외부 커스텀 구현은 커스텀 "프로토콜"을 지정하여 설정 될 수 있습니다. 즉,
XML
<Photon>
<CounterPublisher enabled="True" senderType="ExitGames.Diagnostics.Configuration.AWSCloudWatchSettings, CounterPublisher.AWS.CloudWatch">
<Sender protocol="ExitGames.Diagnostics.Monitoring.Protocol.AWS.CloudWatch.AWSCloudWatchWriter, CounterPublisher.AWS.CloudWatch" />
</CounterPublisher>
</Photon>
중요한 점은, 일반적으로 커스텀 프로토콜 구현은 특정한 환경설정 프로퍼티들의 설정이 필요 하다는 점 입니다.
기록자 사양 "senderType" 프로퍼티 클래스 타입을 지정하여 될 수 있습니다(위에서 보인 예와 같이).
Counters 스키마
"CounterPublisher" 는 등록된 카운터를 읽고 쓰게 됩니다.
카운터를 등록하기 위해서는 CounterPublisher.AddCounter(ICounter counter, string name)
라는 특별한 메소드가 있습니다.
일반적으로 카운터는 Photon.SocketServer.Diagnostics.PhotonCounter
와 같이 몇 가지 논리적인인 이유로 클래스로 그룹화 됩니다.
"PhotonCounter" 는 .NET 어플리케이션에 기반한 모든 "ApplicationBase" 에 대하여 디폴트 카운터를 제공합니다.
(AvrgOpExecTime, EventsSentCount, EventsSentPerSec, MessagesSentCount,
MessagesSentPerSec, RawMessagesSentCount, RawMessagesSentPerSec,
InitPerSec, OpReceiveCount, OpReceivePerSec, OpResponseCount,
OpResponsePerSec, OperationsFast, OperationsMaxTime, OperationsMiddle,
OperationsSlow, SessionCount)
카운터는 "PublishCounter" 속성을 가진 정적 readonly(읽기만 가능한) 필드들로 추가적인 프로퍼티들을 다른 이름과 같은 것으로 정의 할 수 있습니다.
C#
public static class PhotonCounter
{
[PublishCounter("AvrgOpExecTime")]
public static readonly AverageCounter AverageOperationExecutionTime = new AverageCounter();
...
}
카운터 클래스들은 "CounterPublisher"에 CounterPublisher.AddCounterClass
또는
CounterPublisher.AddStaticCounterClass
를 가지고 다음과 같이 등록 됩니다:
C#
if (PhotonSettings.Default.CounterPublisher.Enabled)
{
if (PhotonSettings.Default.CounterPublisher.AddDefaultAppCounter)
{
CounterPublisher.DefaultInstance.AddStaticCounterClass(typeof(PhotonCounter), this.ApplicationName);
}
CounterPublisher.DefaultInstance.Start();
}
일반적으로 모든 카운터 클래스는 논리적 네임스페이스와 카운터 이름을 포함하고 있는 특별한 스키마 클래스와 짝을 이루고 있습니다.(Photon.CounterPublisher.SocketServerCounterSchema
):
C#
namespace Photon.CounterPublisher
{
public static class SocketServerCounterSchema
{
public static class Common
{
public static readonly string CategoryName = "Photon Socket Server";
public static readonly string BuffersInUseCounter = "IO Buffers In Use";
...
}
public static class Enet
{
public static readonly string ACKsInCounter = "Acknowledgements in";
public static readonly string ACKsInPerSecondCounter = "Acknowledgements in/sec";
...
}
public static class Tcp
{
...
}
...
}
}
따라서 카운터 클래스는 스키마를 대신하여 카운터에 대하여 형성 하게 됩니다.
C#
namespace Photon.CounterPublisher
{
[CounterSet(Name = "Photon")]
public static class SocketServerCounter
{
/// <summary>
/// The bytes in per second counter.
/// </summary>
[PublishCounter("BytesInPerSecond")]
public static readonly PerformanceCounterReader BytesInPerSecondCounter =
CreateCounterReader(Schema.Common.CategoryName, Schema.Common.BytesInPerSecondCounter);
...
}
}
마지막으로,"CounterPublisher" 는 모든 추가적인 카운터에 대하여 <Counters/Schema>
환경설정 요소를 통해 읽고 쓰는 것을 설정 할 수 있습니다.
XML
<Photon>
<CounterPublisher ... >
<Sender ... />
<Counters>
<Schema namespace="TestNamespace" type="Photon.CounterPublisher.SystemCounter, CounterPublisher" />
</Counters>
</CounterPublisher>
</Photon>
현명하게 매트릭 이름을 고르는 것이 중요 합니다. 다음의 명명 규칙을 준수하도록 하세요.
- 파스칼케이스 매칭
[a-zA-Z0-9]+
심볼 집합
1.1. "Per" 접미사 이후 포맷은 다음과 같아야 합니다:{ValueUnit}{YourMetricInWordsAction}Per{Interval}
. LikeSystem.InBytesRecvPerSecond
.
1.2. "Count" 접미사 이후 포맷은 다음과 같아야 합니다:{CountUnit}{YourMetric}Count
.CounterPublisher.EventsSentCount
와 같이. - 값들 :
2.1. (값/간격) 또는 값/간격. "bytes in/sec"과 같이, TCP: "Disconnected Peers +/sec". 또는
2.1. If have in the end: (Value) like Time Spent In Server: In (ms). {ValueUnit}AnyThingInPascalCase
- 특별한 것
표준 유닛 타입: Seconds | Microseconds | Milliseconds | Bytes | Kilobytes | Megabytes |
Gigabytes | Terabytes | Bits | Kilobits | Megabits | Gigabits | Terabits | Percent |
Count.
Windows 성능 카운터 게시하기
원조 Photon Core는 Windows 성능 카운터 (WPC)에 통계 정보를 기록합니다. 따라서 독립적인 CounterPublisher .NET 어플리케이션이 같이 출하되었고 이것은 프록시의 종류와 같은 역할을 합니다:원하는 곳(Photon 의 Windows 성능 카운터를 포함하여)에서 카운터를 읽으며 임시적으로 카운터를 메모리내에 추가하고 이 카운터들을 게시 하게 됩니다.
추가적으로 Photon Core 카운터들인 "CounterPublisher" 어플리케이션은 CPU 부하량, 메모리 사용량등 Windows 시스템 카운터와 같은 것을 읽고 브로드캐스트합니다.
"CounterPublisher" 어플리케이션은 기본적으로 사용하도록 설정되어 있습니다.이 값은 "/CounterPublisher/bin/CounterPublisher.dll.config" 에서 설정 될 수 있습니다.
내부적으로는 WPC 를 읽을 수 있도록 특별히 디자인된 카운터 클래스 기능을 가진 표준 "CounterPublisher"의 "ApplicationBase" 기반 Photon 어플리케이션입니다.
가장 간단한 환경 설정의 내용은 다음과 같습니다:
XML
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="Photon" type="Photon.SocketServer.Diagnostics.Configuration.PhotonSettings, Photon.SocketServer"/>
</configSections>
<Photon>
<CounterPublisher enabled="True" />
</Photon>
</configuration>
<Photon>
섹션의 alias 를 Photon.SocketServer.Diagnostics.Configuration.PhotonSettings
타입으로 유지하는것이 중요 한데, 어플리케이션 퍼블리셔 인스턴스의 기본 환경설정에 내부 이름으로 예약 되었기 때문입니다.
기본적으로 게시는 매 10초 마다 앤드포인트 udp://255.255.255.255:40001
(프로토콜 이름은 "PhotonBinary" 입니다) 로 브로드캐스트 하기 위해 구식의 Photon 바이너리 프로토콜 upd 패킷으로 전송하는 것으로 설정됩니다.
상용에서 사용할 때는 유니캐스트 앤드포인트와 senderId 를 명시적으로 지정하는 것이 더 좋습니다.
"CounterPublisher" 어플리케이션은 CounterPublisher.AddStaticCounterClass
메소드를 사용하여 2개의 카운터 클래스를 등록 합니다::
Photon.CounterPublisher.SystemCounter
는 CPU, 메모리와 전체적인 네트워크에 대한 통계를 리포트 하며 Photon.CounterPublisher.SocketServerCounter
는 네트워크(UDP,ENET,TCP,...) 와 여러가지 큐 통계등을 포함하여 특정한 원시 Photon Core WPC 카운터를 리포트합니다.
어떤 카운터들과 값이 현재 게재되고 있는지 보기 위해서는 ExitGames.Diagnostics
패키지의 DEBUG
로그 레벨이 "/CounterPublisher/bin/log4net.config" 에 강제적으로 들어가 있어야 합니다. 그리고 나서 "Photon/Log/CounterPublisher.log" 를 살펴 보세요(이 경로는 "log4net.config" 내의 LogFileAppender 환경설정에서 지정되어 있습니다).
XML
<logger name="ExitGames.Diagnostics">
<level value="DEBUG" />
</logger>
Photon 관리화면에 게시하기
Photon 은 통계데이터를 게시하기 위한 이전 방식의 컴팩트한 바이너리 패킷 프로토콜이 있습니다.( ExitGames.Diagnostics.Configuration.ProtocolType.PhotonBinary
은 <Sender>
의 기본 프로토콜 타입 입니다)
모든 전송 레이어 상에서 동작 할 수 있습니다: UDP, TCP, PGM, HTTP
"ProtocolType" 은 "PhotonBinary" 입니다.
Sender 타입은 ExitGames.Diagnostics.Configuration.PhotonBinaryWriterSettings
입니다.
Writer 타입은 ExitGames.Diagnostics.Monitoring.Protocol.Photon.Binary.PhotonBinaryWriter
입니다.
UDP 와 같은 신뢰할 수 없는 전송을 사용할 때, "MaxPayloadSize" 를 설정하여 네트워크 전송동안에 패킷 프레그먼트화를 방지 하는 것이 좋습니다.
네트워크의 MTU 내에 페이로드의 총 길이를 유지 하도록 해 주세요.
최적의 값이 정해져 있지는 않으나 일반적인 네트워크 시나리오를 위한 몇 가지 지침이 있습니다:
- 빠른 이더넷 (1432) - 인트라넷에서 가장 많이 사용 됩니다.
- 기가비트 이더넷 (8932) - Jumbo 프레임들은 더 효율적으로 이 기능을 사용할 수 있습니다.
- Commodity Internet (512) - 인터넷을 통해 라우팅되는 경우는 이 범위의 값이 합리적 입니다.
더 높은 값도 가능하지만 경로의 모든 홉을 제어 할 수 없습니다.
어플리케이션은 선택하고 .config 를 다음처럼 변경 하세요:
XML
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="Photon" type="Photon.SocketServer.Diagnostics.Configuration.PhotonSettings, Photon.SocketServer"/>
</configSections>
<Photon>
<CounterPublisher
enabled="True"
addDefaultAppCounter="True"
updateInterval="10"
senderType="ExitGames.Diagnostics.Configuration.PhotonBinaryWriterSettings, ExitGamesLibs">
<Sender
protocol="ExitGames.Diagnostics.Monitoring.Protocol.Photon.Binary.PhotonBinaryWriter, ExitGamesLibs"
endpoint="udp://127.0.0.1:40001"
senderId="servers/Realtime/Public/Local/Test/{0}"
initialDelay="10"
sendInterval="10"
maxQueueLength="720"
maxPayloadSize="512" />
</CounterPublisher>
</Photon>
</configuration>
또는
XML
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="Photon" type="Photon.SocketServer.Diagnostics.Configuration.PhotonSettings, Photon.SocketServer"/>
</configSections>
<Photon>
<CounterPublisher enabled="True">
<Sender
protocol="PhotonBinary"
endpoint="udp://127.0.0.1:40001"
senderId="servers/Realtime/Public/Local/Test/{0}" />
</CounterPublisher>
</Photon>
</configuration>
또는
XML
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="Photon" type="Photon.SocketServer.Diagnostics.Configuration.PhotonSettings, Photon.SocketServer"/>
</configSections>
<Photon>
<CounterPublisher enabled="True">
<Sender
endpoint="https://localhost/PhotonCounter/Insert"
senderId="servers/Realtime/Public/Local/Test/{0}" />
</CounterPublisher>
</Photon>
</configuration>
"senderId" 프로퍼티는 통계 퍼블리셔 식별자로 나중에 식별 될 수 있습니다.
"senderId" 의 {0}
은 일반적으로 로컬 호스트 명으로 교체 됩니다.
만약 "addDefaultAppCounter" 이 사용불가로 되어 있다면 "CounterPublisher" 는 기본 "ApplicationBase" 카운터를 생략하게 됩니다."UpdateInterval" 은 초 단위 샘플링 속도를 나타 냅니다.
Graphite 로 게시하기
Photon은 Graphite를 지원 합니다. Writer 는 ExitGamesLibs
내부에서 구현되어 있습니다. UDP, TCP, PGM, HTTP 상의 모든 전송 레이어에서 동작 할 수 있습니다. Graphite 의 디폴트 전송 레이어는 UDP 입니다.
"ProtocolType" 은 "GraphiteText" 입니다.
전송 타입은 ExitGames.Diagnostics.Configuration.GraphiteTextWriterSettings
입니다.
Write 타입은 ExitGames.Diagnostics.Monitoring.Protocol.Graphite.Text.GraphiteTextWriter
입니다.
텍스트 기반의 프로토콜 이며 형식은 다음과 같습니다:
metric_path value timestamp\n
metric_path
는 PATH[.PATH...]
형태 입니다. .
은 네임스페이스의 구분자 입니다.value
는 float 입니다.
timestamp
는 에포크(epoch) 부터의 초 단위의 unix 시간 입니다.
프로토콜 데이터 예제:
EU.RACK01.FIRST.System.Cpu 1.53993 1428332168
EU.RACK01.FIRST.System.CpuTotal 2.981617 1428332168
EU.RACK01.FIRST.System.Memory 5317 1428332168
EU.RACK01.FIRST.System.BytesTotalPerSecond 8103.247 1428332168
EU.RACK01.FIRST.System.BytesSentPerSecond 1784.697 1428332168
EU.RACK01.FIRST.System.BytesReceivedPerSecond 6383.81 1428332168
만약 UDP 와 같이 비신뢰 전송을 사용할 때면 네트워크가 전송되는 동안 패킷의 단편화를 방지 하기 위해서 "MaxPayloadSize" 프로퍼티 설정을 해 볼만 합니다.
페이로드의 총 길이를 네트워크의 MTU 내로 유지하는 것에 주의를 기울이시기 바랍니다.
값은 환경에 따라 변할 수 있으므로 일반적인 네트워크 시나리오에 대한 가이드를 보여 드리겠습니다:
- 빠른 이더넷 (1432) - 인트라넷에서 가장 많이 사용 됩니다.
- 기가비트 이더넷 (8932) - Jumbo 프레임들은 더 효율적으로 이 기능을 사용할 수 있습니다.
- Commodity Internet (512) - 인터넷을 통해 라우팅되는 경우는 이 범위의 값이 합리적 입니다.
더 높은 값도 가능하지만 경로의 모든 홉을 제어 할 수 없습니다.
어플리케이션을 선택하고 다음과 같이 .config 를 변경하세요:
XML
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="Photon" type="Photon.SocketServer.Diagnostics.Configuration.PhotonSettings, Photon.SocketServer"/>
</configSections>
<Photon>
<CounterPublisher
enabled="True"
addDefaultAppCounter="True"
updateInterval="10"
senderType="ExitGames.Diagnostics.Configuration.GraphiteTextWriterSettings, ExitGamesLibs">
<Sender
protocol="ExitGames.Diagnostics.Monitoring.Protocol.Graphite.Text.GraphiteTextWriter, ExitGamesLibs"
endpoint="udp://127.0.0.1:2003"
senderId="{#CloudType#}.{#PrivateCloud#}.{#Region#}.{#Cluster#}.{0}"
initialDelay="10"
sendInterval="10"
maxQueueLength="720"
maxPayloadSize="512" />
</CounterPublisher>
</Photon>
</configuration>
또는
XML
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="Photon" type="Photon.SocketServer.Diagnostics.Configuration.PhotonSettings, Photon.SocketServer"/>
</configSections>
<Photon>
<CounterPublisher enabled="True">
<Sender
protocol="GraphiteText"
endpoint="udp://127.0.0.1:2003"
senderId="{#CloudType#}.{#PrivateCloud#}.{#Region#}.{#Cluster#}.{0}" />
</CounterPublisher>
</Photon>
</configuration>
"senderId" 프로퍼티는 통계 퍼블리셔 식별자로 나중에 식별 될 수 있습니다.
"senderId" 의 {0}
은 일반적으로 로컬 호스트 명으로 교체 됩니다.
"Graphite" 프로토콜 구현에 있어서 "senderId" 는 각 메트릭 키 발행의 끝에 붙여질 것 입니다.
만약 "addDefaultAppCounter" 가 사용불가로 되어 있다면 "CounterPublisher" 는 기본 "ApplicationBase" 카운터를 생략하게 됩니다."UpdateInterval" 은 초 단위로 샘플링 속도를 나타냅니다.
InfluxDB로 게시하기
Photon은 UDP상에서 Graphite 프로토콜을 사용한 InfluxDB를 지원 합니다. Writer 는 ExitGamesLibs
내부에서 구현되어 있습니다.
원조 Graphite 프로토콜과의 주요 차이점은 InfluxDB 가 구조화된 키를 기다리는 방식입니다.
"ProtocolType" 은 "InfluxDB090GraphiteText" 입니다.
전송 타입은 ExitGames.Diagnostics.Configuration.InfluxDb090TextWriterSettings
입니다.
Writer 타입은 ExitGames.Diagnostics.Monitoring.Protocol.InfluxDB090.Graphite.Text.GraphiteTextWriter
입니다.
텍스트 기반의 프로토콜 이며 형식은 다음과 같습니다:
metric_path value timestamp\n
metric_path
는 PATH[.PATH...]
형태 입니다. .
은 네임스페이스의 구분자 입니다.value
는 float 입니다.
timestamp
는 에포크(epoch) 부터의 초 단위의 unix 시간 입니다.
InfluxDB 0.9.0 은 다음 포맷으로 키를 기다립니다:
예: region.us-west.hostname.server01.cpu -> tags -> region: us-west, hostname: server01, point name -> cpu
use senderId = "CloudType.{#CloudType#}.PrivateCloud.{#PrivateCloud#}.Region.{#Region#}.Cluster.{#Cluster#}.Machine.{0}"
프로토콜 데이터 예제:
Region.EU.Rack.RACK01.PC.FIRST.NS.System.Cpu 1.53993 1428332168
Region.EU.Rack.RACK01.PC.FIRST.NS.System.CpuTotal 2.981617 1428332168
Region.EU.Rack.RACK01.PC.FIRST.NS.System.Memory 5317 1428332168
Region.EU.Rack.RACK01.PC.FIRST.NS.System.BytesTotalPerSecond 8103.247 1428332168
Region.EU.Rack.RACK01.PC.FIRST.NS.System.BytesSentPerSecond 1784.697 1428332168
Region.EU.Rack.RACK01.PC.FIRST.NS.System.BytesReceivedPerSecond 6383.81 1428332168
InfluxDB 는 .
구분자를 "separator" 프로퍼티를 이용하여 다른 것으로 변경 할 수 있습니다.
이 구분자는 메트릭 키 네임의 분리 태그에 사용 됩니다.키들을 다시쓰는 것은 "rewriteKeys" 를 통해 끌 수 있습니다.
만약 UDP 와 같이 비신뢰 전송을 사용할 때면 네트워크가 전송되는 동안 패킷의 단편화를 방지 하기 위해서 "MaxPayloadSize" 프로퍼티 설정을 해 볼만 합니다.
페이로드의 총 길이를 네트워크의 MTU 내로 유지하는 것에 주의를 기울이시기 바랍니다.
값은 환경에 따라 변할 수 있으므로 일반적인 네트워크 시나리오에 대한 가이드를 보여 드리겠습니다:
- 빠른 이더넷 (1432) - 인트라넷에서 가장 많이 사용 됩니다.
- 기가비트 이더넷 (8932) - Jumbo 프레임들은 더 효율적으로 이 기능을 사용할 수 있습니다.
- Commodity Internet (512) - 인터넷을 통해 라우팅되는 경우는 이 범위의 값이 합리적 입니다.
더 높은 값도 가능하지만 경로의 모든 홉을 제어 할 수 없습니다.
어플리케이션을 선택하고 다음과 같이 .config 를 변경하세요:
XML
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="Photon" type="Photon.SocketServer.Diagnostics.Configuration.PhotonSettings, Photon.SocketServer"/>
</configSections>
<Photon>
<CounterPublisher
enabled="True"
addDefaultAppCounter="True"
updateInterval="10"
senderType="ExitGames.Diagnostics.Configuration.InfluxDb090TextWriterSettings, ExitGamesLibs">
<Sender
protocol="ExitGames.Diagnostics.Monitoring.Protocol.InfluxDB090.Graphite.Text.GraphiteTextWriter, ExitGamesLibs"
endpoint="udp://127.0.0.1:2003"
senderId="CloudType.REALTIME.PrivateCloud.BLAH.Region.LOCAL.Cluster.EY.Machine.{0}"
initialDelay="10"
sendInterval="10"
maxQueueLength="720"
maxPayloadSize="512" />
</CounterPublisher>
</Photon>
</configuration>
또는
XML
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="Photon" type="Photon.SocketServer.Diagnostics.Configuration.PhotonSettings, Photon.SocketServer"/>
</configSections>
<Photon>
<CounterPublisher enabled="True">
<Sender
protocol="InfluxDB090GraphiteText"
endpoint="udp://127.0.0.1:2003"
senderId="CloudType.REALTIME.PrivateCloud.BLAH.Region.LOCAL.Cluster.EY.Machine.{0}" />
</CounterPublisher>
</Photon>
</configuration>
"senderId" 프로퍼티는 통계 퍼블리셔 식별자로 나중에 식별 될 수 있습니다.
"senderId" 의 {0}
은 일반적으로 로컬 호스트 명으로 교체 됩니다.
"Graphite" 프로토콜 구현에 있어서 "senderId" 는 각 메트릭 키 발행의 끝에 붙여질 것 입니다.
만약 "addDefaultAppCounter" 가 사용불가로 되어 있다면 "CounterPublisher" 는 기본 "ApplicationBase" 카운터를 생략하게 됩니다."UpdateInterval" 은 초 단위로 샘플링 속도를 나타냅니다.
StatsD로 게시하기
Photon은 StatsD를 지원 합니다. Writer 는 ExitGamesLibs
내부에서 구현되어 있습니다. UDP, TCP, PGM, HTTP 상의 모든 전송 레이어에서 동작 할 수 있습니다. StatsD의 디폴트 전송 레이어는 UDP 입니다.
"ProtocolType" 은 "StatsDText" 입니다.
전송 타입은 ExitGames.Diagnostics.Configuration.StatsDWriterSettings
입니다.
Write 타입은 ExitGames.Diagnostics.Monitoring.Protocol.StatsD.Text.StatsDTextWriter
입니다.
엑스포트된 메트릭의 포맷은 UTF-8 텍스트이며 메트릭스는 개행 문자로 구분 되어 집니다:
Metrics 는 일반적으로 <metric name>:<value>|<type>
형식을 가지며 예외들은 메트릭 타입에 기술 되어 있습니다.
이 프로토콜은 정수와 부동 소수점 값 두 개 모두 사용 할 수 있습니다. 가장 최대로 저장 할 수 있는 값은 IEEE 754 double precision float 이지만 대부분의 구현과 그래프 시스템에서는 정수 값만을 지원 합니다. 모든 값에 대한 호환을 위해 (-253, 253) 값의 범위에 있어야 합니다.
프로토콜 데이터의 예제:
REALTIME/PUBLIC/LOCAL/FIRST.System.Cpu:0.472394|c
REALTIME/PUBLIC/LOCAL/FIRST.System.CpuTotal:4.921546|c
REALTIME/PUBLIC/LOCAL/FIRST.System.Memory:5040|c
REALTIME/PUBLIC/LOCAL/FIRST.System.BytesTotalPerSecond:274.1134|c
REALTIME/PUBLIC/LOCAL/FIRST.System.BytesSentPerSecond:247.9789|c
REALTIME/PUBLIC/LOCAL/FIRST.System.BytesReceivedPerSecond:25.77675|c
만약 UDP 와 같이 비신뢰 전송을 사용할 때면 네트워크가 전송되는 동안 패킷의 단편화를 방지 하기 위해서 "MaxPayloadSize" 프로퍼티 설정을 해 볼만 합니다.
페이로드의 총 길이를 네트워크의 MTU 내로 유지하는 것에 주의를 기울이시기 바랍니다.
값은 환경에 따라 변할 수 있으므로 일반적인 네트워크 시나리오에 대한 가이드를 보여 드리겠습니다:
- 빠른 이더넷 (1432) - 인트라넷에서 가장 많이 사용 됩니다.
- 기가비트 이더넷 (8932) - Jumbo 프레임들은 더 효율적으로 이 기능을 사용할 수 있습니다.
- Commodity Internet (512) - 인터넷을 통해 라우팅되는 경우는 이 범위의 값이 합리적 입니다.
더 높은 값도 가능하지만 경로의 모든 홉을 제어 할 수 없습니다.
어플리케이션을 선택하고 다음과 같이 .config 를 변경하세요:
XML
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="Photon" type="Photon.SocketServer.Diagnostics.Configuration.PhotonSettings, Photon.SocketServer"/>
</configSections>
<Photon>
<CounterPublisher
enabled="True"
addDefaultAppCounter="True"
updateInterval="10"
senderType="ExitGames.Diagnostics.Configuration.StatsDWriterSettings, ExitGamesLibs">
<Sender
protocol="ExitGames.Diagnostics.Monitoring.Protocol.StatsD.Text.StatsDTextWriter, ExitGamesLibs"
endpoint="udp://127.0.0.1:8125"
senderId="REALTIME/PUBLIC/LOCAL/{0}"
initialDelay="10"
sendInterval="10"
maxQueueLength="720"
maxPayloadSize="512" />
</CounterPublisher>
</Photon>
</configuration>
또는
XML
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="Photon" type="Photon.SocketServer.Diagnostics.Configuration.PhotonSettings, Photon.SocketServer"/>
</configSections>
<Photon>
<CounterPublisher enabled="True">
<Sender
protocol="StatsDText"
endpoint="udp://127.0.0.1:8125"
senderId="REALTIME/PUBLIC/LOCAL/{0}" />
</CounterPublisher>
</Photon>
</configuration>
"senderId" 프로퍼티는 통계 퍼블리셔 식별자로 나중에 식별 될 수 있습니다.
"senderId" 의 {0}
은 일반적으로 로컬 호스트 명으로 교체 됩니다.
"StatsD" 프로토콜 구현에 있어서 "senderId" 는 각 메트릭 키 발행의 끝에 붙여질 것 입니다.
만약 "addDefaultAppCounter" 가 사용불가로 되어 있다면 "CounterPublisher" 는 기본 "ApplicationBase" 카운터를 생략하게 됩니다. "UpdateInterval" 은 초 단위로 샘플링 속도를 나타 냅니다.
NewRelic Platform으로 게시하기
New Relic의 SaaS-기반 어플리케이션 성능 모니터링은 멋진 웹 소프트웨어를 구축, 디플로이와 유지보수에 도움을 줍니다.
메트릭스를 "CounterPublisher"와 같이 NewRelic Platform에 게시하기 위한 CounterPublisher.NewRelic
안에 writer plugin 이 분리되어 구현되어 있습니다.
이것은 HTTP/HTTPS 상의 NewRelic API를 호출 하기 위해서 원시 NewRelic SDK 클라이언트를 사용합니다.
이 플러그인을 사용하기 위해 "CounterPublisher" 환경 설정을 변경 하는것 외에 설정하고자 하는 모든 디펜던시를 어플리케이션 내로 복사 해야 합니다.
의존성에는 다음 사항들이 포함됩니다:
config/newrelic.json
CounterPublisher.NewRelic.dll
CounterPublisher.NewRelic.dll.config
CounterPublisher.NewRelic.pdb
NewRelic.Platform.Sdk.dll
NewRelic.Platform.Sdk.pdb
Newtonsoft.Json.dll
Newtonsoft.Json.xml
NLog.dll
NLog.xml
ExitGames 의존성은 어플리케이션 자체에서 제공되어야 합니다:
ExitGames.Logging.Log4Net.dll
ExitGames.Logging.Log4Net.pdb
ExitGames.Logging.Log4Net.xml
ExitGamesLibs.dll
ExitGamesLibs.pdb
ExitGamesLibs.xml
log4net.dll
전송자 타입은 ExitGames.Diagnostics.Configuration.NewRelicAgentSettings
입니다.
Writer 타입은ExitGames.Diagnostics.Monitoring.Protocol.NewRelic.Agent.NewRelicWriter
입니다.
메트릭 데이터는 다음 URI를 사용하여 JSON 데이터의 HTTP POST 로 전송 됩니다:
https://platform-api.newrelic.com/platform/v1/metrics.
POST의 MIME-type 은 application/json
입니다.
The New Relic 플러그인 제품들은 매 60초 주기로 데이터를 post 하는 것에 최적화 되어 있습니다.
POST 주기와 제한에 대해서는 문서를 참고 하세요:
- 컴포넌트: 현재 계정당 추적되는 500개의 유일한 컴포넌트
- 컴포넌트당 메트릭스: 컴포넌트당 총 10,000 개의 유일한 메트릭스. 메트릭 이름이 너무 동적으로 작성되지 않도록 주의 해주세요. 개별 포스트내로 보내지는 메트릭스의 수가 작을 지라도 시간이 경과 함에 따라서 큰 갯수의 유일한 매트릭스를 이루게 됩니다. 이 제한을 넘어서게 된다면 서버는 메트릭스 이름을 * 로 같이 통합하는 것을 시도 할 수 있습니다.
- 포스트당 메트릭스: 포스트당 20,000개의 메트릭스 전송 수. 포스트는 요청내의 메트릭스 총 개수가 이 제한을 넘어서지 않는 다면 단일 요청안에 여러개의 컴포넌트의 데이터를 전송할 수 있습니다.
- 포스트 주기: 갱신 주기 분당 2회. 에이전트들은 분당 1회 이내로 전송하는 것을 예측하고 있습니다.
NewRelic 시작 하기:
- NewRelic 계정 등록
- 프로필 설정에서 "LicenseKey" 얻기
- 디펜던시(dependencies)를 어플리케이션에 복사
- 환경설정
- agentId, agentName, agentVersion에 대하여 생각해 보기
제약사항:
- 전송 간격은 60초 보다 작을 수 없습니다.
- 전송간격으로 플러그인은 통합된 데이터를 항상 전송합니다 :최소, 최대, 평방제곱의 합, 개수
- 플러그인은 빈 루트 네임스페이스에 대한 메트릭은 지원하지 않습니다.
- Photon CounterPublisher의 키 포맷을 형성하는 규칙이 있습니다.
(일반적으로:[Namespace.]Key
) 로 NewRelic 의 키로 지정합니다:
카운터 포맷 : System.CPU
또는 System.Memory
또는 System.BytesInPerSecond
메트릭 포맷: Component/Label[/Attribute/...]
트랜스폼: System.CPU.Load
-> System.CPU/Load[/SenderId]
명명 규칙과 카운터의 적당한 포맷 규칙에 대해서는 카운터 스키마를 참고 하시기 바랍니다.
어플리케이션을 선택하고 다음과 같이 .config 를 변경하세요:
XML
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="Photon" type="Photon.SocketServer.Diagnostics.Configuration.PhotonSettings, Photon.SocketServer"/>
</configSections>
<Photon>
<CounterPublisher
enabled="True"
addDefaultAppCounter="True"
updateInterval="10"
senderType="ExitGames.Diagnostics.Configuration.NewRelicAgentSettings, CounterPublisher.NewRelic">
<Sender
protocol="ExitGames.Diagnostics.Monitoring.Protocol.NewRelic.Agent.NewRelicWriter, CounterPublisher.NewRelic"
senderId="{#CloudType#}/{#PrivateCloud#}/{#Region#}/{#Cluster#}/{0}"
agentId="com.exitgames.plugins.newrelic.agent"
agentName="Photon: {0}"
version="1.0.0"
licenseKey="..."
initialDelay="60"
sendInterval="60" />
</CounterPublisher>
</Photon>
</configuration>
또는
XML
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="Photon" type="Photon.SocketServer.Diagnostics.Configuration.PhotonSettings, Photon.SocketServer"/>
</configSections>
<Photon>
<CounterPublisher
enabled="True"
senderType="ExitGames.Diagnostics.Configuration.NewRelicAgentSettings, CounterPublisher.NewRelic">
<Sender
protocol="ExitGames.Diagnostics.Monitoring.Protocol.NewRelic.Agent.NewRelicWriter, CounterPublisher.NewRelic"
senderId="{#CloudType#}/{#PrivateCloud#}/{#Region#}/{#Cluster#}/{0}"
licenseKey="..."
agentName="ExitGames Photon.CounterPublisher local test"
initialDelay="60"
sendInterval="60" />
</CounterPublisher>
</Photon>
</configuration>
"senderId" 프로퍼티는 통계 퍼블리셔 식별자로 나중에 식별 될 수 있습니다.
"senderId" 의 {0}
은 일반적으로 로컬 호스트 명으로 교체 됩니다.
"NewRelic" 프로토콜 구현에 있어서 "senderId" 는 각 메트릭 키 발행의 끝에 붙여질 것 입니다.
만약 "addDefaultAppCounter" 가 사용불가로 되어 있다면 "CounterPublisher" 는 기본 "ApplicationBase" 카운터를 생략하게 됩니다."UpdateInterval" 은 초 단위로 샘플링 속도를 나타 냅니다.
Amazon AWS CloudWatch 으로 게시하기
Amazon CloudWatch 는 AWS cloud resources와 AWS 에서 수행되는 어플리케이션에 대한 모니터링 서비스 입니다. 메트릭스를 추적하고 수집, 로그 파일의 수집과 모니터링, 알람 설정을 위해서 Amazon CloudWatch 를 사용할 수 있습니다.
Amazon CloudWatch 는 어플리케이션과 서비스에서 생성된 커스텀 메트릭스 뿐만 아니라 Amazon EC2 인스턴스, Amazon DynamoDB 테이블, Amazon RDS DB 인스턴스와 같은 AWS 리소스를 모니터링 할 수 있습니다.
Amazon CloudWatch 는 리소스 활용도, 어플리케이션 성능과 운영 상태를 시스템 측면에서 시각적으로 보는데 사용할 수 있습니다.
이러한 기능을 통하여 어플리케이션을 원활 하게 수행할 수 있게 상황에 대처할 수 있도록 활용 할 수 있습니다.
"CounterPublisher" 를 통해 Amazon CloudWatch로 메트릭스를 발행 하려면 분리된 CounterPublisher.AWS.CloudWatch
에 Writer 플러그인 구현을 이용하시기 바랍니다.
Amazon SDK CloudWatch 클라이언트를 이용하여 HTTP/HTTPS 상의 API를 호출 합니다.
이 플러그인을 사용하기 위해 "CounterPublisher" 환경 설정을 변경 하는것 외에 설정하고자 하는 모든 디펜던시를 어플리케이션 내로 복사 해야 합니다.
의존성에는 다음 사항들이 포함됩니다:
CounterPublisher.AWS.CloudWatch.dll
CounterPublisher.AWS.CloudWatch.dll.config
CounterPublisher.AWS.CloudWatch.pdb
최소 SDK 버전은 2.3.24.3 입니다:
AWSSDK.dll
AWSSDK.xml
ExitGames 의존성은 어플리케이션 자체에서 제공 되어야 합니다:
ExitGames.Logging.Log4Net.dll
ExitGames.Logging.Log4Net.pdb
ExitGames.Logging.Log4Net.xml
ExitGamesLibs.dll
ExitGamesLibs.pdb
ExitGamesLibs.xml
log4net.dll
Sender 타입은 ExitGames.Diagnostics.Configuration.AWSCloudWatchSettings
입니다.
Writer 타입은 ExitGames.Diagnostics.Monitoring.Protocol.AWS.CloudWatch.AWSCloudWatchWriter
입니다.
Amazon Cloudwatch는 특정 메트릭과 같이 데이터 포인트와 관련 되어 있습니다.
만약 특정 메트릭이 존재하지 않는다면 Amazon CloudWatch 는 그 메트릭을 생성 합니다.
새로운 메트릭이 list-metrics 액션 호출에 나타날때 까지는 15분 정도 소요될 수 있습니다.
put-metric-datarequest의 크기는 HTTP GET 요청에서 8 KB 까지 제한되어 있으면 HTTP POST 요청은 40KB 까지 제한되어 있습니다.
1/1000 초 단위로 타임 스탬프의 데이터 포인트를 게시 할 수 있지만 CloudWatch 는 분단위로의 최소입자로 데이터를 통합 합니다.
CloudWatch 는 매 1분 주기마다 샘플의 갯수, 최대값, 최소값은 물론 수신된 값의 평균(아이템의 총 합계를 아이템의 총 개수로 나눔)을 기록 합니다.
CloudWatch를 시작 하기 위해서:
- Amazon AWS 계정에 등록
- 프로필 설정에서 "AccessKey", "SecretKey" 취득
- 선호 지역과 CloudWatch 커스텀 메트릭스 네임스페이스(즉, ExitGames/PhotonTest) 에 따라서 서비스 url을 선택 합니다.
- 의존성 파일을 어플리케이션에 복사
- 환경설정
제약 사항:
- 전송 간격은 60초 보다 작을 수 없습니다.
- 전송 간격으로 플러그인은 통합된 데이터를 항상 전송합니다 :최소, 최대, 평방제곱의 합, 개수
- 각 메트릭은 다음의 배열들이 프로모트 됩니다:senderId, instanceId, autoScalingGroupName.
- 플러그인은 빈 루트 네임스페이스에 대한 메트릭은 지원하지 않습니다.
- 플러그인은 내부 측정방식의 선택을 위한 공통 데이터 크기 타입과 "Per" 접미사를 기반으로 유닛 타입을 감지하려고 합니다.
- 메트릭 이름을 현명하게 선택하는 것이 중요 합니다.(일반적으로:
[Namespace.]Key
입니다)
명명 규칙과 카운터의 적당한 포맷 규칙에 대해서는 카운터 스키마를 참고 하시기 바랍니다.
어플리케이션을 선택하고 다음과 같이 .config 를 변경하세요:
XML
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="Photon" type="Photon.SocketServer.Diagnostics.Configuration.PhotonSettings, Photon.SocketServer"/>
</configSections>
<Photon>
<CounterPublisher
enabled="True"
addDefaultAppCounter="True"
updateInterval="10"
senderType="ExitGames.Diagnostics.Configuration.AWSCloudWatchSettings, CounterPublisher.AWS.CloudWatch">
<Sender
protocol="ExitGames.Diagnostics.Monitoring.Protocol.AWS.CloudWatch.AWSCloudWatchWriter, CounterPublisher.AWS.CloudWatch"
senderId="{#CloudType#}/{#PrivateCloud#}/{#Region#}/{#Cluster#}/{0}"
awsCloudWatchAccessKey = "..."
awsCloudWatchSecretKey = "..."
awsCloudWatchServiceUrl = "..."
awsCloudWatchNamespace = "..."
initialDelay="60"
sendInterval="60" />
</CounterPublisher>
</Photon>
</configuration>
"senderId" 프로퍼티는 통계 퍼블리셔 식별자로 나중에 식별 될 수 있습니다.
"senderId" 의 {0}
은 일반적으로 로컬 호스트 명으로 교체 됩니다.
"CloudWatch" 프로토콜 구현에 있어서 "senderId" 는 각 메트릭 키 발행에 붙여질 것 입니다.
커스텀 성능 카운터 구현
아키텍쳐에 대한 상세내용은 사용법/카운터 스키마를 살펴 보세요.
우선, 어플리케이션에서 추적해야할 값들이 필요 합니다. 우리는 ExitGames.Diagnostics.Counter
의 내부 메모리 카운터를 이 목적에 사용할 것 입니다.
어필리케이션에서 /lib 폴더의 ExitGamesLibs.dll 에 대한 참조를 가지고 있는지 확인 해 보세요:
카운터 선언
다음 단계는 카운터 정의 클래스를 생성 하는 것 입니다. ExitGames.Diagnostics.Counter
와 ExitGames.Diagnostics.Monitoring
를 "using" 지시어를 이용하여 추가 하고 아래에 보인 것 처럼 커스텀 카운터를 선언 합니다. 유일한 이름을 가진 PublishCounter
속성을 추가합니다; 카운터 퍼블리셔에 의해서 카운터 값이 게시되는 것을 확신 하는 것 입니다(아래 참조).
C#
using ExitGames.Diagnostics.Counter;
using ExitGames.Diagnostics.Monitoring;
public static class MyCustomCounter
{
[PublishCounter(MessagesPerSecond")]
public static readonly CountsPerSecondCounter MessagesPerSecond = new CountsPerSecondCounter();
}
명명법과 카운터의 올바른 형식에 대해서는 카운터 스키마의 규칙을 참고 하세요.
카운터 사용방법
코드의 적당한 위치에 카운터의 증감을 해 줍니다. 예를 들어, 1초당 전송된 메시지의 개수는 SendMessage
오퍼레이션을 처리하는 메소드에 다음의 코드를 추가 합니다:
C#
protected virtual void HandleSendMessageOperation(LitePeer peer, OperationRequest operationRequest)
{
// [... operation logic ...]
// increment performance counter:
MyCustomCounter.MessagesPerSecond.Increment();
}
다 되었습니다 - 이제 성능 데이터 수집에 필요한 모든 것을 완료 하셨습니다..
카운터 퍼블리셔 초기 내용 설정
다음 단계는 수집된 성능 데이터를 게시 하는 것 입니다.
이것을 하기 위하여 어플리케이션이 시작 하는 동안 "CounterPublisher" 의 초기 설정이 필요 합니다.
어플리케이션의 "Setup" 메소드가 이것을 처리하는 아주 좋은 장소 입니다.
이 예제에서는 카운터 퍼블리셔의 초기 설정 방법과 커스텀 카운터 정의 클래스를 추가하는 것을 보여 주고 있습니다.
두 번째 파라미터에 대해서는 임의의 이름을 정할 수 있습니다 - 나중에 관리화면에서 표시될 카운터의 카테고리로 사용 되게 됩니다.
C#
protected override void Setup()
{
// [... setup logic ...]
// initialize counter publisher and add your custom counter class(es):
if (PhotonSettings.Default.CounterPublisher.Enabled)
{
// counters for the photon dashboard
CounterPublisher.DefaultInstance.AddStaticCounterClass(typeof(MyCustomCounter), "MyApplication");
CounterPublisher.DefaultInstance.Start();
}
}
또는 .NET Photon 어플리케이션 환경설정 파일을 확장하여 인-메모리 메트릭스를 <Counters/Schema>
설정 항목에 게시 할 수 있습니다.
XML
<Photon>
<CounterPublisher ... >
<Sender ... />
<Counters>
<Schema namespace="MyApplication" type="...MyCustomCounter, YOUR_LIB_NAME" />
</Counters>
</CounterPublisher>
</Photon>
카운터 퍼블리셔 환경 설정
마지막 단계는 카운터 퍼블리셔의 적절한 환경을 추가하는 것 입니다. 시계열 데이터베이스가 실행되고 있는 곳으로 데이터를 전송할 IP / 포트를 설정 합니다. 멀티캐스팅은 동일한 서브넷에서만 동작하는 것을 기억해 주세요; 네트워크가 다른 곳에서 성능 데이터를 게시하기 위해서는 고정 IP 를 사용하고 방화벽에서 포트가 열려 있는지 확인 해 주세요.
이 메뉴얼의 사용법에 대한 주제를 살펴 보시기 바랍니다.
예제:
XML
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="Photon" type="Photon.SocketServer.Diagnostics.Configuration.PhotonSettings, Photon.SocketServer"/>
</configSections>
<Photon>
<CounterPublisher enabled="True">
<Sender
protocol="PhotonBinary"
endpoint="udp://127.0.0.1:40001"
senderId="servers/Realtime/Public/Local/Test/{0}" />
<Counters>
<Schema namespace="MyApplication" type="...MyCustomCounter, YOUR_LIB_NAME" />
</Counters>
</CounterPublisher>
</Photon>
</configuration>
커스텀 프로토콜 구현
어떻게 처리가 되는지 더 많은 이해를 위해 CounterPublisher.AWS.CloudWatch
프로젝트 , CounterPublisher.NewRelic
프로젝트,Application 프로토콜 주제를 살펴 보세요.
커스텀 어플리케이션 프로토콜의 구현에 대한 기본 개념은 분리된 .NET 라이브러리(dll)을 생성하고:
- 필요할 경우
ExitGames.Diagnostics.Configuration.CounterSampleSenderSettings
에 기반한
설정 클래스 확장을 구현 합니다. - 메인 엔트리 포인트인
ExitGames.Diagnostics.Monitoring.Protocol.ICounterSampleWriter
Writer 인터페이스를
구현 합니다. - app.config 파일에 다음과 같은 샘플 환경설정을 제공 합니다:
XML
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="Photon" type="Photon.SocketServer.Diagnostics.Configuration.PhotonSettings, Photon.SocketServer"/>
</configSections>
<Photon>
<CounterPublisher
enabled="True"
addDefaultAppCounter="True"
updateInterval="10"
senderType="ExitGames.Diagnostics.Configuration.AWSCloudWatchSettings, CounterPublisher.AWS.CloudWatch">
<Sender
protocol="ExitGames.Diagnostics.Monitoring.Protocol.AWS.CloudWatch.AWSCloudWatchWriter, CounterPublisher.AWS.CloudWatch"
senderId="{#CloudType#}/{#PrivateCloud#}/{#Region#}/{#Cluster#}/{0}"
awsCloudWatchAccessKey = "..."
awsCloudWatchSecretKey = "..."
awsCloudWatchServiceUrl = "..."
awsCloudWatchNamespace = "..."
initialDelay="60"
sendInterval="60" />
</CounterPublisher>
</Photon>
</configuration>
카운터 writer 인터페이스
ExitGames.Diagnostics.Monitoring.Protocol.ICounterSampleWriter
프로토콜 플러그인에 들어가기 위한 메인 엔트리 포인트 입니다.
Writer 인 ExitGames.Diagnostics.Monitoring.Protocol.PhotonBinaryWriterBase
의 기본 추상 구현이 있는데 이것은 슈퍼 샘플된 데이터 통합의 추가적인 큐를 제공 합니다.
ICounterSampleWriter
메소드를 구현합니다:
C#
public interface ICounterSampleWriter : IDisposable
{
/// <summary>
/// Is writer ready to publish any data.
/// IsConnected status is subset of this status.
/// Default implementation is writer started and connected.
/// </summary>
bool Ready { get; }
/// <summary>
/// Start writing.
/// Stop is handled by IDisposable implementation.
/// Can be called once.
/// </summary>
void Start(CounterSampleSenderBase sender);
/// <summary>
/// Called by <see cref="CounterSampleSenderBase"/>
/// to write samples out to some storage.
/// </summary>
void Publish(CounterSampleCollection[] packages);
}
환경설정
기본 환경 설정 클래스는 ExitGames.Diagnostics.Configuration.CounterSampleSenderSettings
입니다.
"Writer" 에 설정되도록 추가적인 파라미터들이 필요할 경우에 확장 할 수 있습니다.
C#
public class InfluxDB090TextWriterSettings : GraphiteTextWriterSettings
{
/// <summary>
/// Do rewriting of keys provided by sampler to keep them distinct to tags part of the path.
/// </summary>
[ConfigurationProperty("rewriteKeys", IsRequired = false, DefaultValue = true)]
public bool RewriteKeys
{
get
{
return (bool)this["rewriteKeys"];
}
set
{
this["rewriteKeys"] = value;
}
}
/// <summary>
/// Separator used by InfluxDB instead of default DOT(.).
/// </summary>
[ConfigurationProperty("separator", IsRequired = false, DefaultValue = '.')]
public char Separator
{
get
{
return (char)this["separator"];
}
set
{
this["separator"] = value;
}
}
public InfluxDB090TextWriterSettings() { }
public InfluxDB090TextWriterSettings(CounterSampleSenderSettings settings) : base(settings) { }
}
사용법
플러그인을 사용하기 위해서:
- 어플리케이션에 의존 파일을 복사 합니다.
- 필요시 유효한 "Writer" 타입으로 환경을 설정하고 "환경설정" 합니다.
예제:
XML
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="Photon" type="Photon.SocketServer.Diagnostics.Configuration.PhotonSettings, Photon.SocketServer"/>
</configSections>
<Photon>
<CounterPublisher enabled="True">
<Sender
protocol="InfluxDB090GraphiteText"
endpoint="udp://127.0.0.1:2003"
senderId="CloudType.REALTIME.PrivateCloud.BLAH.Region.LOCAL.Cluster.EY.Machine.{0}" />
</CounterPublisher>
</Photon>
</configuration>
문제해결
- 카운터 게시가 사용할 수 있도록 되어 있나요? 어플리케이션의 환경 설정 파일을 검토 해 보세요.
즉,/deploy/CounterPublisher/bin/CounterPublisher.dll.config 파일 입니다. - 에러와 목적지 데이터 베이스 로그파일에 대해서는
/deploy/log/* 에서 Photon 로그파일을 체크 해주세요. - 방화벽에서 필요한 포트가 열려 있는지 확인 해주세요.
- 로그에 데이터가 게시되고 있는지 확인 해주세요 (log4net 에서
ExitGames.Diagnostics
을
DEBUG 로 설정 합니다.), 패킷은 (wireshark sniffer를 사용 합니다). - sniffer와
netstat
를 이용하여 패킷 IP/포트 원천지/ 목적지를 체크 합니다. Check packets ip / port source / - sniffer 이용 및 로그 레벨을 확장하여 목적지 데이터베이스가 패킷을 수신 하는지 체크 합니다.
- 데이터의 포맷과 프로토콜이 검토된 데이터 패킷인지 검토 합니다.
- 어떤 카운터와 값들이 게시 되었는지 보기 위해서
ExitGames.Diagnostics
패키지의
로그 레벨은DEBUG
레벨로 /CounterPublisher/bin/log4net.config 에서 강제로 설정 합니다.
그리고 로그를 Photon/Log/CounterPublisher.log (이 경로는 log4net.config 내의 LogFileAppender 설정에서 지정되어 있음) 에서 확인 합니다:
XML
<logger name="ExitGames.Diagnostics">
<level value="DEBUG" />
</logger>
설정 목록
ExitGames.Diagnostics.Configuration.CounterSampleSenderSettings
:
(<Photon><CounterPublisher><Sender> 속성...
)
endpoint=""
, 필수protocol="PhotonBinary"
, 필수,
대소문자 구별되는 프로토콜 타입 또는 커스텀 Writer 타입 구현.senderId=""
,
전송자의 id로 카운터 데이터와 같이 전송됨.initialDelay="10"
,
첫 번째 데이터가 게시될 때 까지 지연 시간sendInterval="10"
,
초 단위의 게시 간격maxQueueLength="120"
,
게시할 동안에 발생된 에러로 인하여 재게시를 위하여 큐에 들어가야 하는 패킷의 개수maxRetryCount="-1"
,
게시될 때 오류로 인하여 카운터 퍼블리셔가 게시를 중지하는 개수를 의미 합니다.
만약 0 보다 작은 값이라고 하면 오류가 발생 해도 절대로 중단 하지 않습니다.
모든 어플리케이션 프로토콜 종류에 지정하는 설정이 또한 존재 합니다.
ApplicationBase 의 카운터 리스트
Photon.SocketServer.Diagnostics.PhotonCounter
에 의해 구현된 매트릭스입니다.
"ApplicationBase" 에 등록되었을 때 네임스페이스는 어플리케이션 이름과 동일할 것 입니다.
{ApplicationName}.AvrgOpExecTime
, 평균 오퍼레이션 실행 시간.{ApplicationName}.EventsSentCount
, 전송한 이벤트 수.{ApplicationName}.EventsSentPerSec
, 초당 전송한 이벤트.{ApplicationName}.MessagesSentCount
, 메시지(객체 메시지)전송 수.{ApplicationName}.MessagesSentPerSec
, 초당 메시지(객체 메시지)전송 수.{ApplicationName}.RawMessagesSentCount
, 원시 메시지(byte[]) 전송 수.{ApplicationName}.RawMessagesSentPerSec
, 초당 원시 메시지(byte[])전송 수.{ApplicationName}.InitPerSec
, 초당 init.{ApplicationName}.OpReceiveCount
, 오퍼레이션 수신 수.{ApplicationName}.OpReceivePerSec
, 초당 오퍼레이션 수신 수.{ApplicationName}.OpResponseCount
, 오퍼레이션 응답 수.{ApplicationName}.OpResponsePerSec
, 초당 오퍼레이션 응답 수.{ApplicationName}.OperationsFast
, 빠른 오퍼레이션{ApplicationName}.OperationsMaxTime
, 최대 오퍼레이션 시간{ApplicationName}.OperationsMiddle
, 초당 오퍼레이션 중간값{ApplicationName}.OperationsSlow
, 초당 느린 오퍼레이션{ApplicationName}.SessionCount
, 세션 수
ExitGames.Diagnostics.Counter 카운터 리스트
ExitGames.Diagnostics.Counter
네임스페이스에 대한 인-메모리 카운터에서 사용할 수 있는 타입에 대하여 좀 더 자세히 다루어 보겠습니다.
모든 카운터들은 ICounter
인터페이스를 구현합니다::
C#
namespace ExitGames.Diagnostics.Counter
{
public interface ICounter
{
string Name { get; }
// Gets the type of the counter.
CounterType CounterType { get; }
// Gets the next value.
float GetNextValue();
// Increments the counter by one and returns the new value.
long Increment();
// Increments the counter by a given value and returns the new value.
long IncrementBy(long value);
// Decrements the counter by one and returns the new value.
long Decrement();
}
}
본 바와 같이 카운터 값에 대한 증/감을 위한 주요 메소드들이 있습니다.
GetNextValue
는 카운터의 실제 "값"을 리턴 해주는 메소드입니다.
이것은 값을 계산 할 수 도 있습니다 - 예를들어 AverageCounter 의 GetNextValue
를 호출 했을 때 이전의 GetNextValue
호출에 대한 카운터는 모든 증/감 에 대한 평균을 계산하여 값을 리턴 해줍니다.
GetNextValue
는 내부 값을 리셋 합니다 - 절대로 코드에서 수동으로 호출 하면 안됩니다. 그렇지 않으면 게시된 데이터가 맞지 않게 됩니다. "CounterPublisher" 는 정기적 주기로 GetNextValue
를 호출하도록 작성됩니다.
NumericCounter
아주 직관적인 카운터 입니다. 단일 값을 가지고 있습니다;
GetNextValue
는 단일 값을 리턴하고 카운터를 리셋 하지 않습니다.
예제: 10초 간격의 시작에서 NumericCounter의 값이 5 입니다. 1과 6으로 두번 증가되었고 3의 값으로 한번 감소 되었습니다. 따라서 최종 결과값은 5+1+6-3 = 9 입니다.
전형적인 유즈 케이스: 시스템에 현재 로그인 한 사용자 수
C#
public void AddToCache(ArrayList items)
{
foreach (var item in items)
{
Cache.Insert(item);
}
MyCacheItemCounter.IncrementBy(items.Count);
}
public void RemoveFromCache(ArrayList items)
{
foreach (var item in items)
{
Cache.Remove(item);
}
MyCacheItemCounter.IncrementBy( -items.Count);
}
// When the CounterPublisher calls MyCacheItemCounter.GetNextValue(), it always returns the current number of items in cache.
AverageCounter
AverageCounter 는 최근에 리셋된 이후 부터 얼마나 자주 호출 되었는지를 추적하고, 어떤 값으로든 증가 될 수 있습니다.
현재 간격에서 호출당 평균량을 리턴 합니다( = 총 량 / 호출 #)
예제: 10초 간격에서 AverageCounter 가 1,2,4,5의 값으로 4번 증가 되었습니다. 총 12 이며 평균은 이 간격에서는 12/4 = 3 입니다.
전형적 유즈케이스: 특정 오퍼레이션의 평균 실행시간 또는 전송된 메시지당 평균 텍스트 길이
C#
public void WinGame(Player player, int coins)
{
player.Account.Add(coins);
AverageCoinsWonCounter.IncrementBy(coins);
}
public void LoseGame(Player player, int coins)
{
player.Account.Remove(coins);
AverageCoinsWonCounter.IncrementBy( -coins);
}
// When the CounterPublisher calls AverageCoinsWonCounter.GetNextValue(), it returns the average amount a player has won in the interval since the previous call to GetNextValue().
// This amount might as well be negative. The internal counter value is reset afterwards - i.e., if no Game was won or lost between two calls to GetNextValue(), the average is 0.
CountsPerSecondCounter
CountsPerSecondCounter 는 단일 값을 갖고 있으며, 어떤 값으로도 증가 및 감소가 가능 합니다.
이 카운터는 최근 인터벌에서 초당 평균 량을 리턴 해줍니다.
해 주어야 할 것은 카운터를 증가/감소 하는 것이고 자동적으로 "초당"으로 이러한 호출을 변환 해줍니다.
예제: 10초 간격에서 CountsPerSecondCounter 10,20,70 으로 3번 증가 했습니다. 총 100 입니다.
결과적으로 초당 10 의 값이 됩니다.
전형적인 유즈케이스: 네트워크 인터페이스 상에서 초당 전송된 바이트의 수 또는 초당 발생된 특정 액션에 대한 횟수
C#
public void RaiseEvent()
{
// do something to raise an event
EventsPerSecondCounter.Increment();
}
// RaiseEvent can be called at any time - multiple times per second, or only once every few seconds, and requires no fixed interval.
// When the CounterPublisher calls EventsPerSecondCounter.GetNextValue(), the counter checks how many seconds have passed since the the last call to GetNextValue().
// It calculates it's return value as "CurrentValue / SecondsPassed". The internal value is reset when GetNextValue() is called.
PerformanceCounterReader
PerformanceCounterReader 의 목적은 Windows 성능 카운터에 있는 값을 읽기 위한 것입니다.
읽기 전용 카운터로 증가/감소를 할 수 없습니다. 이것은 안전하기 때문에 성능 카운터가 존재하지 않거나 액세스가 허용되지 않는 경우에도 오류를 발생 시키지 않습니다.
WindowsPerformanceCounter
WindowsPerformanceCounter
는 Windows 성능 카운터의 래퍼(wrapper) 클래스입니다. Windows 성능 카운터의 읽고 쓰기 권한을 제공 합니다. 성능 카운터가 있어야 하고 어플리케이션의 읽기/쓰기 권한이 적절하게 부여 되어 있지 않으면 예외가 발생 합니다.
Windows 성능 카운터에 대한 자세한 내용은 MSDN을 참조하시기 바라며 시작 하기 좋은 문서 입니다.
Back to top- 시작하기Markdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline
- 성능 카운터Markdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline
- In-Memory 카운터Markdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline
- Windows 성능 카운터Markdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline
- 사용방법Markdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline
- 개요Markdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline
- 아키텍쳐Markdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline
- 전송 프로토콜Markdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline
- 어플리케이션 프로토콜Markdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline
- Counters 스키마Markdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline
- Windows 성능 카운터 게시하기Markdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline
- Photon 관리화면에 게시하기Markdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline
- Graphite 로 게시하기Markdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline
- InfluxDB로 게시하기Markdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline
- StatsD로 게시하기Markdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline
- NewRelic Platform으로 게시하기Markdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline
- Amazon AWS CloudWatch 으로 게시하기Markdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline
- 커스텀 성능 카운터 구현Markdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline
- 카운터 선언Markdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline
- 카운터 사용방법Markdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline
- 카운터 퍼블리셔 초기 내용 설정Markdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline
- 카운터 퍼블리셔 환경 설정Markdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline
- 커스텀 프로토콜 구현Markdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline
- 카운터 writer 인터페이스Markdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline
- 환경설정Markdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline
- 사용법Markdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline
- 문제해결Markdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline
- 설정 목록Markdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline
- ApplicationBase 의 카운터 리스트Markdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline
- ExitGames.Diagnostics.Counter 카운터 리스트Markdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline
- NumericCounterMarkdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline
- AverageCounterMarkdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline
- CountsPerSecondCounterMarkdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline
- PerformanceCounterReaderMarkdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline
- WindowsPerformanceCounterMarkdig.Syntax.Inlines.HtmlInlineMarkdig.Syntax.Inlines.HtmlInline