AWS ALB의 Access log의 파서 프로그램입니다. 파이썬 버전이고 간혹 사용해서 메모 용도르 저장해둡니다.

 

import re

#참고
# 1) https://docs.aws.amazon.com/ko_kr/elasticloadbalancing/latest/application/load-balancer-access-logs.html
# 2) https://stackoverflow.com/questions/68875527/regex-for-python-based-logparser-for-printing-aws-elb-logs

fields = [ "type",
"time",
"elb",
"client_ip",
"client_port",
"target_ip",
"target_port",
"request_processing_time",
"target_processing_time",
"response_processing_time",
"elb_status_code",
"target_status_code",
"received_bytes",
"sent_bytes",
"request_type",
"request_url",
"request_protocol",
"user_agent_browser",
"ssl_cipher",
"ssl_protocol",
"target_group_arn",
"trace_id",
"domain_name",
"chosen_cert_arn",
"matched_rule_priority",
"request_creation_time",
"actions_executed",
"redirect_url",
"lambda_error_reason",
"target_port_list",
"target_status_code_list",
"classification",
"classification_reason" ]



field = str(input("what is the field needed? "))
regex = r'([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*):([0-9]*) ([^ ]*)[:-]([0-9]*) ([-.0-9]*) ([-.0-9]*) ([-.0-9]*) (|[-0-9]*) (-|[-0-9]*) ([-0-9]*) ([-0-9]*) \"([^ ]*) ([^ ]*) (- |[^ ]*)\" \"([^\"]*)\" ([A-Z0-9-]+) ([A-Za-z0-9.-]*) ([^ ]*) \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\" ([-.0-9]*) ([^ ]*) \"([^\"]*)\" \"([^\"]*)\" \"([^ ]*)\" \"([^\s]+?)\" \"([^\s]+)\" \"([^ ]*)\" \"([^ ]*)\"'

def ParseLogFile(file):
    resultDict = {}

    with open(file, 'r') as log:
        line = log.readline()
        while line:
            line_split = re.split(regex, line)
            line_split = line_split[1:len(line_split) - 1]
            index = fields.index(field)
            val = line_split[index]
            resultDict.setdefault(val, 0)
            resultDict[val] += 1
            line = log.readline()
        return resultDict
if __name__ == '__main__':
    result=ParseLogFile("C:\\HOME\\2.log")
    print(result)

자주 잊어버려서 메모

 

nginx location 기본 문법
 - https://lahuman.github.io/nginx_location_options/
-----

# 정확하게 일치 
location = / {
    [ configuration A ]
}

# 지정한 패턴으로 시작
location / {
    [ configuration B ]
}

# 지정한 패턴으로 시작
location /documents/ {
    [ configuration C ]
}

# 지정한 패턴으로 시작 패턴이 일치 하면 다른 패턴 탐색 중지( 정규식 아님 )
location ^~ /images/ {
    [ configuration D ]
}

# 정규식 표현 일치 - 대소문자 구분
location ~ \.(gif|jpg|jpeg)$ {
    [ configuration E ]
}

# 정규식 표현 일치 - 대소문자 구분 안함
location ~* \.(gif|jpg|jpeg)$ {
    [ configuration F ]
}

AWS 람다 + SNS조합해서 바운스된 이메일 DB구축 -> 서비스에서는 적절하게 로직/유저 메시지 처리해야함

 

관련해서 참고 링크

 - https://docs.aws.amazon.com/ses/latest/dg/notification-contents.html

 - 바운스되는 종류(bounce type): https://docs.aws.amazon.com/ses/latest/dg/notification-contents.html#bounce-types

  => 케이스별로 적절하게 로직처리(예. MailboxFull이면 유저에게 메일함이  꽉 찾는지 확인해서 조치요청 UI)

 

 

추가글 참고
- https://blog.eomsh.com/199

'AWS > ' 카테고리의 다른 글

CloudWatch 인스턴스의 메모리 및 디스크 Matrix 추가  (0) 2016.08.07

자동화를 위해서 애플 앱스토어의 여러 기능을 개발할 수 있습니다.(애플에서 API일부를 제공해줘서)

 

그 중 앱의 IAP 리스트를 조회하는 API샘플입니다.

 - 주의: API는 호출양 제한이 걸려있습니다.(링크 참고)

 

List All In-App Purchases for an App

  - https://developer.apple.com/documentation/appstoreconnectapi/list_all_in-app_purchases_for_an_app

 

java 샘플 소스

 - git 주소: https://github.com/oshnew/spring-boot-ver2-study/commit/b04e4293e983bf7425be17a97aaac6c80f70a26b

import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import sample.apple.AppStoreConnectApi.AppStoreConnectApiJWT;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * 특정 애플 앱의 IAP로 등록된 상품 리스트 조회
 *  - 참고: https://developer.apple.com/documentation/appstoreconnectapi/list_all_in-app_purchases_for_an_app
 *
 * @author
 */
public class ListInAppPurchasesForAnApp {

	public static void main(String[] args) throws IOException {

		final String issuer = "입력필요";
		final String keyIdentifier = "입력필요"; //전달받은 사설키의 키 ID
		final String privateKeyFilePath = "입력필요"; //사설키 경로(제품개발 권한 액세스). 애플 앱스토어 웹 콘솔에서 다운로드 받음. 키에 허용권한(ACCOUNT_HOLDER, ADMIN, APP_MANAGER 중 1가지) 필요

		int expireAfterMinutes = 20; //20분 넘으면 안됨

		AppStoreConnectApiJWT clzJWT = new AppStoreConnectApiJWT();
		final String jwt = clzJWT.makeApiAuthJwt(issuer, keyIdentifier, expireAfterMinutes, privateKeyFilePath); //인증용 JWT생성

		System.out.println("인증용 JWT: " + jwt);

		OkHttpClient client = new OkHttpClient.Builder().readTimeout(4, TimeUnit.SECONDS).connectTimeout(1, TimeUnit.SECONDS).writeTimeout(5, TimeUnit.SECONDS).build();

		final String id = "입력필요"; //애플 앱스토어 웹 콘솔에서 'Apple ID'로 표시되는 부분, 앱의 구분용ID로 추정됨
		String prefixUri = String.format("https://api.appstoreconnect.apple.com/v1/apps/%s/inAppPurchasesV2", id);

		HttpUrl.Builder httpBuilder = HttpUrl.get(prefixUri).newBuilder();
		httpBuilder.addQueryParameter("limit", "200"); //최대 200건까지 API에서 제약됨
		httpBuilder.addQueryParameter("filter[inAppPurchaseType]", "NON_CONSUMABLE"); //비 소모성만 조회하기 필터링

		final String fullUrl = httpBuilder.build().toString();
		System.out.println("fullrUrl: " + fullUrl);

		Request request = new Request.Builder().addHeader("Authorization", "Bearer " + jwt).url(fullUrl).build();
		Response response = client.newCall(request).execute();

		if (response.isSuccessful()) {
			String rtnMsg = response.body().string();
			System.out.println(String.format("성공. 응답 msg => '%s", rtnMsg));
		} else {
			System.out.println(String.format("응답에러(200이 아님). 응답 code:'%s'\n errMsg:'%s'", response.code(), response.body().string()));
		}

	}
}

 

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.tomcat.util.codec.binary.Base64;

import java.io.BufferedReader;
import java.io.FileReader;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 애플 App Store Connect API에서 사용할 인증용 JWT토큰을 생성
 *
 * @author
 */
public class AppStoreConnectApiJWT {

	/**
	 * 애플 App Store Connect API에서 사용할 인증용 JWT토큰을 생성하는 샘플 소스
	 * - 참고: https://developer.apple.com/documentation/appstoreconnectapi/generating_tokens_for_api_requests
	 *
	 * @param issuer Your issuer ID from the API Keys page in App Store Connect; for example, 57246542-96fe-1a63-e053-0824d011072a.
	 * @param keyIdentifier
	 * @param expireAfterMinutes
	 * @param privateKeyFilePath
	 * @return
	 */
	public String makeApiAuthJwt(String issuer, String keyIdentifier, int expireAfterMinutes, String privateKeyFilePath) {

		if (expireAfterMinutes > 20) {
			throw new IllegalArgumentException(
				"expireAfterMinutes는 20보다 작아야합니다. 참고: https://developer.apple.com/documentation/appstoreconnectapi/generating_tokens_for_api_requests");
		}

		final String strPrivateKey = readPrivateKeyBody(privateKeyFilePath);
		PrivateKey privateKeyObj = convertToPrivateKeyObj(strPrivateKey);

		Map<String, Object> header = new HashMap<>();
		header.put("alg", SignatureAlgorithm.ES256);
		header.put("kid", keyIdentifier);
		header.put("typ", "JWT");

		final Date now = new Date();

		//주의: 일반적으로 만료시간이 20분보다 크면 애플에서 거부함. https://developer.apple.com/documentation/appstoreconnectapi/generating_tokens_for_api_requests#3878467
		LocalDateTime expLdt = LocalDateTime.ofInstant(now.toInstant(), ZoneId.systemDefault()).plusMinutes(10);
		Date expiredAt = java.sql.Timestamp.valueOf(expLdt);

		// @formatter:off
		String jwt =  Jwts.builder()
		.setHeader(header)
		.setIssuer(issuer)
		.setAudience("appstoreconnect-v1") //애플 API정의서
		.setIssuedAt(now)  //발행 시간
		.setExpiration(expiredAt) //만료시간
		.signWith(SignatureAlgorithm.ES256, privateKeyObj)
		.compact();

		// @formatter:on

		return jwt;
	}

	private static PrivateKey convertToPrivateKeyObj(String strPrivateKey) {

		try {
			byte[] encodedKey = Base64.decodeBase64(strPrivateKey);
			return KeyFactory.getInstance("EC").generatePrivate(new PKCS8EncodedKeySpec(encodedKey));
		} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
			throw new RuntimeException(e.getMessage(), e);
		}
	}

	/**
	 * private key 내용을 얻어옴
	 *  -  -----BEGIN PRIVATE KEY----- 또는 -----END PRIVATE KEY----- 와 같은 가이드라인 줄은 제외하고 실제 사용하는 부분만 파일에서 가져옴
	 *
	 * @param filePath
	 * @return
	 */
	private String readPrivateKeyBody(String filePath) {

		try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {

			String line;
			StringBuilder sb = new StringBuilder();
			while ((line = br.readLine()) != null) {
				if (line.contains("PRIVATE KEY")) { //guard line은 pass
					continue;
				}
				sb.append(line);
			}

			return sb.toString();

		} catch (Exception e) {
			throw new RuntimeException(e.getMessage(), e);
		}
	}
}

 

java 11 vs 17 성능 관련 자료 정리(작성 중)

 

 

참고 자료

  1. https://www.optaplanner.org/blog/2021/09/15/HowMuchFasterIsJava17.html

headless CMS란

 - https://business.adobe.com/kr/glossary/headless-cms.html

 

best-headless-cms-2022

 - https://www.izooto.com/blog/best-headless-cms-2022

 

Site Generators(비교)
 - https://jamstack.org/generators/


Publii - Static-Site CMS (데스크탑 설치형 CMS 오픈소스)

 - https://news.hada.io/topic?id=7068
 - https://github.com/GetPublii/Publii

서비스를 보호하기 위한 요청 양을 제한하는 몇가지 방법이 있습니다.

그 중 bucket4j를 이용한 방법 몇가지를 간략히 메모해두겠습니다.

 

우선 참고 링크들

 

POC 테스트 목적의 간단히 개발한 코드

 - https://github.com/oshnew/spring-boot-ver2-study/blob/master/src/main/java/com/biz/app/ratelimit/RateLimitTestController.java

 

주의: 러프하게 정리 중인 자료인데 마무리가 안 되어 있어서 잘못된 내용이 있을 수 있습니다.

 

 

----

개발 중에 대기열 시스템이 필요한 경우가 종종 있습니다.

관련 내용을 간략하게 메모 목적으로 정리해둡니다.

 

1. 만들려고 하는 대기열 시스템의 개략적인 내용

  - 좀 된 자료로서 몇가지는 변경이 필요(예. vert.x대신 armeira등)

대기열 시스템 개발 설계 요약

2. 기타 참고할만한 내용들 메모

 - https://fr.slideshare.net/devcatpublications/ndc2019-142692683

 - 내용 중 조금 수정/고려해야할 부분이 있어보임(ex. 대기번호를 매번 보내서 비교를 안해도 되는 방법 고민? 등)

 

 - https://www.cloudflare.com/ko-kr/application-services/products/waiting-room/

+ Recent posts