"_id" : ObjectId("5bee629dee0fc9d332b2107b"), 

    "no" : NumberLong(30001), 

    "name" : "레몬과일가게", 

    "products" : [

        {

            "id" : NumberLong(50001), 

            "name" : "레몬", 

            "price" : NumberInt(4), 

        }, 

        {

            "id" : NumberLong(50002), 

            "name" : "사과", 

            "price" : NumberInt(12), 

        }, 

        {

            "id" : NumberLong(50003), 

            "name" : "파인애플", 

            "price" : NumberInt(3), 

        }, 

        {

            "id" : NumberLong(50004), 

            "name" : "귤", 

            "price" : NumberInt(3), 

        }

    ]

mongodb 에서   30001번 과일가게에서 레몬의 가격을 변경하기 위한 코드 샘플

var filter = Builders<store>.Filter.Where(c => c.no == 30001 && c.products.Any(e => e.id == 50001));

var update = Builders<player>.Update.Set(x => x.products[-1].price, 2000);

var option = new UpdateOptions() { IsUpsert = false }; 


출처 : https://stackoverflow.com/questions/31453681/mongo-update-array-element-net-driver-2-0

블로그 이미지

레몬도리 LemonDory

개발자의 이야기

출처 : https://stackify.com/log4net-guide-dotnet-logging/


If you have been doing .NET programming very long, odds are, you have touched a few projects that used log4net. It has been around for a long time and is very similar to log4j which is for Java. Log4net is a tool I have used forever and I wanted to share a tutorial to use for .Net logging!

What is log4net and why should you use it, or any C# logging framework?

I still find it hard to believe how many people I talk to that don’t use any sort of C# logging framework. Personally, it would be one of the first things I add to any new project.

Logging frameworks are important because they make it easy to write your logs to different places by simply changing your configuration. You can write your .NET logs to a file on disk, a database, a log management system or potentially dozens of other places, all without changing your code.

 

Getting Started: How to Install log4net via Nuget

1. Add log4net Package

Starting with log4net is as easy as installing a Nuget package. You can use the Visual Studio UI to search for it and install it, or just run this quick command from the Package Manager Console.

PM> Install-Package log4net

2. Add log4net.config file

Add a new file to your project in Visual Studio called log4net.config and be sure to set a property for the file. Set “Copy to Output Directory” to “Copy Always”. This is important because we need the log4net.config file to be copied to the bin folder when you build and run your app.

To get you started quickly, copy this log4net config and put it in your new log4net.config file. This will log messages to the console and a log file both. We will discuss more about logging appenders further down.

 <log4net>
    <root>
      <level value="ALL" />
      <appender-ref ref="console" />
      <appender-ref ref="file" />
    </root>
    <appender name="console" type="log4net.Appender.ConsoleAppender">
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date %level %logger - %message%newline" />
      </layout>
    </appender>
    <appender name="file" type="log4net.Appender.RollingFileAppender">
      <file value="myapp.log" />
      <appendToFile value="true" />
      <rollingStyle value="Size" />
      <maxSizeRollBackups value="5" />
      <maximumFileSize value="10MB" />
      <staticLogFileName value="true" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%thread] %level %logger - %message%newline" />
      </layout>
    </appender>
  </log4net>

3. Tell log4net to Load Your Config

The next thing we need to do is tell log4net where to load it’s configuratin from so that it actually works. I suggest putting this in your AssemblyInfo.cs file. You can find it under the Properties section in your project.

Add this to the bottom of your AssemblyInfo file.

[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config")]

4. Log Something!

Now you can modify your app to log something and try it out!

    class Program
    {
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        static void Main(string[] args)
        {
            log.Info("Hello logging world!");
            Console.WriteLine("Hit enter");
            Console.ReadLine();
        }
    }

Log Appenders: What They Are and Which Ones You Need to Know

Appenders are how you direct where you want your logs sent. The most popular of the standard appenders are most likely the RollingFileAppender and ConsoleAppender.

I would also try the DebugAppender if you want to see your log statements in the Visual Studio Debug window so you don’t have to open a log file.

If you are using a Console, checkout the ColoredConsoleAppender.

Colored console for log4net

COLORED CONSOLE FOR LOG4NET

 

Make Good Use of Multiple Log Levels and Filter by Them

Be sure to use Debug, Info, Warning, Error, and Fatal logging levels as appropriate within your code. Don’t lot everything as Debug. Be sure to think about how you would be viewing the logs and what you want to see it later when coding your logging statements.

You can specify in your log4net config which log4net logging levels you want to log. This is really valuable if you want to specify only certain levels to be logged to a specific log appender or to reduce logging in production. This also you to log more or less data without changing your code.

log4net levels:

  • All – Log everything
  • Debug
  • Info
  • Warn
  • Error
  • Fatal
  • Off – Don’t log anything

Advanced Topics & log4net Best Practices

1. Define Your LogManager Object as Static

Declaring any variable in your code has overhead. When I have been doing some profiling sessions in the past to optimize code, I have noticed that the constructors on the LogManager object can use a lot of CPU.

Declare it as static and use this little trick so you don’t have to hard code the class type.

   private static readonly log4net.ILog log 
       = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

2. How to Enable log4net’s Own Internal Debug Logging

From time to time, you may have problems with a specific appender, or issues working with it.

To help resolve these issues, enable internal log4net logging via your web.config file.

<configuration>
   <appSettings>
      <add key="log4net.Internal.Debug" value="true"/>
   </appSettings>
</configuration>

You can then specify where the logging is written to.

<configuration>
...

<system.diagnostics>
    <trace autoflush="true">
        <listeners>
            <add 
                name="textWriterTraceListener" 
                type="System.Diagnostics.TextWriterTraceListener" 
                initializeData="C:\tmp\log4net.txt" />
        </listeners>
    </trace>
</system.diagnostics>

...
</configuration>

3. Do Not Send Your Logs to a Database Table with the AdoAppender

Trying to query logs in SQL is very difficult if you log any real volume. You are much better off sending your logs to Elasticsearch or a log management service that can provide full-text indexing and more functionality with your logs.

 

4. Do Not Send Emails on Every Exception

The last thing you want to do is send any sort of emails from an appender. They either get ignored over time or something starts throwing a lot of exceptions and then your app starts sending thousands of errors. Although, there is an SmtpAppender if you really want to do this.

 

5. How to Send Alerts for Exceptions

If you want to send alerts about exceptions, send your exceptions to an error trackingproduct, like Retrace, which is designed for this. They can also de-dupe your errors so you can figure out when an error is truly new, track its history, and track error rates.

 

6. Send Your Logs to a Log Management System to View Them Across Servers

Capturing logs and logging them to a file on disk is great. But if you want to search your logs across multiple servers and applications, you need to send all of your logs to a central repository. There are a lot of log management solutions that can help you with this, or you can even setup your own elasticsearch cluster for it.

If you want to query all the files on disk, consider using VisualLogParser.

 

7. Use Filters to Suppress Certain Logging Statements

Filters can be configured to suppress specific log messages. Take a look at these examples.

Here’s how you can filter by the text on the log messages.

<filter type="log4net.Filter.StringMatchFilter">
  <stringToMatch value="test" /> <!-- Can filter by string or regex -->
</filter>

And here, you can filter by the log level.

<filter type="log4net.Filter.LevelRangeFilter">
   <levelMin value="INFO" />
   <levelMax value="FATAL" />
</filter>

8. You Can Make Your Own Custom log4net Appenders

If you want to do something that the standard appenders do not support, you can search online for one or write your own.

One example could be an appender for writing to Azure Storage. Once upon a time, we wrote one to send our logs to Azure Table storage to centralize them. We couldn’t really query them due to the lack of full-text indexing, but we could view them.

As an example of a custom appender, you can review the source code for our appender for sending logs to Retrace.

 

9. Customize Your Layout in Your Logs with log4net Pattern Layouts

You can modify your configuration to change what fields are outputting and in what format using pattern layouts.

    <appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender">
      <param name="File" value="stackify.log" />
      <param name="AppendToFile" value="true" />
      <rollingStyle value="Size" />
      <maxSizeRollBackups value="10" />
      <maximumFileSize value="10MB" />
      <staticLogFileName value="true" />
      <layout type="log4net.Layout.PatternLayout">
        <param name="ConversionPattern" value="%-5p %d{MM-dd hh:mm:ss.ffff}  [%thread]  %m%n" />
      </layout>
    </appender>

Using the layout above, write the level (%p), current date time (%d), thread # (%thread), the message (%m) and a new line (%n). The “-5” in the “%-5p” is to set the width of the field to 5 characters.

Here are some other notable fields you can log, although they can have a big performance impact to your app and would not be recommended for high volume logging on a production application.

  • %method – name of the method where the log message was written
  • %stacktrace{level} – output a stack trace to show where the log message was written
  • %type – type of the caller issuing the log request. Mostly likely your class name
  • %line – the line number from where your logging statement was logged

A layout like this:

<layout type="log4net.Layout.PatternLayout">
        <param name="ConversionPattern" value="%-5p%d{ yyyy-MM-dd HH:mm:ss} – [%thread] %m method:%method %n stacktrace:%stacktrace{5} %n type:%type %n line: %line %n" />
</layout>

Produces a log message like this:

ERROR 2017-02-06 09:38:10 – [10] Error downloading web request method:ThrowWebException 
 stacktrace:Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly > System.AppDomain.ExecuteAssembly > System.AppDomain._nExecuteAssembly > ConsoleApplication1.Program.Main > ConsoleApplication1.Class1.ThrowWebException 
 type:ConsoleApplication1.Class1 
 line: 26 

10. Use the Diagnostic Contexts to Log Additional Fields

You can also log custom fields to help give some more context about the user, customer or transaction related to the log statements.

The below example sets a custom property called “customer”. You can then modify your log4net pattern layout to include “%property{customer}” to output it in your logs.

            log4net.ThreadContext.Properties["customer"] = "My Customer Name";

            log.Debug("We are going to try and do a web request");

            try
            {
                Class1.ThrowWebException();
            }
            catch (Exception ex)
            {
                log.Error("Error trying to do something", ex);
            }
            log.Debug("We are done with the web request");

11. How to Correlate Log Messages by Web Request Transaction

Additionally, you can assign objects in contexts to use what it calls “active property values.” When the log message is written, the ToString() method will be called which can dynamically do something.

This can be used to write transaction IDs to help correlate messages to a web requestor transaction!

        //Create our little helper class
        public class ActivityIdHelper
        {
            public override string ToString()
            {
                if (Trace.CorrelationManager.ActivityId == Guid.Empty)
                {
                    Trace.CorrelationManager.ActivityId = Guid.NewGuid();
                }

                return Trace.CorrelationManager.ActivityId.ToString();
            }
        }

In your global.asax or Startup.cs class, subscribe to an event for when a request first starts.

        public override void Init()
        {
            base.Init();
            this.Error += WebApiApplication_Error;
            this.BeginRequest += WebApiApplication_BeginRequest;
            this.EndRequest += WebApiApplication_EndRequest;

        }

        void WebApiApplication_BeginRequest(object sender, EventArgs e)
        {
            //set the property to our new object
            log4net.LogicalThreadContext.Properties["activityid"] = new ActivityIdHelper();

            log.Debug("WebApiApplication_BeginRequest");
        }

If you add “%property{activity}” to your pattern layout, you can now see a transaction ID in your logs like so. Your log messages may still look like spaghetti, but at least you can easily see which ones go together.

DEBUG 02-06 02:51:58.6347 – a69640f7-d47d-4aa4-99c9-13cfd9ab93c2 WebApiApplication_BeginRequest 
DEBUG 02-06 02:51:58.6382 – a69640f7-d47d-4aa4-99c9-13cfd9ab93c2 Starting KitchenAsync - Call redis
DEBUG 02-06 02:51:58.9315 – b8a3bcee-e82e-4298-b27f-6481b256b5ad Finished KitchenAsync
DEBUG 02-06 02:51:59.1285 – a69640f7-d47d-4aa4-99c9-13cfd9ab93c2 Call Webclient
DEBUG 02-06 02:51:59.1686 – 54218fab-bd1b-4c77-9ff8-ebef838dfb82 WebApiApplication_BeginRequest
DEBUG 02-06 02:51:59.1746 – 54218fab-bd1b-4c77-9ff8-ebef838dfb82 Starting KitchenAsync - Call redis
DEBUG 02-06 02:51:59.4378 – a69640f7-d47d-4aa4-99c9-13cfd9ab93c2 Finished KitchenAsync
DEBUG 02-06 02:51:59.6450 – 54218fab-bd1b-4c77-9ff8-ebef838dfb82 Call Webclient
DEBUG 02-06 02:51:59.9294 – 54218fab-bd1b-4c77-9ff8-ebef838dfb82 Finished KitchenAsync

12. How to Log ASP.NET Request Details

You could use the same strategy as above to dynamically grab ASP.NET request info to add to your log message.

        public class WebRequestInfo
        {
            public override string ToString()
            {
                return HttpContext.Current?.Request?.RawUrl + ", " + HttpContext.Current?.Request?.UserAgent;
            }
        }

        void WebApiApplication_BeginRequest(object sender, EventArgs e)
        {
            log4net.LogicalThreadContext.Properties["activityid"] = new ActivityIdHelper();
            log4net.LogicalThreadContext.Properties["requestinfo"] = new WebRequestInfo();

            log.Debug("WebApiApplication_BeginRequest");
        }

13. How to Do Structured Logging, or Log an Object or Properties with a Message

By default, you can log an object to it and it will serialize it with its default renderers.

log.Debug(new {color="red", int1 = 1});

Output:

DEBUG 2017-02-06 15:07:25 – [8] { color = red, int1 = 1 }

But what if you want to log your entire log message as JSON?

There are several nuget packages related to log4net and JSON, but the support and docs for all of them seem a little sketchy.

I would recommend just making your own JsonLayout class that does it. There is a good sample on GitHub. You could then control exactly how you log the JSON and which fields you log.

Output from the GitHub JsonLayout:

{
	"processSessionId" : "225ba696-6607-4abc-95f6-df8e0438e898",
	"level" : "DEBUG",
	"messageObject" : "Finished KitchenAsync",
	"renderedMessage" : "Finished KitchenAsync",
	"timestampUtc" : "2017-02-06T21:20:07.5690494Z",
	"logger" : "WebApp2.Controllers.TestController",
	"thread" : "69",
	"exceptionObject" : null,
	"exceptionObjectString" : null,
	"userName" : "IIS APPPOOL\\WebApp2",
	"domain" : "/LM/W3SVC/1/ROOT/WebApp2-10-131308895921693643",
	"identity" : "",
	"location" : "WebApp2.Controllers.TestController+d__27.MoveNext(C:\\BitBucket\\PrefixTests\\WebApp2\\Controllers\\TestController.cs:477)",
	"pid" : 14428,
	"machineName" : "LAPTOP-1UJ70V4E",
	"workingSet" : 352481280,
	"osVersion" : "Microsoft Windows NT 10.0.14393.0",
	"is64bitOS" : true,
	"is64bitProcess" : true,
	"properties" : {
		"requestinfo" : {},
		"activityid" : {},
		"log4net:UserName" : "IIS APPPOOL\\WebApp2",
		"log4net:Identity" : "",
		"log4net:HostName" : "LAPTOP-1UJ70V4E"
	}
}

If you want to really get the value of structured logging, you will want to send your logs to a log management tool that can index all the fields and enable powerful searching and analytics capabilities.

Learn more here: What is structured logging and why developers need it.

 

14. How to View log4net C# Logs by ASP.NET Web Request

Log files can quickly become a spaghetti mess of log messages. Especially with web apps that have lots of AJAX requests going on that all do logging.

I highly recommend using Prefix, Stackify’s FREE .NET Profiler to view your logs per web request, along with SQL queries, HTTP calls and much more.

transaction trace annotated



블로그 이미지

레몬도리 LemonDory

개발자의 이야기

출처 : https://gist.github.com/denji/8359866


NGINX Tuning For Best Performance

For this configuration you can use web server you like, i decided, because i work mostly with it to use nginx.

Generally, properly configured nginx can handle up to 400K to 500K requests per second (clustered), most what i saw is 50K to 80K (non-clustered) requests per second and 30% CPU load, course, this was 2 x Intel Xeon with HyperThreading enabled, but it can work without problem on slower machines.

You must understand that this config is used in testing environment and not in production so you will need to find a way to implement most of those features best possible for your servers.

First, you will need to install nginx

yum install nginx
apt install nginx

Backup your original configs and you can start reconfigure your configs. You will need to open your nginx.conf at /etc/nginx/nginx.conf with your favorite editor.

# you must set worker processes based on your CPU cores, nginx does not benefit from setting more than that
worker_processes auto; #some last versions calculate it automatically

# number of file descriptors used for nginx
# the limit for the maximum FDs on the server is usually set by the OS.
# if you don't set FD's then OS settings will be used which is by default 2000
worker_rlimit_nofile 100000;

# only log critical errors
error_log /var/log/nginx/error.log crit;

# provides the configuration file context in which the directives that affect connection processing are specified.
events {
    # determines how much clients will be served per worker
    # max clients = worker_connections * worker_processes
    # max clients is also limited by the number of socket connections available on the system (~64k)
    worker_connections 4000;

    # optmized to serve many clients with each thread, essential for linux -- for testing environment
    use epoll;

    # accept as many connections as possible, may flood worker connections if set too low -- for testing environment
    multi_accept on;
}

# cache informations about FDs, frequently accessed files
# can boost performance, but you need to test those values
open_file_cache max=200000 inactive=20s; 
open_file_cache_valid 30s; 
open_file_cache_min_uses 2;
open_file_cache_errors on;

# to boost I/O on HDD we can disable access logs
access_log off;

# copies data between one FD and other from within the kernel
# faster then read() + write()
sendfile on;

# send headers in one peace, its better then sending them one by one 
tcp_nopush on;

# don't buffer data sent, good for small data bursts in real time
tcp_nodelay on;

# reduce the data that needs to be sent over network -- for testing environment
gzip on;
gzip_min_length 10240;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/json application/xml;
gzip_disable msie6;

# allow the server to close connection on non responding client, this will free up memory
reset_timedout_connection on;

# request timed out -- default 60
client_body_timeout 10;

# if client stop responding, free up memory -- default 60
send_timeout 2;

# server will close connection after this time -- default 75
keepalive_timeout 30;

# number of requests client can make over keep-alive -- for testing environment
keepalive_requests 100000;

Now you can save config and run bottom command

nginx -s reload
/etc/init.d/nginx start|restart

If you wish to test config first you can run

nginx -t
/etc/init.d/nginx configtest

Just For Security Reason

server_tokens off;

Nginx Simple DDoS Defense

This is far away from secure DDoS defense but can slow down some small DDoS. Those configs are also in test environment and you should do your values.

# limit the number of connections per single IP
limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;

# limit the number of requests for a given session
limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=5r/s;

# zone which we want to limit by upper values, we want limit whole server
server {
    limit_conn conn_limit_per_ip 10;
    limit_req zone=req_limit_per_ip burst=10 nodelay;
}

# if the request body size is more than the buffer size, then the entire (or partial)
# request body is written into a temporary file
client_body_buffer_size  128k;

# headerbuffer size for the request header from client -- for testing environment
client_header_buffer_size 3m;

# maximum number and size of buffers for large headers to read from client request
large_client_header_buffers 4 256k;

# read timeout for the request body from client -- for testing environment
client_body_timeout   3m;

# how long to wait for the client to send a request header -- for testing environment
client_header_timeout 3m;

Now you can do again test config

nginx -t # /etc/init.d/nginx configtest

And then reload or restart your nginx

nginx -s reload
/etc/init.d/nginx reload|restart

You can test this configuration with tsung and when you are satisfied with result you can hit Ctrl+C because it can run for hours.

DoS HTTP/1.1 and above: Range Requests

By default max_ranges is not limited. DoS attacks can many Range-Requests (Impact on stability I/O).

Socket Sharding in NGINX 1.9.1+ (DragonFly BSD and Linux 3.9+)

Socket typeLatency (ms)Latency stdev (ms)CPU Load
Default15.6526.590.3
accept_mutex off15.5926.4810
reuseport12.353.150.3

Thread Pools in NGINX Boost Performance 9x! (Linux)

Multi-threaded sending of files is currently supported only Linux. Without sendfile_max_chunk limit, one fast connection may seize the worker process entirely.

Happy Hacking!


블로그 이미지

레몬도리 LemonDory

개발자의 이야기

우분투 apt로 설치 시에 apt-key를 설정하고 설치해야 하는 경우가 생겼다.

바로 mono인데 문제는 방화벽이 다 막혀있고 proxy로 연결이 가능한 상태인데....


sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80

위 명령을 사용하는데 hkp://keyserver.ubuntu.com:80이 연결이 안된다.

80포트 조차 막혀있다니...


다행히 우회할 수 있는 방법이 프록시 서버가 있었다.

구글을 검색하다보니 

--keyserver-options http-proxy=http://localhost:3128 을 옵션을 이용하면 프록시 서버를 이용해 설치가 가능하단다. 


예제로 mono 설치 시 사용하는 apt-key 명령을 전체 남긴다.

sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --keyserver-options http-proxy=http://localhost:3128 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF 


블로그 이미지

레몬도리 LemonDory

개발자의 이야기

$ sudo vi /etc/apt/apt.conf


-파일이 없을 경우 새로 생성하자.

- 아래 내용을 추가 

- :wq로 저장 


Acquire::http::proxy "http://adress:port/";


$ sudo apt-get update

$ sudo apt-get upgrade


- 정상적으로 진행되는 것을 확인해 보자

블로그 이미지

레몬도리 LemonDory

개발자의 이야기


mongodb collection을 protobuf class로 가져오려고 하던 중에 List 형태를 가져와보려고 많은 시간을 소비해 가며 보던 중에 .proto로 gen할 때 자세히 보니 repeated 값들이 readonly로 생성 되는 것을 보았다.


여기 저기 검색하던 중에 protobuf를 본 외국인의 글을 발견했다.(질문자는 다른 방법이 필요했던 거였지만 아래 더 자세한 설명을 해준 답변자의 답변이 눈에 들어왔다)

링크 : https://stackoverflow.com/questions/16617933/protobuf-net-generated-class-from-proto-is-repeated-field-supposed-to-be-re


This was a new issue for us as well after updating our proto-net executable and related files. It was new behavior we hadn't experienced before.

After a little digging in csharp.xslt, we found the definition for 'repeated' fields:

<xsl:template match="FieldDescriptorProto[label='LABEL_REPEATED']">
    <xsl:variable name="type"><xsl:apply-templates select="." mode="type"/></xsl:variable>
    <xsl:variable name="format"><xsl:apply-templates select="." mode="format"/></xsl:variable>
    <xsl:variable name="field"><xsl:apply-templates select="." mode="field"/></xsl:variable>
    private <xsl:if test="not($optionXml)">readonly</xsl:if> global::System.Collections.Generic.List&lt;<xsl:value-of select="$type" />&gt; <xsl:value-of select="$field"/> = new global::System.Collections.Generic.List&lt;<xsl:value-of select="$type"/>&gt;();
    [<xsl:apply-templates select="." mode="checkDeprecated"/>global::ProtoBuf.ProtoMember(<xsl:value-of select="number"/>, Name=@"<xsl:value-of select="name"/>", DataFormat = global::ProtoBuf.DataFormat.<xsl:value-of select="$format"/><xsl:if test="options/packed='true'">, Options = global::ProtoBuf.MemberSerializationOptions.Packed</xsl:if>)]<!--
    --><xsl:if test="$optionDataContract">
    [global::System.Runtime.Serialization.DataMember(Name=@"<xsl:value-of select="name"/>", Order = <xsl:value-of select="number"/>, IsRequired = false)]
    </xsl:if><xsl:if test="$optionXml">
    [global::System.Xml.Serialization.XmlElement(@"<xsl:value-of select="name"/>", Order = <xsl:value-of select="number"/>)]
    </xsl:if>
    public global::System.Collections.Generic.List&lt;<xsl:value-of select="$type" />&gt; <xsl:call-template name="pascal"/>
    {
      get { return <xsl:value-of select="$field"/>; }<!--
      --><xsl:if test="$optionXml">
      set { <xsl:value-of select="$field"/> = value; }</xsl:if>
    }
  </xsl:template>

I've pulled out the specific parts for the private field and the setter:

private <xsl:if test="not($optionXml)">readonly</xsl:if> ...snip...

public ...snip...
{
  ...snip... 
  <!----><xsl:if test="$optionXml">
  set { <xsl:value-of select="$field"/> = value; }
  </xsl:if>
}

Notice the suspect conditions above for $optionXml. If you just remove those, the field is no longer readonly and the setter is properly generated.

So it then becomes: private ...snip...

public ...snip...
{
  ...snip... 
  set { <xsl:value-of select="$field"/> = value; }
}

Full 'fixed' template:

  <xsl:template match="FieldDescriptorProto[label='LABEL_REPEATED']">
    <xsl:variable name="type"><xsl:apply-templates select="." mode="type"/></xsl:variable>
    <xsl:variable name="format"><xsl:apply-templates select="." mode="format"/></xsl:variable>
    <xsl:variable name="field"><xsl:apply-templates select="." mode="field"/></xsl:variable>
    private global::System.Collections.Generic.List&lt;<xsl:value-of select="$type" />&gt; <xsl:value-of select="$field"/> = new global::System.Collections.Generic.List&lt;<xsl:value-of select="$type"/>&gt;();
    [<xsl:apply-templates select="." mode="checkDeprecated"/>global::ProtoBuf.ProtoMember(<xsl:value-of select="number"/>, Name=@"<xsl:value-of select="name"/>", DataFormat = global::ProtoBuf.DataFormat.<xsl:value-of select="$format"/><xsl:if test="options/packed='true'">, Options = global::ProtoBuf.MemberSerializationOptions.Packed</xsl:if>)]<!--
    --><xsl:if test="$optionDataContract">
    [global::System.Runtime.Serialization.DataMember(Name=@"<xsl:value-of select="name"/>", Order = <xsl:value-of select="number"/>, IsRequired = false)]
    </xsl:if><xsl:if test="$optionXml">
    [global::System.Xml.Serialization.XmlElement(@"<xsl:value-of select="name"/>", Order = <xsl:value-of select="number"/>)]
    </xsl:if>
    public global::System.Collections.Generic.List&lt;<xsl:value-of select="$type" />&gt; <xsl:call-template name="pascal"/>
    {
      get { return <xsl:value-of select="$field"/>; }
      set { <xsl:value-of select="$field"/> = value; }
    }
  </xsl:template>

I played with setting optionXml to false, but it didn't work and you may still want that option enabled anyway.


위와 마지막 fixed template을 보고 protogen.exe 폴더에 있는 csharp.xslt의 내용을 수정하면 될 것이다.

블로그 이미지

레몬도리 LemonDory

개발자의 이야기

https://www.fun25.co.kr/blog/ubuntu-16-04-mysql-server-install/

OS: Ubuntu 16.04

# apt-get update
# apt-get install mysql-server

MySQL 서버의 root 계정의 암호를 설정한다. 이 암호는 설치 후 반드시 필요하니 꼭 메모해 두도록 한다.

enter image description here

설치시에 나오는 메시지이다.

패키지 목록을 읽는 중입니다... 완료
의존성 트리를 만드는 중입니다       
상태 정보를 읽는 중입니다... 완료
The following additional packages will be installed:
  apparmor libaio1 libapparmor-perl libcgi-fast-perl libcgi-pm-perl libencode-locale-perl libevent-core-2.0-5 libfcgi-perl
  libhtml-parser-perl libhtml-tagset-perl libhtml-template-perl libhttp-date-perl libhttp-message-perl libio-html-perl
  liblwp-mediatypes-perl libnuma1 libtimedate-perl liburi-perl mysql-client-5.7 mysql-client-core-5.7 mysql-common
  mysql-server-5.7 mysql-server-core-5.7 psmisc
제안하는 패키지:
  apparmor-profiles apparmor-profiles-extra apparmor-docs apparmor-utils libdata-dump-perl libipc-sharedcache-perl libwww-perl
  mailx tinyca
다음 새 패키지를 설치할 것입니다:
  apparmor libaio1 libapparmor-perl libcgi-fast-perl libcgi-pm-perl libencode-locale-perl libevent-core-2.0-5 libfcgi-perl
  libhtml-parser-perl libhtml-tagset-perl libhtml-template-perl libhttp-date-perl libhttp-message-perl libio-html-perl
  liblwp-mediatypes-perl libnuma1 libtimedate-perl liburi-perl mysql-client-5.7 mysql-client-core-5.7 mysql-common mysql-server
  mysql-server-5.7 mysql-server-core-5.7 psmisc
0개 업그레이드, 25개 새로 설치, 0개 제거 및 74개 업그레이드 안 함.
19.5 M바이트 아카이브를 받아야 합니다.
이 작업 후 165 M바이트의 디스크 공간을 더 사용하게 됩니다.
계속 하시겠습니까? [Y/n] 
받기:1 http://ftp.daumkakao.com/ubuntu xenial-updates/main amd64 mysql-common all 5.7.17-0ubuntu0.16.04.2 [15.7 kB]
받기:2 http://ftp.daumkakao.com/ubuntu xenial-updates/main amd64 libapparmor-perl amd64 2.10.95-0ubuntu2.6 [31.4 kB]
받기:3 http://ftp.daumkakao.com/ubuntu xenial-updates/main amd64 apparmor amd64 2.10.95-0ubuntu2.6 [450 kB]
받기:4 http://ftp.daumkakao.com/ubuntu xenial/main amd64 libaio1 amd64 0.3.110-2 [6,356 B]
받기:5 http://ftp.daumkakao.com/ubuntu xenial/main amd64 libnuma1 amd64 2.0.11-1ubuntu1 [21.0 kB]
받기:6 http://ftp.daumkakao.com/ubuntu xenial-updates/main amd64 mysql-client-core-5.7 amd64 5.7.17-0ubuntu0.16.04.2 [6,516 kB]
받기:7 http://ftp.daumkakao.com/ubuntu xenial-updates/main amd64 mysql-client-5.7 amd64 5.7.17-0ubuntu0.16.04.2 [1,666 kB]
받기:8 http://ftp.daumkakao.com/ubuntu xenial-updates/main amd64 mysql-server-core-5.7 amd64 5.7.17-0ubuntu0.16.04.2 [7,564 kB]
받기:9 http://ftp.daumkakao.com/ubuntu xenial/main amd64 psmisc amd64 22.21-2.1build1 [48.0 kB]
받기:10 http://ftp.daumkakao.com/ubuntu xenial-updates/main amd64 libevent-core-2.0-5 amd64 2.0.21-stable-2ubuntu0.16.04.1 [70.6 kB]
받기:11 http://ftp.daumkakao.com/ubuntu xenial-updates/main amd64 mysql-server-5.7 amd64 5.7.17-0ubuntu0.16.04.2 [2,466 kB]
받기:12 http://ftp.daumkakao.com/ubuntu xenial/main amd64 libhtml-tagset-perl all 3.20-2 [13.5 kB]
받기:13 http://ftp.daumkakao.com/ubuntu xenial/main amd64 liburi-perl all 1.71-1 [76.9 kB]
받기:14 http://ftp.daumkakao.com/ubuntu xenial/main amd64 libhtml-parser-perl amd64 3.72-1 [86.1 kB]
받기:15 http://ftp.daumkakao.com/ubuntu xenial/main amd64 libcgi-pm-perl all 4.26-1 [185 kB]
받기:16 http://ftp.daumkakao.com/ubuntu xenial/main amd64 libfcgi-perl amd64 0.77-1build1 [32.3 kB]
받기:17 http://ftp.daumkakao.com/ubuntu xenial/main amd64 libcgi-fast-perl all 1:2.10-1 [10.2 kB]
받기:18 http://ftp.daumkakao.com/ubuntu xenial/main amd64 libencode-locale-perl all 1.05-1 [12.3 kB]
받기:19 http://ftp.daumkakao.com/ubuntu xenial/main amd64 libhtml-template-perl all 2.95-2 [60.4 kB]
받기:20 http://ftp.daumkakao.com/ubuntu xenial/main amd64 libtimedate-perl all 2.3000-2 [37.5 kB]
받기:21 http://ftp.daumkakao.com/ubuntu xenial/main amd64 libhttp-date-perl all 6.02-1 [10.4 kB]
받기:22 http://ftp.daumkakao.com/ubuntu xenial/main amd64 libio-html-perl all 1.001-1 [14.9 kB]
받기:23 http://ftp.daumkakao.com/ubuntu xenial/main amd64 liblwp-mediatypes-perl all 6.02-1 [21.7 kB]
받기:24 http://ftp.daumkakao.com/ubuntu xenial/main amd64 libhttp-message-perl all 6.11-1 [74.3 kB]
받기:25 http://ftp.daumkakao.com/ubuntu xenial-updates/main amd64 mysql-server all 5.7.17-0ubuntu0.16.04.2 [10.8 kB]
내려받기 19.5 M바이트, 소요시간 5초 (3,442 k바이트/초)
패키지를 미리 설정하는 중입니다...
Selecting previously unselected package mysql-common.
(데이터베이스 읽는중 ...현재 14946개의 파일과 디렉터리가 설치되어 있습니다.)
Preparing to unpack .../mysql-common_5.7.17-0ubuntu0.16.04.2_all.deb ...
Unpacking mysql-common (5.7.17-0ubuntu0.16.04.2) ...
Selecting previously unselected package libapparmor-perl.
Preparing to unpack .../libapparmor-perl_2.10.95-0ubuntu2.6_amd64.deb ...
Unpacking libapparmor-perl (2.10.95-0ubuntu2.6) ...
Selecting previously unselected package apparmor.
Preparing to unpack .../apparmor_2.10.95-0ubuntu2.6_amd64.deb ...
Unpacking apparmor (2.10.95-0ubuntu2.6) ...
Selecting previously unselected package libaio1:amd64.
Preparing to unpack .../libaio1_0.3.110-2_amd64.deb ...
Unpacking libaio1:amd64 (0.3.110-2) ...
Selecting previously unselected package libnuma1:amd64.
Preparing to unpack .../libnuma1_2.0.11-1ubuntu1_amd64.deb ...
Unpacking libnuma1:amd64 (2.0.11-1ubuntu1) ...
Selecting previously unselected package mysql-client-core-5.7.
Preparing to unpack .../mysql-client-core-5.7_5.7.17-0ubuntu0.16.04.2_amd64.deb ...
Unpacking mysql-client-core-5.7 (5.7.17-0ubuntu0.16.04.2) ...
Selecting previously unselected package mysql-client-5.7.
Preparing to unpack .../mysql-client-5.7_5.7.17-0ubuntu0.16.04.2_amd64.deb ...
Unpacking mysql-client-5.7 (5.7.17-0ubuntu0.16.04.2) ...
Selecting previously unselected package mysql-server-core-5.7.
Preparing to unpack .../mysql-server-core-5.7_5.7.17-0ubuntu0.16.04.2_amd64.deb ...
Unpacking mysql-server-core-5.7 (5.7.17-0ubuntu0.16.04.2) ...
Selecting previously unselected package psmisc.
Preparing to unpack .../psmisc_22.21-2.1build1_amd64.deb ...
Unpacking psmisc (22.21-2.1build1) ...
Selecting previously unselected package libevent-core-2.0-5:amd64.
Preparing to unpack .../libevent-core-2.0-5_2.0.21-stable-2ubuntu0.16.04.1_amd64.deb ...
Unpacking libevent-core-2.0-5:amd64 (2.0.21-stable-2ubuntu0.16.04.1) ...
Processing triggers for systemd (229-4ubuntu10) ...
Processing triggers for ureadahead (0.100.0-19) ...
Processing triggers for libc-bin (2.23-0ubuntu3) ...
mysql-common (5.7.17-0ubuntu0.16.04.2) 설정하는 중입니다 ...
update-alternatives: using /etc/mysql/my.cnf.fallback to provide /etc/mysql/my.cnf (my.cnf) in auto mode
Selecting previously unselected package mysql-server-5.7.
(데이터베이스 읽는중 ...현재 15287개의 파일과 디렉터리가 설치되어 있습니다.)
Preparing to unpack .../mysql-server-5.7_5.7.17-0ubuntu0.16.04.2_amd64.deb ...
Unpacking mysql-server-5.7 (5.7.17-0ubuntu0.16.04.2) ...
Selecting previously unselected package libhtml-tagset-perl.
Preparing to unpack .../libhtml-tagset-perl_3.20-2_all.deb ...
Unpacking libhtml-tagset-perl (3.20-2) ...
Selecting previously unselected package liburi-perl.
Preparing to unpack .../liburi-perl_1.71-1_all.deb ...
Unpacking liburi-perl (1.71-1) ...
Selecting previously unselected package libhtml-parser-perl.
Preparing to unpack .../libhtml-parser-perl_3.72-1_amd64.deb ...
Unpacking libhtml-parser-perl (3.72-1) ...
Selecting previously unselected package libcgi-pm-perl.
Preparing to unpack .../libcgi-pm-perl_4.26-1_all.deb ...
Unpacking libcgi-pm-perl (4.26-1) ...
Selecting previously unselected package libfcgi-perl.
Preparing to unpack .../libfcgi-perl_0.77-1build1_amd64.deb ...
Unpacking libfcgi-perl (0.77-1build1) ...
Selecting previously unselected package libcgi-fast-perl.
Preparing to unpack .../libcgi-fast-perl_1%3a2.10-1_all.deb ...
Unpacking libcgi-fast-perl (1:2.10-1) ...
Selecting previously unselected package libencode-locale-perl.
Preparing to unpack .../libencode-locale-perl_1.05-1_all.deb ...
Unpacking libencode-locale-perl (1.05-1) ...
Selecting previously unselected package libhtml-template-perl.
Preparing to unpack .../libhtml-template-perl_2.95-2_all.deb ...
Unpacking libhtml-template-perl (2.95-2) ...
Selecting previously unselected package libtimedate-perl.
Preparing to unpack .../libtimedate-perl_2.3000-2_all.deb ...
Unpacking libtimedate-perl (2.3000-2) ...
Selecting previously unselected package libhttp-date-perl.
Preparing to unpack .../libhttp-date-perl_6.02-1_all.deb ...
Unpacking libhttp-date-perl (6.02-1) ...
Selecting previously unselected package libio-html-perl.
Preparing to unpack .../libio-html-perl_1.001-1_all.deb ...
Unpacking libio-html-perl (1.001-1) ...
Selecting previously unselected package liblwp-mediatypes-perl.
Preparing to unpack .../liblwp-mediatypes-perl_6.02-1_all.deb ...
Unpacking liblwp-mediatypes-perl (6.02-1) ...
Selecting previously unselected package libhttp-message-perl.
Preparing to unpack .../libhttp-message-perl_6.11-1_all.deb ...
Unpacking libhttp-message-perl (6.11-1) ...
Selecting previously unselected package mysql-server.
Preparing to unpack .../mysql-server_5.7.17-0ubuntu0.16.04.2_all.deb ...
Unpacking mysql-server (5.7.17-0ubuntu0.16.04.2) ...
Processing triggers for systemd (229-4ubuntu10) ...
Processing triggers for ureadahead (0.100.0-19) ...
libapparmor-perl (2.10.95-0ubuntu2.6) 설정하는 중입니다 ...
apparmor (2.10.95-0ubuntu2.6) 설정하는 중입니다 ...
update-rc.d: warning: start and stop actions are no longer supported; falling back to defaults
diff: /var/lib/apparmor/profiles/.apparmor.md5sums: No such file or directory
libaio1:amd64 (0.3.110-2) 설정하는 중입니다 ...
libnuma1:amd64 (2.0.11-1ubuntu1) 설정하는 중입니다 ...
mysql-client-core-5.7 (5.7.17-0ubuntu0.16.04.2) 설정하는 중입니다 ...
mysql-client-5.7 (5.7.17-0ubuntu0.16.04.2) 설정하는 중입니다 ...
mysql-server-core-5.7 (5.7.17-0ubuntu0.16.04.2) 설정하는 중입니다 ...
psmisc (22.21-2.1build1) 설정하는 중입니다 ...
libevent-core-2.0-5:amd64 (2.0.21-stable-2ubuntu0.16.04.1) 설정하는 중입니다 ...
mysql-server-5.7 (5.7.17-0ubuntu0.16.04.2) 설정하는 중입니다 ...
update-alternatives: using /etc/mysql/mysql.cnf to provide /etc/mysql/my.cnf (my.cnf) in auto mode
Renaming removed key_buffer and myisam-recover options (if present)
libhtml-tagset-perl (3.20-2) 설정하는 중입니다 ...
liburi-perl (1.71-1) 설정하는 중입니다 ...
libhtml-parser-perl (3.72-1) 설정하는 중입니다 ...
libcgi-pm-perl (4.26-1) 설정하는 중입니다 ...
libfcgi-perl (0.77-1build1) 설정하는 중입니다 ...
libcgi-fast-perl (1:2.10-1) 설정하는 중입니다 ...
libencode-locale-perl (1.05-1) 설정하는 중입니다 ...
libhtml-template-perl (2.95-2) 설정하는 중입니다 ...
libtimedate-perl (2.3000-2) 설정하는 중입니다 ...
libhttp-date-perl (6.02-1) 설정하는 중입니다 ...
libio-html-perl (1.001-1) 설정하는 중입니다 ...
liblwp-mediatypes-perl (6.02-1) 설정하는 중입니다 ...
libhttp-message-perl (6.11-1) 설정하는 중입니다 ...
mysql-server (5.7.17-0ubuntu0.16.04.2) 설정하는 중입니다 ...
Processing triggers for systemd (229-4ubuntu10) ...
Processing triggers for ureadahead (0.100.0-19) ...
Processing triggers for libc-bin (2.23-0ubuntu3) ...

설치된 MySQL 버전을 확인해 볼려면 아래와 같이 dkpg 명령어를 이용한다. MySQL 5.7 버전으로 설치가 되었다.

# dpkg --list | grep mysql
ii  mysql-client-5.7           5.7.17-0ubuntu0.16.04.2         amd64        MySQL database client binaries
ii  mysql-client-core-5.7      5.7.17-0ubuntu0.16.04.2         amd64        MySQL database core client binaries
ii  mysql-common               5.7.17-0ubuntu0.16.04.2         all          MySQL database common files, e.g. /etc/mysql/my.cnf
ii  mysql-server               5.7.17-0ubuntu0.16.04.2         all          MySQL database server (metapackage depending on the latest version)
ii  mysql-server-5.7           5.7.17-0ubuntu0.16.04.2         amd64        MySQL database server binaries and system database setup
ii  mysql-server-core-5.7      5.7.17-0ubuntu0.16.04.2         amd64        MySQL database server binaries

MySQL 서버 시작

# service mysql start

MySQL 서버 종료

# service mysql stop

설정 파일 위치는 /etc/mysql/my.cnf 이다. 아래와 같이 클라이언트와 서버쪽 설정 파일을 include 하도록 되어 있다.

#
# The MySQL database server configuration file.
#
# You can copy this to one of:
# - "/etc/mysql/my.cnf" to set global options,
# - "~/.my.cnf" to set user-specific options.
# 
# One can use all long options that the program supports.
# Run program with --help to get a list of available options and with
# --print-defaults to see which it would actually understand and use.
#
# For explanations see
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html

#
# * IMPORTANT: Additional settings that can override those from this file!
#   The files must end with '.cnf', otherwise they'll be ignored.
#

!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/

서버쪽 설정을 변경할려면 /etc/mysql/mysql/conf.d/mysqld.cnf 를 수정하면 된다. MySQL 서버는 초기 설치시에 바인딩 어드레스가 127.0.0.1 로 되어 있기 때문에 리모트에서 접속이 불가하다. 리모트에서 접속을 할려면 아래와 같이 bind-address 를 0.0.0.0 으로 한 후 MySQL 서버를 재시작한다.

#
# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
bind-address            = 0.0.0.0

MySQL 서버로 접속해 본다.

root@api_mysql_dev:~# mysql -u root -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 6
Server version: 5.7.17-0ubuntu0.16.04.2 (Ubuntu)

Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

외부 접속 설정(https://zetawiki.com/wiki/MySQL_%EC%9B%90%EA%B2%A9_%EC%A0%91%EC%86%8D_%ED%97%88%EC%9A%A9)

모든 IP 허용
INSERT INTO mysql.user (host,user,authentication_string,ssl_cipher, x509_issuer, x509_subject) VALUES ('%','root',password('패스워드'),'','','');
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%';
FLUSH PRIVILEGES;
IP 대역 허용 ( 예: 111.222.xxx.xxx )
  • 다음과 같이 설정하면 111.222로 시작하는 모든 IP가 허용된다.
INSERT INTO mysql.user (host,user,authentication_string,ssl_cipher, x509_issuer, x509_subject) VALUES ('111.222.%','root',password('패스워드'),'','','');
GRANT ALL PRIVILEGES ON *.* TO 'root'@'111.222.%';
FLUSH PRIVILEGES;
특정 IP 1개 허용 ( 예: 111.222.33.44 )
INSERT INTO mysql.user (host,user,authentication_string,ssl_cipher, x509_issuer, x509_subject) VALUES ('111.222.33.44','root',password('패스워드'),'','','');
GRANT ALL PRIVILEGES ON *.* TO 'root'@'111.222.33.44';
FLUSH PRIVILEGES;
  • 모든 IP를 허용한 경우 다음과 같이 원래 상태로 복구할 수 있다.
DELETE FROM mysql.user WHERE Host='%' AND User='root';
FLUSH PRIVILEGES;


블로그 이미지

레몬도리 LemonDory

개발자의 이야기

HttpListener를 사용하여 개발 중에 서버포트로 연결이 불가하다는 메시지로 Exception이 떨어지는 현상이 발생하여 찾아본 명령어


명령 프롬프트(관리자 권한)를 열고 아래 명령어에 포트만 변경하여 실행하고 실행해보자


netsh http add urlacl url=http://*:8888/ user=Everyone listen=yes 


아래 참고 블로그를 링크 걸어놓는다.


참고 : http://www.windowcmc.com/q.php?q=netsh-http-kr-manual

블로그 이미지

레몬도리 LemonDory

개발자의 이야기

티스토리 툴바