@@ -27,13 +27,17 @@ defmodule Cadet.Logger.CloudWatchLogger do
2727 @ impl true
2828 def init ( { __MODULE__ , opts } ) when is_list ( opts ) do
2929 config = configure_merge ( read_env ( ) , opts )
30- { :ok , init ( config , % __MODULE__ { } ) }
30+ state = init ( config , % __MODULE__ { } )
31+ ensure_log_stream_exists ( state . log_group , state . log_stream )
32+ { :ok , state }
3133 end
3234
3335 @ impl true
3436 def init ( { __MODULE__ , name } ) when is_atom ( name ) do
3537 config = read_env ( )
36- { :ok , init ( config , % __MODULE__ { } ) }
38+ state = init ( config , % __MODULE__ { } )
39+ ensure_log_stream_exists ( state . log_group , state . log_stream )
40+ { :ok , state }
3741 end
3842
3943 @ impl true
@@ -159,6 +163,65 @@ defmodule Cadet.Logger.CloudWatchLogger do
159163 end
160164 end
161165
166+ # Ensures the log stream exists, creates it if not
167+ # Returns :ok or :error
168+ # Uses ExAws.Logs.describe_log_streams and ExAws.Logs.create_log_stream
169+ # Assumes ExAws.Logs is available
170+
171+ defp ensure_log_stream_exists ( log_group , log_stream ) do
172+ describe_op = % ExAws.Operation.JSON {
173+ http_method: :post ,
174+ service: :logs ,
175+ headers: [
176+ { "x-amz-target" , "Logs_20140328.DescribeLogStreams" } ,
177+ { "content-type" , "application/x-amz-json-1.1" }
178+ ] ,
179+ data: % {
180+ "logGroupName" => log_group ,
181+ "logStreamNamePrefix" => log_stream
182+ }
183+ }
184+
185+ client = Application . get_env ( :ex_aws , :ex_aws_mock , ExAws )
186+
187+ case client . request ( describe_op ) do
188+ { :ok , % { "logStreams" => streams } } ->
189+ if Enum . any? ( streams , fn s -> s [ "logStreamName" ] == log_stream end ) do
190+ :ok
191+ else
192+ create_log_stream ( log_group , log_stream , client )
193+ end
194+
195+ { :error , reason } ->
196+ Logger . error ( "Failed to describe log streams: #{ inspect ( reason ) } " )
197+ :error
198+ end
199+ end
200+
201+ defp create_log_stream ( log_group , log_stream , client ) do
202+ create_op = % ExAws.Operation.JSON {
203+ http_method: :post ,
204+ service: :logs ,
205+ headers: [
206+ { "x-amz-target" , "Logs_20140328.CreateLogStream" } ,
207+ { "content-type" , "application/x-amz-json-1.1" }
208+ ] ,
209+ data: % {
210+ "logGroupName" => log_group ,
211+ "logStreamName" => log_stream
212+ }
213+ }
214+
215+ case client . request ( create_op ) do
216+ { :ok , _ } ->
217+ :ok
218+
219+ { :error , reason } ->
220+ Logger . error ( "Failed to create log stream: #{ inspect ( reason ) } " )
221+ :error
222+ end
223+ end
224+
162225 defp build_log_operation ( log_stream , log_group , buffer ) do
163226 # The headers and body structure can be found in the AWS API documentation:
164227 # https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_PutLogEvents.html
0 commit comments