// Path: telemetry-lib/src/main/java/com/yammer/telemetry/tracing/AsynchronousSpanSink.java
// public class AsynchronousSpanSink implements SpanSink {
//     private final ExecutorService executor;
//     private final JobFactory jobFactory;
// 
//     public AsynchronousSpanSink(JobFactory jobFactory) {
//         this(Executors.newSingleThreadExecutor(), jobFactory);
//     }
// 
//     public AsynchronousSpanSink(ExecutorService executor, JobFactory jobFactory) {
//         this.executor = executor;
//         this.jobFactory = jobFactory;
//     }
// 
//     @Override
//     public void record(SpanData spanData) {
//         Runnable job = jobFactory.createJob(spanData);
//         executor.execute(job);
//     }
// 
//     /**
//      * Shutdown the underlying executor in a graceful manner.
//      *
//      * @param timeout grace period for the shutdown to happen within
//      * @param timeunit timeunit for grace period
//      * @return the number of tasks remaining if executor was forcefully killed.
//      */
//     public int shutdown(long timeout, TimeUnit timeunit) {
//         try {
//             executor.shutdown();
//             if (executor.awaitTermination(timeout, timeunit)) {
//                 return 0;
//             }
//         } catch (InterruptedException ignore) {
//         }
// 
//         return executor.shutdownNow().size();
//     }
// 
//     public static interface JobFactory {
//         Runnable createJob(SpanData data);
//     }
// }
// 
// Path: telemetry-lib/src/main/java/com/yammer/telemetry/tracing/SpanData.java
// @SuppressWarnings("UnusedDeclaration")
// public interface SpanData {
//     BigInteger getTraceId();
// 
//     BigInteger getSpanId();
// 
//     Optional<BigInteger> getParentSpanId();
// 
//     String getName();
// 
//     String getHost();
// 
//     long getStartTime();
// 
//     long getDuration();
// 
//     List<AnnotationData> getAnnotations();
// }


import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.datatype.guava.GuavaModule;
import com.yammer.telemetry.tracing.AsynchronousSpanSink;
import com.yammer.telemetry.tracing.SpanData;
import java.io.*;
import java.nio.charset.Charset;
import java.util.logging.Logger;
package com.yammer.telemetry.tracing.logging;



public class LogJobFactory implements AsynchronousSpanSink.JobFactory {
    private static final Logger LOG = Logger.getLogger(LogJob.class.getName());

    private final WriterProvider writerProvider;
    private ObjectMapper objectMapper;

    private LogJobFactory(WriterProvider writerProvider) {
        this.writerProvider = writerProvider;
        this.objectMapper = new ObjectMapper().setPropertyNamingStrategy(new PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy()).setSerializationInclusion(JsonInclude.Include.NON_NULL).registerModule(new GuavaModule());
    }

    public static LogJobFactory withWriter(final Writer writer) {
        if (writer == null) throw new NullPointerException("Writer must not be null");
        return withWriterProvider(new WriterProvider() {
            @Override
            public Writer getWriter() throws IOException {
                return writer;
            }
        });
    }

    public static LogJobFactory withFile(final String file) throws IOException {
        // We try and open the file for append to get early warning of misconfiguration, it will fail is file is not
        // writable.
        try (FileOutputStream ignored = new FileOutputStream(file, true)) {
            return withWriterProvider(new WriterProvider() {
                @Override
                public Writer getWriter() throws IOException {
                    return new OutputStreamWriter(new FileOutputStream(file, true), Charset.forName("UTF-8").newEncoder());
                }
            });
        }
    }

    @Override
// Path: telemetry-lib/src/main/java/com/yammer/telemetry/tracing/AsynchronousSpanSink.java
// public class AsynchronousSpanSink implements SpanSink {
//     private final ExecutorService executor;
//     private final JobFactory jobFactory;
// 
//     public AsynchronousSpanSink(JobFactory jobFactory) {
//         this(Executors.newSingleThreadExecutor(), jobFactory);
//     }
// 
//     public AsynchronousSpanSink(ExecutorService executor, JobFactory jobFactory) {
//         this.executor = executor;
//         this.jobFactory = jobFactory;
//     }
// 
//     @Override
//     public void record(SpanData spanData) {
//         Runnable job = jobFactory.createJob(spanData);
//         executor.execute(job);
//     }
// 
//     /**
//      * Shutdown the underlying executor in a graceful manner.
//      *
//      * @param timeout grace period for the shutdown to happen within
//      * @param timeunit timeunit for grace period
//      * @return the number of tasks remaining if executor was forcefully killed.
//      */
//     public int shutdown(long timeout, TimeUnit timeunit) {
//         try {
//             executor.shutdown();
//             if (executor.awaitTermination(timeout, timeunit)) {
//                 return 0;
//             }
//         } catch (InterruptedException ignore) {
//         }
// 
//         return executor.shutdownNow().size();
//     }
// 
//     public static interface JobFactory {
//         Runnable createJob(SpanData data);
//     }
// }
// 
// Path: telemetry-lib/src/main/java/com/yammer/telemetry/tracing/SpanData.java
// @SuppressWarnings("UnusedDeclaration")
// public interface SpanData {
//     BigInteger getTraceId();
// 
//     BigInteger getSpanId();
// 
//     Optional<BigInteger> getParentSpanId();
// 
//     String getName();
// 
//     String getHost();
// 
//     long getStartTime();
// 
//     long getDuration();
// 
//     List<AnnotationData> getAnnotations();
// }


// Path: telemetry-lib/src/main/java/com/yammer/telemetry/tracing/logging/LogJobFactory.java
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.datatype.guava.GuavaModule;
import com.yammer.telemetry.tracing.AsynchronousSpanSink;
import com.yammer.telemetry.tracing.SpanData;
import java.io.*;
import java.nio.charset.Charset;
import java.util.logging.Logger;

package com.yammer.telemetry.tracing.logging;



public class LogJobFactory implements AsynchronousSpanSink.JobFactory {
    private static final Logger LOG = Logger.getLogger(LogJob.class.getName());

    private final WriterProvider writerProvider;
    private ObjectMapper objectMapper;

    private LogJobFactory(WriterProvider writerProvider) {
        this.writerProvider = writerProvider;
        this.objectMapper = new ObjectMapper().setPropertyNamingStrategy(new PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy()).setSerializationInclusion(JsonInclude.Include.NON_NULL).registerModule(new GuavaModule());
    }

    public static LogJobFactory withWriter(final Writer writer) {
        if (writer == null) throw new NullPointerException("Writer must not be null");
        return withWriterProvider(new WriterProvider() {
            @Override
            public Writer getWriter() throws IOException {
                return writer;
            }
        });
    }

    public static LogJobFactory withFile(final String file) throws IOException {
        // We try and open the file for append to get early warning of misconfiguration, it will fail is file is not
        // writable.
        try (FileOutputStream ignored = new FileOutputStream(file, true)) {
            return withWriterProvider(new WriterProvider() {
                @Override
                public Writer getWriter() throws IOException {
                    return new OutputStreamWriter(new FileOutputStream(file, true), Charset.forName("UTF-8").newEncoder());
                }
            });
        }
    }

    @Override
    public Runnable createJob(SpanData data) {