14 Eylül 2022 Çarşamba

Logback logback.xml Console Appender Tanımlama

Giriş
class olarak "ch.qos.logback.core.ConsoleAppender" kullanmak gerekiyor. Daha sonra da bir encoder tanımlamak lazım

encoder
pattern içinde log formatı belirtilir.
layout belirtilir ama ne olduğunu tam bilmiyorum

Örnek
Şöyle yaparız.
<configuration>
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
  </appender>
  ...  
</configuration>
Örnek
Şöyle yaparız.
<configuration>
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        <layout class="com.touchcorp.touchpoint.utils.MaskingPatternLayout">
          <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </layout>
    </encoder>
  </appender>
  ...
</configuration>
Örnek - renkli çıktı
Şöyle yaparız
<?xml version="1.0" encoding="UTF-8"?>
<included>
  <conversionRule conversionWord="customHighlightingLogLevel" converterClass="com.emcrey.common.config.CustomHighlightingLogLevel" />
  <conversionRule conversionWord="customHighlightingPackageName" converterClass="com.emcrey.common.config.CustomHighlightingPackageName" />
  <conversionRule conversionWord="customHighlightingMessage" converterClass="com.emcrey.common.config.CustomHighlightingMessage" />

 <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
  <encoder>
   <pattern>%customHighlightingLogLevel(%d{yyyy-MM-dd HH:mm:ss} %-5level) %customHighlightingPackageName(%logger{40}.%M\(%line\)): %customHighlightingMessage(%msg%n)</pattern>
  </encoder>
 </appender>
 
 <appender name="FILE" class="ch.qos.logback.core.FileAppender">
  <file>/tmp/logs/apex-fraud-broker.log</file>
  <append>true</append>
  <immediateFlush>true</immediateFlush>
  <encoder>
   <pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{40}.%M\(%line\): %msg%n</pattern>
  </encoder>
 </appender>
 
 <logger name="com.emcrey" level="debug">
  <appender-ref ref="STDOUT"/>
  <appender-ref ref="FILE"/>
 </logger>
 
 <logger name="org.springframework" level="error">
  <appender-ref ref="STDOUT"/>
  <appender-ref ref="FILE"/>
 </logger>
</included>
Sınıflar şöyle
public class CustomHighlightingLogLevel 
  extends ForegroundCompositeConverterBase<ILoggingEvent> {

  @Override
  protected String getForegroundColorCode(ILoggingEvent event) {
    Level level = event.getLevel();
    switch (level.toInt()) {
      case Level.ERROR_INT:
        return ANSIConstants.RED_FG;
      case Level.WARN_INT:
        return ANSIConstants.YELLOW_FG;
      default:
        return ANSIConstants.DEFAULT_FG;
    }
  }
}

public class CustomHighlightingMessage 
  extends ForegroundCompositeConverterBase<ILoggingEvent> {

  @Override
  protected String getForegroundColorCode(ILoggingEvent event) {
    Level level = event.getLevel();
    switch (level.toInt()) {
      case Level.ERROR_INT:
        return ANSIConstants.RED_FG;
      case Level.WARN_INT:
        return ANSIConstants.YELLOW_FG;
      default:
        return ANSIConstants.DEFAULT_FG;
    }
  }
}

public class CustomHighlightingPackageName 
  extends ForegroundCompositeConverterBase<ILoggingEvent> {

  @Override
  protected String getForegroundColorCode(ILoggingEvent event) {
    Level level = event.getLevel();
    switch (level.toInt()) {
      case Level.ERROR_INT:
        return ANSIConstants.RED_FG;
      case Level.WARN_INT:
        return ANSIConstants.YELLOW_FG;
      default:
        return ANSIConstants.CYAN_FG;
    }
  }
}



12 Eylül 2022 Pazartesi

IntelliJ Idea Profiling

Giriş
Açıklaması şöyle
Sometimes, unfortunately, a breakpoint is not enough and you need to use some more serious tools. Mostly those are tools used to detect memory leaks and high CPU usage. The Profiler in IntelliJ provides a lot of the functionalities that previously we needed external tools for.

You can open the Profiler pane through the View Menu|Tool Windows|Profiler or it might already be visible somewhere in the left|bottom|right corners. If there is a Java process running it will appear there.

The interesting bits are hidden in the context menu.
Profiler ile
1. CPU and Memory Live Charts
2. Capture Memory Snapshot
3. Get Thread Dump

işlemleri yapılabilir

Ayarlar
Açıklaması şöyle
IntelliJ IDEA 2022.3 comes with some important profile improvements. You can exclude native calls:
Şeklen şöyle


CPU and Memory Live Charts
Ulaşmak için menü şöyle

Karşımıza çıkan şey için açıklama şöyle
This will show you a timeline graph of the memory and CPU usage of the app while it’s running.

It can be very useful if you want to gauge where the app is at in terms of resource usage or detect any abnormal spikes or drops in either of those.
Şeklen şöyle

Capture Memory Snapshot
Şeklen şöyle










IntelliJ Idea Breakpoint İpuçları

Giriş
IntelliJ ile debug için Shai Almog tarafından gösterilen bazı açıklamalar burada. Bazıları farklı şeyler söylese de bence temelde 3 çeşit breakpoint var
1. Line Breakpoint
2. Field Watchpoint veya Debug Field
3. Exception Breakpoint

1. Line Breakpoint
Seçenekler şöyle
Suspend
Şeklen şöyle. Eğer bu seçenek seçili değilse, Breakpoint'e gelince thread durmaz.

Conditional Breakpoints
Condition koymak istersek şöylen şöyle

Object Marking ile işaretli bir nesneye erişileceği gibi, genel koşullar da yazılabilir. Şeklen şöyle.

Suspending single thread only
Açıklaması şöyle
By default, in the pop up you’ll see the All radio button selected. However, if you choose the Thread one, you can suspend only the thread executing the line of code where the breakpoint is.

This is usually useful when you have threads, which, if suspended, might throw exceptions and die, like threads consuming from Kafka or querying a database with a timeout. Having only one thread stop might help you keep the app running and healthy while you examine the bit of code that might be problematic.
Şeklen şöyle. Sadece bu breakpoint'e gelen thread durdurulur. Diğer thread'ler çalışmaya devam eder.


Print debug statements
Açıklaması şöyle
In the default pop up, by default the Suspend checkbox is selected. If you deselect it, the window will expand revealing a whole lot more options. One of those is Evaluate and log which means that every time the debugger would normally suspend (no matter if it’s a normal breakpoint, with a condition, suspending one or all threads) it will print whatever the statement in that textbox evaluates to instead. It can either be a string literal or anything using the variables in the scope.
Çoklu thread kullanan uygulamalarda, "Suspend" kaldırılır ve "Evaluate and log" ile thread'in log basması sağlanabilir. Şeklen şöyle.


Şeklen şöyle

Eğer breakpoint tam metod ismine konulmuşsa, More yazısına tıklarsak Method entry veya Method exit seçimi yapabiliriz. Şeklen şöyle. Burada Suspend kaldırılmış ve Method exit seçili
Eğer istersek Condition yazılabilir.  Şeklen şöyle



2. Field Watchpoint veya Debug Field
Açıklaması şöyle
This isn’t a breakpoint since the execution never stops at the field. It stops in the line of code that accesses the field. You can optionally toggle this so it will stop only for write, only for read or in both cases.
Örnek
Şeklen şöyle. Burada üye alanı değiştiren yerde kod duracak


3. Exception Breakpoint
Açıklaması şöyle
The default IDE behavior of stopping on every exception is redundant and infuriating!
Açıklaması şöyle
Sometimes, though, you cannot pinpoint the exact line causing the problem. For example in multithreaded applications exceptions are being swallowed and appear as side effects somewhere else or you are not sure where the exception is thrown from due to lack of proper logging or you just need to approach the problem more generally. In those cases, you can add a breakpoint exception.

If you hit Ctrl + Shift + F8 | Cmd + Shift +F8 you’ll see this window listing all currently added breakpoints.
Örnek
Şeklen şöyle. Burada "Class filters" ile fırlatıldığı yer seçilebilir. Ayrıca "Catch Class Filters" ve "Instance Filters" önemli

Örnek
Şeklen şöyle. Burada IllegalArgumentException nereden fırlatılırsa kod orada duracak


Diğer Breakpoint Özellikleri
1. Grouping/Naming
Breakpoint'lere "Edit Description" ile açıklama verilebilir. Ayrıca breakpoint'ler gruplanabilir.

2. Tracepoints
Açıklaması şöyle
We can use a breakpoint as an ad hoc log that doesn’t suspend execution. You can just add printouts which can include expressions, etc. 

11 Eylül 2022 Pazar

DeflaterOutputStream Sınıfı

Giriş
Şu satırı dahil ederiz
import java.util.zip.DeflaterOutputStream;
constructor
Örnek - Yanlış Kullanım
Şöyle yapmak doğru değil. Çünkü Deflator sınıfı kapatılmıyor.
outputStream = new DeflaterOutputStream(outputStream, new Deflater(), BLOCK_SIZE);
Çözüm şunlardan birisini kullanmak. Burada deflator elle kapatılıyor
outputStream = new DeflaterOutputStream(outputStream, new Deflater(), BLOCK_SIZE) {
  @Override
  public void close() throws IOException {
    try {
      super.close();
    } finally {
      def.end();
    }
  }
};
veya şöyle yapmak. Burada usesDefaultDeflater değişkeni true yapılıyor. Böylece GZIPOutputStream kendisine dışarıdan verilen nesnesi kapatıyor.
public GZIPOutputStream(OutputStream out, int size, boolean syncFlush)
      throws IOException {
  super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true),
        size,
        syncFlush);
  usesDefaultDeflater = true;
  ...
}


java komutu Native Memory Seçenekleri

Giriş
1. Uygulama -XX:NativeMemoryTracking=... şeklinde çalıştırılır
2. Uygulamaya jcmd ile Diagnostic Command Request gönderilir ve bir çıktı alınır

Native Memory allocations through JNI - Yani native Anahtar Kelimesi
Açıklaması şöyle. "Native memory" alanına erişmek yani C kodunu çağırmak için Java'daki native anahtar kelimesi kullanılır.
Native memory is memory allocated by the OS on behalf of the Java process through C code. This C code is called by native methods in certain Java classes.
Mesela java.util.zip paketindeki bazı kodlar şöyle
private static native void initIDs();
private native static long init(int level, int strategy, boolean nowrap);
private native static void setDictionary(long addr, byte[] b, int off, int len);
private native int deflateBytes(long addr, byte[] b, int off, int len,
                                  int flush);
private native static int getAdler(long addr);
private native static void reset(long addr);
private native static void end(long addr);
Neden Native Anahtar Kelimesi
Açıklaması şöyle. Sebep performans
The final possibility of native memory allocation from the JVM comes from libraries backed by native code. In some cases it makes more sense to implement functionality as native code, generated by compilers for languages such as C, C++ or Rust. Native code can perform better, or it might be the only way to access certain OS level functionality. Java allows calling native code through the Java Native Interface (JNI). Code called through JNI manages its own memory, so this memory is not tracked by the JVM and not automatically cleaned up through garbage collection. In a language like C, memory is managed by calling the malloc and free functions, which respectively request memory from and return memory to the OS. This is far from the complete picture, but more on that in the next level.
Native Memory Kategorileri
Açıklaması şöyle
Native memory consists of several native memory categories, such as: java heap, metaspace, thread etc.

The next table taken from Oracle’s site describes native memory categories used by NMT. Take into consideration that these categories may change with a release:
Şeklen şöyle

XX:NativeMemoryTracking seçeneği
Açıklaması şöyle. Bu seçeneği kullanınca JVM Off-heap kaynaklarını da takip etmeye başlar.
There are a few categories of native memory that the JVM can track by default, such as memory used by the garbage collector, thread stacks, loaded classes, and more. To enable JVM native memory tracking we simply pass it the -XX:NativeMemoryTracking=detail flag,
-XX:NativeMemoryTracking=... ile kullanılabilecek seçenekler şöyle
1. summary
2. detail
Örnek
Şöyle yaparız
java -XX:NativeMemoryTracking=detail -jar YourApp.jar
Örnek
Eğer testlerde kullanmak istersek şöyle yaparız
<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-surefire-plugin</artifactId>
      <configuration>
        <argLine>-XX:NativeMemoryTracking=detail</argLine>
      </configuration>
    </plugin>
  </plugins>
</build>
Açıklaması şöyle
Pay attention: Enabling NMT will result in a 5–10 percent JVM performance drop. By the way, NMT usage is also tracked by NMT.

NMT is not enabled by default. To enable this feature we need to add the following argument to the application’s JVM parameters: -XX:NativeMemoryTracking=summary

(to get a more detailed view of native memory usage, use: -XX:NativeMemoryTracking=detail)

To obtain the NMT details once the feature is enabled you should perform the following command:

jcmd <pid> VM.native_memory summary
‘<pid>’ is the PID of the application being analyzed

I ran this command manually several times and noticed a native memory category which was leaking, it was “serviceability”. After some research it was found out that there was a bug in 17.0.1 related to ThreadMXBean#dumpAllThreads method. Our application used that method. To fix the problem, I made some changes to avoid using that method (also found out that this bug was known and would be fixed in 17.0.2). After redeploying the fix and checking memory consumption, I was content, the issue disappeared.


9 Eylül 2022 Cuma

Stream.geneate metodu - Sonsuz Bir Stream Yaratır

Giriş
1. generate()  metodu elimizde bir Collection, dizi yok iken Stream yaratmak için kullanılır. 
2. Bu metod sonsuz bir Stream yarattığı için limit() ile sınırlandırmak gerekir.

Örnek
Elimizde şöyle bir kod olsun.
Stream.generate(() -> {
    System.out.println("generating...");
    return "hello!";
})
.limit(3)
.forEach(elem -> {
    System.out.println(elem);
});
Çıktı olarak şunu alırız.
generating...
hello!
generating...
hello!
generating...
hello!
Örnek
Şöyle yaparız
Stream.generate(() -> Boolean.FALSE).limit(100)
Örnek - Test Amaçlı Kullanım
Testlerde sahte veri üretmek için şöyle yaparız. Burada limit() ile sınırlama yok
private static void streamGenerate(){
  Supplier<UUID> supplier = () -> UUID.randomUUID();
  Stream<UUID> generate = Stream.generate(supplier);
  generate.forEach(a-> System.out.println(a));
}

private static void streamMessage(){
  AtomicInteger atomicInteger = new AtomicInteger();
  Supplier<Message> supplier = () -> {
    Message message = new Message(new Random().nextInt(), "Message : " +
      atomicInteger.getAndIncrement());
    return message;
  };

  Stream.generate(supplier)
    .forEach(a-> System.out.println("Message Published: " +a.toString()));
}

private static void streamMailId(long size) {
  List<String> domain = List.of("@gmail.com", "@Yahoo.com", "@outlook.com");

  Supplier<String> supplier = () ->{
    String userName = generateUserName();
    Random random = new Random();
    int index = random.nextInt(domain.size());
    return userName+domain.get(index);
  };

  Stream.generate(supplier).limit(size).forEach(a-> System.out.println(a));
}

7 Eylül 2022 Çarşamba

Lightrun

Giriş
Açıklaması şöyle
Adding real-time information to running applications is a hassle that many developers face. Lightrun helps address this problem by providing a suite of tools to incorporate snapshots, metrics, and code-level logs.

This plug-in can prove useful when deploying applications to production environments. The biggest benefit of using it is that it reduces the time spent on debugging. Being able to view logs in real time and evaluating expressions without the need to redeploy or recompile is beneficial to everyone on the dev team.
Snapshot
Açıklaması şöyle
Once we bind a snapshot there, we can detect the proxy types in the stack
Şeklen şöyle. Burada getTransactionManager metoduna snapshot konulmuş ve alttaki "Lightrun Snapshots" kutusunda Spring'e ait proxy'lerin de görülebilir.
Condition ekleme de Breakpoint Condition gibi. Şeklen şöyle



Log Ekleme
Açıklaması şöyle
Lightrun lets you add a new log to a production application without changing the source code. 
...

We can fill out the log statements in the dialog that prompts us. Notice we can use curly braces to write Java expressions, e.g. variable names, method calls, etc.

These expressions execute in a sandbox which guarantees that they will not affect the application state. The sandbox guarantees read only state!

Once we click OK, we can see the log appear in the IDE. Notice that no code changed, but this will act as if you wrote a logger statement in that line. So logs will be integrated with other logs.


Notice that we print both the statement and the arguments so the log output will include everything we need. You might be concerned that this weighs too heavily on the CPU and you would be right. Lightrun detects overuse of the CPU and suspends expensive operations temporarily to keep execution time in check. This prevents you from accidentally performing an overly expensive operation.